diff options
| author | gingerBill <bill@gingerbill.org> | 2020-11-14 17:09:42 +0000 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2020-11-14 17:09:42 +0000 |
| commit | 9f930421632f4f6d5352ec01f12a1a7fb1050ba7 (patch) | |
| tree | 3023afd61d2b8d024e95eed67bd55b9426ba2ec8 /src/llvm_abi.cpp | |
| parent | a64ea342df4cffa881b5829b8864e22fb9e116ab (diff) | |
Improve lb_abi_to_odin_type
Diffstat (limited to 'src/llvm_abi.cpp')
| -rw-r--r-- | src/llvm_abi.cpp | 49 |
1 files changed, 45 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)); } |