From 6898d26e8083900e5c61717de5dfb0edc409ebd9 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 6 Dec 2023 16:30:44 +0300 Subject: [PATCH] Allow code generation for functions with unesolved symbols --- ir_aarch64.dasc | 17 +++++++++++++++-- ir_emit.c | 1 + ir_main.c | 19 ++++++++++++++----- ir_x86.dasc | 16 ++++++++++++++-- 4 files changed, 44 insertions(+), 9 deletions(-) diff --git a/ir_aarch64.dasc b/ir_aarch64.dasc index 86b9cde..873dc27 100644 --- a/ir_aarch64.dasc +++ b/ir_aarch64.dasc @@ -1172,8 +1172,16 @@ static void ir_emit_load(ir_ctx *ctx, ir_type type, ir_reg reg, ir_ref src) if (IR_IS_TYPE_INT(type)) { ir_insn *insn = &ctx->ir_base[src]; - IR_ASSERT(insn->op != IR_STR && insn->op != IR_SYM && insn->op != IR_FUNC); - ir_emit_load_imm_int(ctx, type, reg, insn->val.i64); + if (insn->op == IR_SYM || insn->op == IR_FUNC) { + void *addr = (ctx->loader && ctx->loader->resolve_sym_name) ? + ctx->loader->resolve_sym_name(ctx->loader, ir_get_str(ctx, insn->val.name)) : + ir_resolve_sym_name(ir_get_str(ctx, insn->val.name)); + IR_ASSERT(addr); + ir_emit_load_imm_int(ctx, type, reg, (intptr_t)addr); + } else { + IR_ASSERT(insn->op != IR_STR); + ir_emit_load_imm_int(ctx, type, reg, insn->val.i64); + } } else { ir_emit_load_imm_fp(ctx, type, reg, src); } @@ -4306,6 +4314,7 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg void *addr = (ctx->loader && ctx->loader->resolve_sym_name) ? ctx->loader->resolve_sym_name(ctx->loader, ir_get_str(ctx, val_insn->val.name)) : ir_resolve_sym_name(ir_get_str(ctx, val_insn->val.name)); + IR_ASSERT(addr); ir_emit_load_imm_int(ctx, IR_ADDR, dst_reg, (intptr_t)addr); continue; } @@ -4335,6 +4344,7 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg void *addr = (ctx->loader && ctx->loader->resolve_sym_name) ? ctx->loader->resolve_sym_name(ctx->loader, ir_get_str(ctx, val_insn->val.name)) : ir_resolve_sym_name(ir_get_str(ctx, val_insn->val.name)); + IR_ASSERT(addr); ir_emit_load_imm_int(ctx, IR_ADDR, tmp_reg, (intptr_t)addr); | str Rx(tmp_reg), [sp, #stack_offset] } else { @@ -4387,6 +4397,7 @@ static void ir_emit_call_ex(ir_ctx *ctx, ir_ref def, ir_insn *insn, int32_t used addr = (ctx->loader && ctx->loader->resolve_sym_name) ? ctx->loader->resolve_sym_name(ctx->loader, ir_get_str(ctx, addr_insn->val.name)) : ir_resolve_sym_name(ir_get_str(ctx, addr_insn->val.name)); + IR_ASSERT(addr); } else { IR_ASSERT(addr_insn->op == IR_ADDR || addr_insn->op == IR_FUNC_ADDR); addr = (void*)addr_insn->val.addr; @@ -4472,6 +4483,7 @@ static void ir_emit_tailcall(ir_ctx *ctx, ir_ref def, ir_insn *insn) addr = (ctx->loader && ctx->loader->resolve_sym_name) ? ctx->loader->resolve_sym_name(ctx->loader, ir_get_str(ctx, addr_insn->val.name)) : ir_resolve_sym_name(ir_get_str(ctx, addr_insn->val.name)); + IR_ASSERT(addr); } else { IR_ASSERT(addr_insn->op == IR_ADDR || addr_insn->op == IR_FUNC_ADDR); addr = (void*)addr_insn->val.addr; @@ -4855,6 +4867,7 @@ static void ir_emit_exitcall(ir_ctx *ctx, ir_ref def, ir_insn *insn) addr = (ctx->loader && ctx->loader->resolve_sym_name) ? ctx->loader->resolve_sym_name(ctx->loader, ir_get_str(ctx, addr_insn->val.name)) : ir_resolve_sym_name(ir_get_str(ctx, addr_insn->val.name)); + IR_ASSERT(addr); } else { IR_ASSERT(addr_insn->op == IR_ADDR || addr_insn->op == IR_FUNC_ADDR); addr = (void*)addr_insn->val.addr; diff --git a/ir_emit.c b/ir_emit.c index 40ddf10..520d875 100644 --- a/ir_emit.c +++ b/ir_emit.c @@ -337,6 +337,7 @@ static void *ir_jmp_addr(ir_ctx *ctx, ir_insn *insn, ir_insn *addr_insn) addr = (ctx->loader && ctx->loader->resolve_sym_name) ? ctx->loader->resolve_sym_name(ctx->loader, ir_get_str(ctx, addr_insn->val.name)) : ir_resolve_sym_name(ir_get_str(ctx, addr_insn->val.name)); + IR_ASSERT(addr); } else { IR_ASSERT(addr_insn->op == IR_ADDR || addr_insn->op == IR_FUNC_ADDR); addr = (void*)addr_insn->val.addr; diff --git a/ir_main.c b/ir_main.c index 7186930..31b9a6f 100644 --- a/ir_main.c +++ b/ir_main.c @@ -231,6 +231,7 @@ int ir_compile_func(ir_ctx *ctx, int opt_level, uint32_t dump, FILE *dump_file, typedef struct _ir_sym { void *addr; + void *thunk_addr; } ir_sym; typedef struct _ir_main_loader { @@ -265,6 +266,9 @@ static bool ir_loader_add_sym(ir_loader *loader, const char *name, void *addr) if (addr && !l->sym[old_val].addr) { /* Update forward declaration */ l->sym[old_val].addr = addr; + if (l->sym[old_val].thunk_addr) { + // TODO: Fix thunk or relocation ??? + } return 1; } return 0; @@ -274,6 +278,7 @@ static bool ir_loader_add_sym(ir_loader *loader, const char *name, void *addr) l->sym = ir_mem_realloc(l->sym, sizeof(ir_sym) * l->sym_count); } l->sym[val].addr = addr; + l->sym[val].thunk_addr = NULL; return 1; } @@ -293,7 +298,15 @@ static void* ir_loader_resolve_sym_name(ir_loader *loader, const char *name) void *addr; if (val) { - return l->sym[val].addr; + if (l->sym[val].addr) { + return l->sym[val].addr; + } + if (!l->sym[val].thunk_addr) { + /* Undefined declaration */ + // TODO: Add thunk or relocation ??? + l->sym[val].thunk_addr = (void*)(intptr_t)sizeof(void*); + } + return l->sym[val].thunk_addr; } addr = ir_resolve_sym_name(name); ir_loader_add_sym(loader, name, addr); /* cache */ @@ -312,11 +325,9 @@ static bool ir_loader_external_sym_dcl(ir_loader *loader, const char *name, uint fprintf(l->dump_file, "extern %s %s;\n", (flags & IR_CONST) ? "const" : "var", name); } if (l->c_file) { - // TODO: ir_emit_c_sym_decl(name, flags | IR_EXTERN, 0, l->c_file); } if (l->llvm_file) { - // TODO: ir_emit_llvm_sym_decl(name, flags | IR_EXTERN, 0, l->llvm_file); } if (l->dump_asm || l->dump_size || l->run) { @@ -430,11 +441,9 @@ static bool ir_loader_sym_dcl(ir_loader *loader, const char *name, uint32_t flag fprintf(l->dump_file, "%s %s [%ld]%s\n", (flags & IR_CONST) ? "const" : "var", name, size, has_data ? " = {" : ";"); } if (l->c_file) { - // TODO: ir_emit_c_sym_decl(name, flags, has_data, l->c_file); } if (l->llvm_file) { - // TODO: ir_emit_llvm_sym_decl(name, flags, has_data, l->llvm_file); } if (l->dump_asm || l->dump_size || l->run) { diff --git a/ir_x86.dasc b/ir_x86.dasc index c9639f2..e10ea47 100644 --- a/ir_x86.dasc +++ b/ir_x86.dasc @@ -2145,8 +2145,16 @@ static void ir_emit_load(ir_ctx *ctx, ir_type type, ir_reg reg, ir_ref src) if (IR_IS_TYPE_INT(type)) { ir_insn *insn = &ctx->ir_base[src]; - IR_ASSERT(insn->op != IR_STR && insn->op != IR_SYM && insn->op != IR_FUNC); - ir_emit_load_imm_int(ctx, type, reg, insn->val.i64); + if (insn->op == IR_SYM || insn->op == IR_FUNC) { + void *addr = (ctx->loader && ctx->loader->resolve_sym_name) ? + ctx->loader->resolve_sym_name(ctx->loader, ir_get_str(ctx, insn->val.name)) : + ir_resolve_sym_name(ir_get_str(ctx, insn->val.name)); + IR_ASSERT(addr); + ir_emit_load_imm_int(ctx, type, reg, (intptr_t)addr); + } else { + IR_ASSERT(insn->op != IR_STR); + ir_emit_load_imm_int(ctx, type, reg, insn->val.i64); + } } else { ir_emit_load_imm_fp(ctx, type, reg, src); } @@ -7154,6 +7162,7 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg void *addr = (ctx->loader && ctx->loader->resolve_sym_name) ? ctx->loader->resolve_sym_name(ctx->loader, ir_get_str(ctx, val_insn->val.name)) : ir_resolve_sym_name(ir_get_str(ctx, val_insn->val.name)); + IR_ASSERT(addr); if (sizeof(void*) == 4 || IR_IS_SIGNED_32BIT(addr)) { | mov Ra(dst_reg), ((ptrdiff_t)addr) } else { @@ -7232,6 +7241,7 @@ static int32_t ir_emit_arguments(ir_ctx *ctx, ir_ref def, ir_insn *insn, ir_reg void *addr = (ctx->loader && ctx->loader->resolve_sym_name) ? ctx->loader->resolve_sym_name(ctx->loader, ir_get_str(ctx, val_insn->val.name)) : ir_resolve_sym_name(ir_get_str(ctx, val_insn->val.name)); + IR_ASSERT(addr); if (sizeof(void*) == 4) { | mov aword [Ra(IR_REG_RSP)+stack_offset], ((ptrdiff_t)addr) |.if X64 @@ -7351,6 +7361,7 @@ static void ir_emit_call_ex(ir_ctx *ctx, ir_ref def, ir_insn *insn, int32_t used addr = (ctx->loader && ctx->loader->resolve_sym_name) ? ctx->loader->resolve_sym_name(ctx->loader, ir_get_str(ctx, addr_insn->val.name)) : ir_resolve_sym_name(ir_get_str(ctx, addr_insn->val.name)); + IR_ASSERT(addr); } else { IR_ASSERT(addr_insn->op == IR_ADDR || addr_insn->op == IR_FUNC_ADDR); addr = (void*)addr_insn->val.addr; @@ -7505,6 +7516,7 @@ static void ir_emit_tailcall(ir_ctx *ctx, ir_ref def, ir_insn *insn) addr = (ctx->loader && ctx->loader->resolve_sym_name) ? ctx->loader->resolve_sym_name(ctx->loader, ir_get_str(ctx, addr_insn->val.name)) : ir_resolve_sym_name(ir_get_str(ctx, addr_insn->val.name)); + IR_ASSERT(addr); } else { IR_ASSERT(addr_insn->op == IR_ADDR || addr_insn->op == IR_FUNC_ADDR); addr = (void*)addr_insn->val.addr;