Skip to content

Commit

Permalink
fix LLVM front-end for the 10 trillionth time
Browse files Browse the repository at this point in the history
  • Loading branch information
Hugobros3 committed Apr 27, 2024
1 parent eb37f77 commit cc24ad2
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 58 deletions.
52 changes: 27 additions & 25 deletions src/frontends/llvm/l2s.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,16 @@ 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);
if (last)
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)
Expand All @@ -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)
Expand All @@ -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,
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down
48 changes: 22 additions & 26 deletions src/frontends/llvm/l2s_instr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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);
Expand Down Expand Up @@ -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);
}
}
}
Expand All @@ -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) {
Expand Down
15 changes: 9 additions & 6 deletions src/frontends/llvm/l2s_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion src/frontends/llvm/l2s_value.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit cc24ad2

Please sign in to comment.