aboutsummaryrefslogtreecommitdiff
path: root/src/llvm_abi.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2020-11-14 17:09:42 +0000
committergingerBill <bill@gingerbill.org>2020-11-14 17:09:42 +0000
commit9f930421632f4f6d5352ec01f12a1a7fb1050ba7 (patch)
tree3023afd61d2b8d024e95eed67bd55b9426ba2ec8 /src/llvm_abi.cpp
parenta64ea342df4cffa881b5829b8864e22fb9e116ab (diff)
Improve lb_abi_to_odin_type
Diffstat (limited to 'src/llvm_abi.cpp')
-rw-r--r--src/llvm_abi.cpp49
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));
}