From 5b2619243a984dd8a2bac2931be0f362e9d42c51 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 14 Dec 2023 01:30:48 +0300 Subject: [PATCH] Fixed several LLVM loader bugs --- ir.h | 1 + ir_load_llvm.c | 51 +++++++++++++++++++++++++++++++++++--------------- ir_main.c | 32 +++++++++++++++++++++++++++++-- 3 files changed, 67 insertions(+), 17 deletions(-) diff --git a/ir.h b/ir.h index 8443514..666564c 100644 --- a/ir.h +++ b/ir.h @@ -798,6 +798,7 @@ struct _ir_loader { uint32_t flags, ir_type ret_type, uint32_t params_count, const uint8_t *param_types); bool (*sym_dcl) (ir_loader *loader, const char *name, uint32_t flags, size_t size, bool has_data); bool (*sym_data) (ir_loader *loader, ir_type type, uint32_t count, const void *data); + bool (*sym_data_pad) (ir_loader *loader, size_t offset); bool (*sym_data_ref) (ir_loader *loader, ir_op op, const char *ref); bool (*sym_data_end) (ir_loader *loader); bool (*func_init) (ir_loader *loader, ir_ctx *ctx, const char *name); diff --git a/ir_load_llvm.c b/ir_load_llvm.c index 5594b14..433c4bd 100644 --- a/ir_load_llvm.c +++ b/ir_load_llvm.c @@ -47,7 +47,6 @@ static ir_type llvm2ir_type(LLVMTypeRef type) case 32: return IR_I32; case 64: return IR_I64; default: - IR_ASSERT(0); break; } break; @@ -152,8 +151,9 @@ static ir_ref llvm2ir_op(ir_ctx *ctx, LLVMValueRef op, ir_type type) ir_ref proto; ir_val val; char buf[256]; + LLVMValueKind kind = LLVMGetValueKind(op); - switch (LLVMGetValueKind(op)) { + switch (kind) { case LLVMConstantIntValueKind: IR_ASSERT(IR_IS_TYPE_INT(type)); if (IR_IS_TYPE_SIGNED(type)) { @@ -201,9 +201,12 @@ static ir_ref llvm2ir_op(ir_ctx *ctx, LLVMValueRef op, ir_type type) name = LLVMGetValueName2(op, &name_len); return ir_const_func(ctx, ir_strl(ctx, name, name_len), proto); case LLVMUndefValueValueKind: + case LLVMPoisonValueValueKind: + // TODO: ??? val.u64 = 0; return ir_const(ctx, val, type); default: + fprintf(stderr, "Unsupported LLVM value kind: %d\n", kind); IR_ASSERT(0); return 0; } @@ -522,6 +525,9 @@ static ir_ref llvm2ir_intrinsic(ir_ctx *ctx, LLVMValueRef insn, LLVMTypeRef ftyp } else if (STR_START(name, name_len, "llvm.dbg.")) { /* skip */ return IR_NULL; + } else if (STR_EQUAL(name, name_len, "llvm.experimental.noalias.scope.decl")) { + /* skip */ + return IR_NULL; } else if (STR_EQUAL(name, name_len, "llvm.assume")) { /* skip */ return IR_NULL; @@ -1127,10 +1133,8 @@ static ir_ref llvm2ir_const_element_ptr(ir_ctx *ctx, LLVMValueRef expr) type_kind = LLVMGetTypeKind(type); IR_ASSERT(type_kind == LLVMPointerTypeKind); - if (LLVMGetValueKind(op0) == LLVMGlobalVariableValueKind) { - type = LLVMGlobalGetValueType(op0); - type_kind = LLVMGetTypeKind(type); - } + type = LLVMGetGEPSourceElementType(expr); + type_kind = LLVMGetTypeKind(type); op = LLVMGetOperand(expr, 1); IR_ASSERT(LLVMGetValueKind(op) == LLVMConstantIntValueKind); @@ -1932,7 +1936,7 @@ static int llvm2ir_forward_func(ir_loader *loader, const char *name, LLVMValueRe return loader->forward_func_dcl(loader, name, flags, ret_type, count, param_types); } -static int llvm2ir_data(ir_loader *loader, LLVMTargetDataRef target_data, LLVMTypeRef type, LLVMValueRef op) +static int llvm2ir_data(ir_loader *loader, LLVMTargetDataRef target_data, LLVMTypeRef type, LLVMValueRef op, size_t pos) { LLVMTypeRef el_type; LLVMValueRef el; @@ -1944,6 +1948,7 @@ static int llvm2ir_data(ir_loader *loader, LLVMTargetDataRef target_data, LLVMTy size_t name_len; char buf[256]; void *p = NULL; + size_t offset, el_size; LLVMValueKind kind = LLVMGetValueKind(op); switch (kind) { @@ -1981,22 +1986,27 @@ static int llvm2ir_data(ir_loader *loader, LLVMTargetDataRef target_data, LLVMTy case LLVMConstantArrayValueKind: case LLVMConstantDataArrayValueKind: el_type = LLVMGetElementType(type); + el_size = LLVMABISizeOfType(target_data, el_type); len = LLVMGetArrayLength(type); + offset = 0; for (i = 0; i < len; i++) { el = LLVMGetAggregateElement(op, i); - if (!llvm2ir_data(loader, target_data, el_type, el)) { + if (!llvm2ir_data(loader, target_data, el_type, el, pos)) { return 0; } + pos += el_size; } return 1; case LLVMConstantStructValueKind: len = LLVMCountStructElementTypes(type); for (i = 0; i < len; i++) { - // TODO: support for offset and alignment - // offset = LLVMOffsetOfElement(target_data, type, i); + offset = LLVMOffsetOfElement(target_data, type, i); + if (i > 0 && loader->sym_data_pad) { + loader->sym_data_pad(loader, pos + offset); + } el_type = LLVMStructGetTypeAtIndex(type, i); el = LLVMGetAggregateElement(op, i); - if (!llvm2ir_data(loader, target_data, el_type, el)) { + if (!llvm2ir_data(loader, target_data, el_type, el, pos + offset)) { return 0; } } @@ -2038,9 +2048,20 @@ static int llvm2ir_data(ir_loader *loader, LLVMTargetDataRef target_data, LLVMTy // case LLVMConstantExprValueKind: // IR_ASSERT(0); // return 0; -// case LLVMUndefValueValueKind: -// IR_ASSERT(0); -// return 0; + case LLVMUndefValueValueKind: + case LLVMPoisonValueValueKind: + // TODO: ??? + if (LLVMGetTypeKind(type) == LLVMArrayTypeKind) { + el_type = LLVMGetElementType(type); + len = LLVMGetArrayLength(type); + t = llvm2ir_type(el_type); + val.i64 = 0; + return loader->sym_data(loader, t, len, &val.i64); + } else { + t = llvm2ir_type(type); + val.i64 = 0; + return loader->sym_data(loader, t, 1, &val.i64); + } default: fprintf(stderr, "Unsupported LLVM value kind: %d\n", kind); IR_ASSERT(0); @@ -2125,7 +2146,7 @@ static int ir_load_llvm_module(ir_loader *loader, LLVMModuleRef module) return 0; } if (has_data) { - llvm2ir_data(loader, target_data, type, init); + llvm2ir_data(loader, target_data, type, init, 0); if (!loader->sym_data_end(loader)) { return 0; } diff --git a/ir_main.c b/ir_main.c index 201bba0..e8e0834 100644 --- a/ir_main.c +++ b/ir_main.c @@ -253,6 +253,7 @@ typedef struct _ir_main_loader { ir_strtab symtab; ir_sym *sym; ir_ref sym_count; + void *data_start; void *data; ir_code_buffer code_buffer; } ir_main_loader; @@ -456,7 +457,7 @@ static bool ir_loader_sym_dcl(ir_loader *loader, const char *name, uint32_t flag } memset(data, 0, size); if (has_data) { - l->data = data; + l->data_start = l->data = data; } if (l->dump_asm) { ir_disasm_add_symbol(name, (uintptr_t)data, size); @@ -514,13 +515,39 @@ static bool ir_loader_sym_data(ir_loader *loader, ir_type type, uint32_t count, if (!l->data) { return 0; } - // TODO: alignement memcpy(l->data, data, size); l->data = (void*)((uintptr_t)l->data + size); } return 1; } +static bool ir_loader_sym_data_pad(ir_loader *loader, size_t offset) +{ + ir_main_loader *l = (ir_main_loader*) loader; + size_t i; + + IR_ASSERT(offset >= (size_t)((char*)l->data - (char*)l->data_start)); + offset -= (char*)l->data - (char*)l->data_start; + if (offset) { + if ((l->dump & IR_DUMP_SAVE) && (l->dump_file)) { + for (i = 0; i < offset; i++) { + fprintf(l->dump_file, "\tuint8_t 0x00,\n"); + } + } + if (l->c_file) { + // TODO: + } + if (l->llvm_file) { + // TODO: + } + if (l->dump_asm || l->dump_size || l->run) { + memset(l->data, 0, offset); + l->data = (void*)((uintptr_t)l->data + offset); + } + } + return 1; +} + static bool ir_loader_sym_data_ref(ir_loader *loader, ir_op op, const char *ref) { ir_main_loader *l = (ir_main_loader*) loader; @@ -943,6 +970,7 @@ int main(int argc, char **argv) loader.loader.forward_func_dcl = ir_loader_forward_func_dcl; loader.loader.sym_dcl = ir_loader_sym_dcl; loader.loader.sym_data = ir_loader_sym_data; + loader.loader.sym_data_pad = ir_loader_sym_data_pad; loader.loader.sym_data_ref = ir_loader_sym_data_ref; loader.loader.sym_data_end = ir_loader_sym_data_end; loader.loader.func_init = ir_loader_func_init;