diff --git a/src/frontends/llvm/l2s.c b/src/frontends/llvm/l2s.c index bf009334f..822b5105b 100644 --- a/src/frontends/llvm/l2s.c +++ b/src/frontends/llvm/l2s.c @@ -36,7 +36,8 @@ static bool cmp_opaque_ptr(OpaqueRef* a, OpaqueRef* b) { KeyHash hash_node(Node**); bool compare_node(Node**, Node**); -static const Node* write_bb_tail(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVMBasicBlockRef bb, LLVMValueRef first_instr) { +static const Node* write_bb_tail(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, LLVMBasicBlockRef bb, LLVMValueRef first_instr) { + BodyBuilder* b = begin_body(fn_or_bb->arena); LLVMValueRef instr; for (instr = first_instr; instr; instr = LLVMGetNextInstruction(instr)) { bool last = instr == LLVMGetLastInstruction(bb); @@ -44,7 +45,7 @@ static const Node* write_bb_tail(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM assert(LLVMGetBasicBlockTerminator(bb) == instr); // LLVMDumpValue(instr); // printf("\n"); - EmittedInstr emitted = convert_instruction(p, fn_or_bb, b, instr); + EmittedInstr emitted = convert_instruction(p, fn_ctx, fn_or_bb, b, instr); if (emitted.terminator) return finish_body(b, emitted.terminator); if (!emitted.instruction) @@ -65,7 +66,7 @@ typedef struct { Node* nbb; } TodoBB; -static TodoBB prepare_bb(Parser* p, Node* fn, LLVMBasicBlockRef bb) { +static TodoBB prepare_bb(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb) { IrArena* a = get_module_arena(p->dst); debug_print("l2s: preparing BB %s %d\n", LLVMGetBasicBlockName(bb), bb); if (get_log_level() <= DEBUG) @@ -92,9 +93,9 @@ static TodoBB prepare_bb(Parser* p, Node* fn, LLVMBasicBlockRef bb) { String name = LLVMGetBasicBlockName(bb); if (!name || strlen(name) == 0) name = unique_name(a, "bb"); - Node* nbb = basic_block(a, fn, params, name); + Node* nbb = basic_block(a, fn_ctx->fn, params, name); insert_dict(LLVMValueRef, const Node*, p->map, bb, nbb); - insert_dict(const Node*, struct List*, p->phis, nbb, phis); + insert_dict(const Node*, struct List*, fn_ctx->phis, nbb, phis); TodoBB todo = { .bb = bb, .instr = instr, @@ -106,15 +107,14 @@ static TodoBB prepare_bb(Parser* p, Node* fn, LLVMBasicBlockRef bb) { } } -const Node* convert_basic_block(Parser* p, Node* fn, LLVMBasicBlockRef bb) { +const Node* convert_basic_block(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb) { IrArena* a = get_module_arena(p->dst); const Node** found = find_value_dict(LLVMValueRef, const Node*, p->map, bb); if (found) return *found; // assert(false); - TodoBB todo = prepare_bb(p, fn, bb); - BodyBuilder* bb_bb = begin_body(a); - todo.nbb->payload.basic_block.body = write_bb_tail(p, todo.nbb, bb_bb, todo.bb, todo.instr); + TodoBB todo = prepare_bb(p, fn_ctx, bb); + todo.nbb->payload.basic_block.body = write_bb_tail(p, fn_ctx, todo.nbb, todo.bb, todo.instr); return todo.nbb; } @@ -157,20 +157,33 @@ const Node* convert_function(Parser* p, LLVMValueRef fn) { break; } Node* f = function(p->dst, params, LLVMGetValueName(fn), annotations, fn_type->payload.fn_type.return_types); + FnParseCtx fn_parse_ctx = { + .fn = f, + .phis = new_dict(const Node*, struct List*, (HashFn) hash_node, (CmpFn) compare_node), + .jumps_todo = new_list(JumpTodo), + }; const Node* r = fn_addr_helper(a, f); insert_dict(LLVMValueRef, const Node*, p->map, fn, r); if (LLVMCountBasicBlocks(fn) > 0) { LLVMBasicBlockRef first_bb = LLVMGetEntryBasicBlock(fn); insert_dict(LLVMValueRef, const Node*, p->map, first_bb, f); - BodyBuilder* b = begin_body(a); - f->payload.fun.body = write_bb_tail(p, f, b, first_bb, LLVMGetFirstInstruction(first_bb)); + f->payload.fun.body = write_bb_tail(p, &fn_parse_ctx, f, first_bb, LLVMGetFirstInstruction(first_bb)); } - while (entries_count_list(p->jumps_todo) > 0) { - JumpTodo todo = pop_last_list(JumpTodo, p->jumps_todo); - convert_jump_finish(p, f, todo); + while (entries_count_list(fn_parse_ctx.jumps_todo) > 0) { + JumpTodo todo = pop_last_list(JumpTodo, fn_parse_ctx.jumps_todo); + convert_jump_finish(p, &fn_parse_ctx, todo); + } + { + size_t i = 0; + struct List* phis_list; + while (dict_iter(fn_parse_ctx.phis, &i, NULL, &phis_list)) { + destroy_list(phis_list); + } } + destroy_dict(fn_parse_ctx.phis); + destroy_list(fn_parse_ctx.jumps_todo); return r; } @@ -247,8 +260,6 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* .map = new_dict(LLVMValueRef, const Node*, (HashFn) hash_opaque_ptr, (CmpFn) cmp_opaque_ptr), .annotations = new_dict(LLVMValueRef, ParsedAnnotation, (HashFn) hash_opaque_ptr, (CmpFn) cmp_opaque_ptr), .scopes = new_dict(const Node*, Nodes, (HashFn) hash_node, (CmpFn) compare_node), - .phis = new_dict(const Node*, struct List*, (HashFn) hash_node, (CmpFn) compare_node), - .jumps_todo = new_list(JumpTodo), .annotations_arena = new_arena(), .src = src, .dst = dirty, @@ -283,15 +294,6 @@ bool parse_llvm_into_shady(const CompilerConfig* config, size_t len, const char* destroy_dict(p.map); destroy_dict(p.annotations); destroy_dict(p.scopes); - { - size_t i = 0; - struct List* phis_list; - while (dict_iter(p.phis, &i, NULL, &phis_list)) { - destroy_list(phis_list); - } - } - destroy_dict(p.phis); - destroy_list(p.jumps_todo); destroy_arena(p.annotations_arena); LLVMContextDispose(context); diff --git a/src/frontends/llvm/l2s_instr.c b/src/frontends/llvm/l2s_instr.c index fc4ece539..45c054c72 100644 --- a/src/frontends/llvm/l2s_instr.c +++ b/src/frontends/llvm/l2s_instr.c @@ -55,29 +55,30 @@ LLVMValueRef remove_ptr_bitcasts(Parser* p, LLVMValueRef v) { return v; } -static const Node* convert_jump_lazy(Parser* p, Node* fn, Node* fn_or_bb, LLVMBasicBlockRef dst) { - IrArena* a = fn->arena; - const Node* wrapper_bb = basic_block(a, fn, empty(a), NULL); +static const Node* convert_jump_lazy(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, LLVMBasicBlockRef dst) { + IrArena* a = fn_or_bb->arena; + const Node* wrapper_bb = basic_block(a, fn_ctx->fn, empty(a), NULL); JumpTodo todo = { .wrapper = wrapper_bb, .src = fn_or_bb, .dst = dst, }; - append_list(JumpTodo, p->jumps_todo, todo); + append_list(JumpTodo, fn_ctx->jumps_todo, todo); + convert_basic_block(p, fn_ctx, dst); return jump_helper(a, wrapper_bb, empty(a)); } -void convert_jump_finish(Parser* p, Node* fn, JumpTodo todo) { - IrArena* a = fn->arena; - const Node* dst_bb = convert_basic_block(p, fn, todo.dst); - BBPhis* phis = find_value_dict(const Node*, BBPhis, p->phis, dst_bb); +void convert_jump_finish(Parser* p, FnParseCtx* fn_ctx, JumpTodo todo) { + IrArena* a = fn_ctx->fn->arena; + const Node* dst_bb = convert_basic_block(p, fn_ctx, todo.dst); + BBPhis* phis = find_value_dict(const Node*, BBPhis, fn_ctx->phis, dst_bb); assert(phis); size_t params_count = entries_count_list(phis->list); LARRAY(const Node*, params, params_count); for (size_t i = 0; i < params_count; i++) { LLVMValueRef phi = read_list(LLVMValueRef, phis->list)[i]; for (size_t j = 0; j < LLVMCountIncoming(phi); j++) { - if (convert_basic_block(p, fn, LLVMGetIncomingBlock(phi, j)) == todo.src) { + if (convert_basic_block(p, fn_ctx, LLVMGetIncomingBlock(phi, j)) == todo.src) { params[i] = convert_value(p, LLVMGetIncomingValue(phi, j)); goto next; } @@ -98,13 +99,8 @@ static const Type* type_untyped_ptr(const Type* untyped_ptr_t, const Type* eleme } /// instr may be an instruction or a constantexpr -EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVMValueRef instr) { - Node* fn = fn_or_bb; - if (fn) { - if (fn_or_bb->tag == BasicBlock_TAG) - fn = (Node*) fn_or_bb->payload.basic_block.fn; - assert(fn->tag == Function_TAG); - } +EmittedInstr convert_instruction(Parser* p, FnParseCtx* fn_ctx, Node* fn_or_bb, BodyBuilder* b, LLVMValueRef instr) { + Node* fn = fn_ctx ? fn_ctx->fn : NULL; IrArena* a = get_module_arena(p->dst); int num_ops = LLVMGetNumOperands(instr); @@ -133,13 +129,13 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM if (!found) { Nodes str = scope_to_string(p, dbgloc); insert_dict(const Node*, Nodes, p->scopes, fn_or_bb, str); - debug_print("Found a debug location for "); - log_node(DEBUG, fn_or_bb); + debugv_print("Found a debug location for "); + log_node(DEBUGV, fn_or_bb); for (size_t i = 0; i < str.count; i++) { - log_node(DEBUG, str.nodes[i]); - debug_print(" -> "); + log_node(DEBUGV, str.nodes[i]); + debugv_print(" -> "); } - debug_print(" (depth= %zu)\n", str.count); + debugv_print(" (depth= %zu)\n", str.count); } } } @@ -162,26 +158,26 @@ EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVM return (EmittedInstr) { .terminator = branch(a, (Branch) { .branch_condition = condition, - .true_jump = convert_jump_lazy(p, fn, fn_or_bb, targets[0]), - .false_jump = convert_jump_lazy(p, fn, fn_or_bb, targets[1]), + .true_jump = convert_jump_lazy(p, fn_ctx, fn_or_bb, targets[0]), + .false_jump = convert_jump_lazy(p, fn_ctx, fn_or_bb, targets[1]), }) }; } else { assert(n_targets == 1); return (EmittedInstr) { - .terminator = convert_jump_lazy(p, fn, fn_or_bb, targets[0]) + .terminator = convert_jump_lazy(p, fn_ctx, fn_or_bb, targets[0]) }; } } case LLVMSwitch: { const Node* inspectee = convert_value(p, LLVMGetOperand(instr, 0)); - const Node* default_jump = convert_jump_lazy(p, fn, fn_or_bb, LLVMGetOperand(instr, 1)); + const Node* default_jump = convert_jump_lazy(p, fn_ctx, fn_or_bb, LLVMGetOperand(instr, 1)); int n_targets = LLVMGetNumOperands(instr) / 2 - 1; LARRAY(const Node*, targets, n_targets); LARRAY(const Node*, literals, n_targets); for (size_t i = 0; i < n_targets; i++) { literals[i] = convert_value(p, LLVMGetOperand(instr, i * 2 + 2)); - targets[i] = convert_jump_lazy(p, fn, fn_or_bb, LLVMGetOperand(instr, i * 2 + 3)); + targets[i] = convert_jump_lazy(p, fn_ctx, fn_or_bb, LLVMGetOperand(instr, i * 2 + 3)); } return (EmittedInstr) { .terminator = br_switch(a, (Switch) { diff --git a/src/frontends/llvm/l2s_private.h b/src/frontends/llvm/l2s_private.h index 18c36ac47..24f2ab694 100644 --- a/src/frontends/llvm/l2s_private.h +++ b/src/frontends/llvm/l2s_private.h @@ -16,13 +16,17 @@ typedef struct { struct Dict* map; struct Dict* annotations; struct Dict* scopes; - struct Dict* phis; - struct List* jumps_todo; Arena* annotations_arena; LLVMModuleRef src; Module* dst; } Parser; +typedef struct { + Node* fn; + struct Dict* phis; + struct List* jumps_todo; +} FnParseCtx; + #ifndef LLVM_VERSION_MAJOR #error "Missing LLVM_VERSION_MAJOR" #else @@ -47,7 +51,7 @@ const Type* convert_type(Parser* p, LLVMTypeRef t); const Node* convert_metadata(Parser* p, LLVMMetadataRef meta); const Node* convert_global(Parser* p, LLVMValueRef global); const Node* convert_function(Parser* p, LLVMValueRef fn); -const Node* convert_basic_block(Parser* p, Node* fn, LLVMBasicBlockRef bb); +const Node* convert_basic_block(Parser* p, FnParseCtx* fn_ctx, LLVMBasicBlockRef bb); typedef struct { const Node* terminator; @@ -65,9 +69,8 @@ typedef struct { LLVMBasicBlockRef dst; } JumpTodo; -void convert_jump_finish(Parser* p, Node* fn, JumpTodo todo); - -EmittedInstr convert_instruction(Parser* p, Node* fn_or_bb, BodyBuilder* b, LLVMValueRef instr); +void convert_jump_finish(Parser* p, FnParseCtx*, JumpTodo todo); +EmittedInstr convert_instruction(Parser* p, FnParseCtx*, Node* fn_or_bb, BodyBuilder* b, LLVMValueRef instr); Nodes scope_to_string(Parser* p, LLVMMetadataRef dbgloc); diff --git a/src/frontends/llvm/l2s_value.c b/src/frontends/llvm/l2s_value.c index 495fe55c1..4d9a36284 100644 --- a/src/frontends/llvm/l2s_value.c +++ b/src/frontends/llvm/l2s_value.c @@ -85,7 +85,7 @@ const Node* convert_value(Parser* p, LLVMValueRef v) { r = ref_decl_helper(a, decl); insert_dict(LLVMTypeRef, const Type*, p->map, v, r); BodyBuilder* bb = begin_body(a); - EmittedInstr emitted = convert_instruction(p, NULL, bb, v); + EmittedInstr emitted = convert_instruction(p, NULL, NULL, bb, v); Nodes types = singleton(t); decl->payload.constant.instruction = bind_last_instruction_and_wrap_in_block_explicit_return_types(bb, emitted.instruction, &types); return r;