mirror of
https://github.com/danog/ir.git
synced 2024-12-02 09:38:29 +01:00
Fixed several LLVM loader bugs
This commit is contained in:
parent
27f5e34d90
commit
5b2619243a
1
ir.h
1
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);
|
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_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) (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_ref) (ir_loader *loader, ir_op op, const char *ref);
|
||||||
bool (*sym_data_end) (ir_loader *loader);
|
bool (*sym_data_end) (ir_loader *loader);
|
||||||
bool (*func_init) (ir_loader *loader, ir_ctx *ctx, const char *name);
|
bool (*func_init) (ir_loader *loader, ir_ctx *ctx, const char *name);
|
||||||
|
@ -47,7 +47,6 @@ static ir_type llvm2ir_type(LLVMTypeRef type)
|
|||||||
case 32: return IR_I32;
|
case 32: return IR_I32;
|
||||||
case 64: return IR_I64;
|
case 64: return IR_I64;
|
||||||
default:
|
default:
|
||||||
IR_ASSERT(0);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -152,8 +151,9 @@ static ir_ref llvm2ir_op(ir_ctx *ctx, LLVMValueRef op, ir_type type)
|
|||||||
ir_ref proto;
|
ir_ref proto;
|
||||||
ir_val val;
|
ir_val val;
|
||||||
char buf[256];
|
char buf[256];
|
||||||
|
LLVMValueKind kind = LLVMGetValueKind(op);
|
||||||
|
|
||||||
switch (LLVMGetValueKind(op)) {
|
switch (kind) {
|
||||||
case LLVMConstantIntValueKind:
|
case LLVMConstantIntValueKind:
|
||||||
IR_ASSERT(IR_IS_TYPE_INT(type));
|
IR_ASSERT(IR_IS_TYPE_INT(type));
|
||||||
if (IR_IS_TYPE_SIGNED(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);
|
name = LLVMGetValueName2(op, &name_len);
|
||||||
return ir_const_func(ctx, ir_strl(ctx, name, name_len), proto);
|
return ir_const_func(ctx, ir_strl(ctx, name, name_len), proto);
|
||||||
case LLVMUndefValueValueKind:
|
case LLVMUndefValueValueKind:
|
||||||
|
case LLVMPoisonValueValueKind:
|
||||||
|
// TODO: ???
|
||||||
val.u64 = 0;
|
val.u64 = 0;
|
||||||
return ir_const(ctx, val, type);
|
return ir_const(ctx, val, type);
|
||||||
default:
|
default:
|
||||||
|
fprintf(stderr, "Unsupported LLVM value kind: %d\n", kind);
|
||||||
IR_ASSERT(0);
|
IR_ASSERT(0);
|
||||||
return 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.")) {
|
} else if (STR_START(name, name_len, "llvm.dbg.")) {
|
||||||
/* skip */
|
/* skip */
|
||||||
return IR_NULL;
|
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")) {
|
} else if (STR_EQUAL(name, name_len, "llvm.assume")) {
|
||||||
/* skip */
|
/* skip */
|
||||||
return IR_NULL;
|
return IR_NULL;
|
||||||
@ -1127,10 +1133,8 @@ static ir_ref llvm2ir_const_element_ptr(ir_ctx *ctx, LLVMValueRef expr)
|
|||||||
|
|
||||||
type_kind = LLVMGetTypeKind(type);
|
type_kind = LLVMGetTypeKind(type);
|
||||||
IR_ASSERT(type_kind == LLVMPointerTypeKind);
|
IR_ASSERT(type_kind == LLVMPointerTypeKind);
|
||||||
if (LLVMGetValueKind(op0) == LLVMGlobalVariableValueKind) {
|
type = LLVMGetGEPSourceElementType(expr);
|
||||||
type = LLVMGlobalGetValueType(op0);
|
type_kind = LLVMGetTypeKind(type);
|
||||||
type_kind = LLVMGetTypeKind(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
op = LLVMGetOperand(expr, 1);
|
op = LLVMGetOperand(expr, 1);
|
||||||
IR_ASSERT(LLVMGetValueKind(op) == LLVMConstantIntValueKind);
|
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);
|
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;
|
LLVMTypeRef el_type;
|
||||||
LLVMValueRef el;
|
LLVMValueRef el;
|
||||||
@ -1944,6 +1948,7 @@ static int llvm2ir_data(ir_loader *loader, LLVMTargetDataRef target_data, LLVMTy
|
|||||||
size_t name_len;
|
size_t name_len;
|
||||||
char buf[256];
|
char buf[256];
|
||||||
void *p = NULL;
|
void *p = NULL;
|
||||||
|
size_t offset, el_size;
|
||||||
LLVMValueKind kind = LLVMGetValueKind(op);
|
LLVMValueKind kind = LLVMGetValueKind(op);
|
||||||
|
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
@ -1981,22 +1986,27 @@ static int llvm2ir_data(ir_loader *loader, LLVMTargetDataRef target_data, LLVMTy
|
|||||||
case LLVMConstantArrayValueKind:
|
case LLVMConstantArrayValueKind:
|
||||||
case LLVMConstantDataArrayValueKind:
|
case LLVMConstantDataArrayValueKind:
|
||||||
el_type = LLVMGetElementType(type);
|
el_type = LLVMGetElementType(type);
|
||||||
|
el_size = LLVMABISizeOfType(target_data, el_type);
|
||||||
len = LLVMGetArrayLength(type);
|
len = LLVMGetArrayLength(type);
|
||||||
|
offset = 0;
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
el = LLVMGetAggregateElement(op, 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
pos += el_size;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
case LLVMConstantStructValueKind:
|
case LLVMConstantStructValueKind:
|
||||||
len = LLVMCountStructElementTypes(type);
|
len = LLVMCountStructElementTypes(type);
|
||||||
for (i = 0; i < len; i++) {
|
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_type = LLVMStructGetTypeAtIndex(type, i);
|
||||||
el = LLVMGetAggregateElement(op, 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;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2038,9 +2048,20 @@ static int llvm2ir_data(ir_loader *loader, LLVMTargetDataRef target_data, LLVMTy
|
|||||||
// case LLVMConstantExprValueKind:
|
// case LLVMConstantExprValueKind:
|
||||||
// IR_ASSERT(0);
|
// IR_ASSERT(0);
|
||||||
// return 0;
|
// return 0;
|
||||||
// case LLVMUndefValueValueKind:
|
case LLVMUndefValueValueKind:
|
||||||
// IR_ASSERT(0);
|
case LLVMPoisonValueValueKind:
|
||||||
// return 0;
|
// 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:
|
default:
|
||||||
fprintf(stderr, "Unsupported LLVM value kind: %d\n", kind);
|
fprintf(stderr, "Unsupported LLVM value kind: %d\n", kind);
|
||||||
IR_ASSERT(0);
|
IR_ASSERT(0);
|
||||||
@ -2125,7 +2146,7 @@ static int ir_load_llvm_module(ir_loader *loader, LLVMModuleRef module)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (has_data) {
|
if (has_data) {
|
||||||
llvm2ir_data(loader, target_data, type, init);
|
llvm2ir_data(loader, target_data, type, init, 0);
|
||||||
if (!loader->sym_data_end(loader)) {
|
if (!loader->sym_data_end(loader)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
32
ir_main.c
32
ir_main.c
@ -253,6 +253,7 @@ typedef struct _ir_main_loader {
|
|||||||
ir_strtab symtab;
|
ir_strtab symtab;
|
||||||
ir_sym *sym;
|
ir_sym *sym;
|
||||||
ir_ref sym_count;
|
ir_ref sym_count;
|
||||||
|
void *data_start;
|
||||||
void *data;
|
void *data;
|
||||||
ir_code_buffer code_buffer;
|
ir_code_buffer code_buffer;
|
||||||
} ir_main_loader;
|
} 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);
|
memset(data, 0, size);
|
||||||
if (has_data) {
|
if (has_data) {
|
||||||
l->data = data;
|
l->data_start = l->data = data;
|
||||||
}
|
}
|
||||||
if (l->dump_asm) {
|
if (l->dump_asm) {
|
||||||
ir_disasm_add_symbol(name, (uintptr_t)data, size);
|
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) {
|
if (!l->data) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// TODO: alignement
|
|
||||||
memcpy(l->data, data, size);
|
memcpy(l->data, data, size);
|
||||||
l->data = (void*)((uintptr_t)l->data + size);
|
l->data = (void*)((uintptr_t)l->data + size);
|
||||||
}
|
}
|
||||||
return 1;
|
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)
|
static bool ir_loader_sym_data_ref(ir_loader *loader, ir_op op, const char *ref)
|
||||||
{
|
{
|
||||||
ir_main_loader *l = (ir_main_loader*) loader;
|
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.forward_func_dcl = ir_loader_forward_func_dcl;
|
||||||
loader.loader.sym_dcl = ir_loader_sym_dcl;
|
loader.loader.sym_dcl = ir_loader_sym_dcl;
|
||||||
loader.loader.sym_data = ir_loader_sym_data;
|
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_ref = ir_loader_sym_data_ref;
|
||||||
loader.loader.sym_data_end = ir_loader_sym_data_end;
|
loader.loader.sym_data_end = ir_loader_sym_data_end;
|
||||||
loader.loader.func_init = ir_loader_func_init;
|
loader.loader.func_init = ir_loader_func_init;
|
||||||
|
Loading…
Reference in New Issue
Block a user