Allow code generation for functions with unesolved symbols

This commit is contained in:
Dmitry Stogov 2023-12-06 16:30:44 +03:00
parent 2c67a3ac86
commit 6898d26e80
4 changed files with 44 additions and 9 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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;