From 9f930421632f4f6d5352ec01f12a1a7fb1050ba7 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 14 Nov 2020 17:09:42 +0000 Subject: [PATCH] Improve lb_abi_to_odin_type --- src/llvm_abi.cpp | 49 ++++++++++++++++++++++++++++++++++++++++---- src/llvm_backend.cpp | 4 ++++ 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/llvm_abi.cpp b/src/llvm_abi.cpp index d9e115a34..79f7948a3 100644 --- a/src/llvm_abi.cpp +++ b/src/llvm_abi.cpp @@ -275,8 +275,8 @@ Type *alloc_type_struct_from_field_types(Type **field_types, isize field_count, return t; } -Type *alloc_type_tuple_from_field_types(Type **field_types, isize field_count, bool is_packed) { - if (field_count == 1) { +Type *alloc_type_tuple_from_field_types(Type **field_types, isize field_count, bool is_packed, bool must_be_tuple) { + if (!must_be_tuple && field_count == 1) { return field_types[0]; } @@ -292,6 +292,21 @@ Type *alloc_type_tuple_from_field_types(Type **field_types, isize field_count, b return t; } +Type *alloc_type_proc_from_types(Type **param_types, unsigned param_count, Type *results, bool is_c_vararg) { + + Type *params = alloc_type_tuple_from_field_types(param_types, param_count, false, true); + isize results_count = 0; + if (results != nullptr) { + GB_ASSERT(results->kind == Type_Tuple); + results_count = results->Tuple.variables.count; + } + + Scope *scope = nullptr; + Type *t = alloc_type_proc(scope, params, param_count, results, results_count, false, /*not sure what to put here*/ProcCC_CDecl); + t->Proc.c_vararg = is_c_vararg; + return t; +} + Type *lb_abi_to_odin_type(LLVMTypeRef type, bool is_return, u32 level = 0) { LLVMTypeKind kind = LLVMGetTypeKind(type); switch (kind) { @@ -318,7 +333,33 @@ Type *lb_abi_to_odin_type(LLVMTypeRef type, bool is_return, u32 level = 0) { case LLVMDoubleTypeKind: return t_f64; case LLVMPointerTypeKind: - return t_rawptr; + { + LLVMTypeRef elem = LLVMGetElementType(type); + if (lb_is_type_kind(elem, LLVMFunctionTypeKind)) { + unsigned param_count = LLVMCountParamTypes(elem); + LLVMTypeRef *params = gb_alloc_array(heap_allocator(), LLVMTypeRef, param_count); + defer (gb_free(heap_allocator(), params)); + LLVMGetParamTypes(elem, params); + + Type **param_types = gb_alloc_array(heap_allocator(), Type *, param_count); + defer (gb_free(heap_allocator(), param_types)); + + for (unsigned i = 0; i < param_count; i++) { + param_types[i] = lb_abi_to_odin_type(params[i], false, /*level*/0); + } + + LLVMTypeRef ret = LLVMGetReturnType(elem); + Type *ret_type = lb_abi_to_odin_type(ret, true, /*level*/0); + + bool is_c_vararg = !!LLVMIsFunctionVarArg(elem); + return alloc_type_proc_from_types(param_types, param_count, ret_type, is_c_vararg); + } + return alloc_type_pointer(lb_abi_to_odin_type(elem, false, level)); + } + case LLVMFunctionTypeKind: + GB_PANIC("LLVMFunctionTypeKind should not be seen on its own"); + break; + case LLVMStructTypeKind: { unsigned field_count = LLVMCountStructElementTypes(type); @@ -327,7 +368,7 @@ Type *lb_abi_to_odin_type(LLVMTypeRef type, bool is_return, u32 level = 0) { fields[i] = lb_abi_to_odin_type(LLVMStructGetTypeAtIndex(type, i), false, level+1); } if (is_return) { - return alloc_type_tuple_from_field_types(fields, field_count, !!LLVMIsPackedStruct(type)); + return alloc_type_tuple_from_field_types(fields, field_count, !!LLVMIsPackedStruct(type), false); } else { return alloc_type_struct_from_field_types(fields, field_count, !!LLVMIsPackedStruct(type)); } diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index fbddb893e..1f20c607d 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1278,6 +1278,9 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { offset = 1; } + m->internal_type_level += 1; + defer (m->internal_type_level -= 1); + unsigned field_count = cast(unsigned)(type->Struct.fields.count + offset); LLVMTypeRef *fields = gb_alloc_array(heap_allocator(), LLVMTypeRef, field_count); GB_ASSERT(fields != nullptr); @@ -1288,6 +1291,7 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { fields[i+offset] = lb_type(m, field->type); } + if (type->Struct.custom_align > 0) { fields[0] = lb_alignment_prefix_type_hack(m, type->Struct.custom_align); }