diff options
Diffstat (limited to 'src/llvm_abi.cpp')
| -rw-r--r-- | src/llvm_abi.cpp | 39 |
1 files changed, 30 insertions, 9 deletions
diff --git a/src/llvm_abi.cpp b/src/llvm_abi.cpp index e18dc344b..07d2dd6e3 100644 --- a/src/llvm_abi.cpp +++ b/src/llvm_abi.cpp @@ -965,6 +965,10 @@ namespace lbAbiArm64 { } return false; } + + unsigned is_homogenous_aggregate_small_enough(LLVMTypeRef *base_type_, unsigned member_count_) { + return (member_count_ <= 4); + } lbArgType compute_return_type(LLVMContextRef c, LLVMTypeRef type, bool return_is_defined) { LLVMTypeRef homo_base_type = {}; @@ -975,22 +979,31 @@ namespace lbAbiArm64 { } else if (is_register(type)) { return non_struct(c, type); } else if (is_homogenous_aggregate(c, type, &homo_base_type, &homo_member_count)) { - return lb_arg_type_direct(type, LLVMArrayType(homo_base_type, homo_member_count), nullptr, nullptr); + if(is_homogenous_aggregate_small_enough(&homo_base_type, homo_member_count)) { + return lb_arg_type_direct(type, LLVMArrayType(homo_base_type, homo_member_count), nullptr, nullptr); + } else { + //TODO(Platin): do i need to create stuff that can handle the diffrent return type? + // else this needs a fix in llvm_backend_proc as we would need to cast it to the correct array type + + //LLVMTypeRef array_type = LLVMArrayType(homo_base_type, homo_member_count); + LLVMAttributeRef attr = lb_create_enum_attribute_with_type(c, "sret", type); + return lb_arg_type_indirect(type, attr); + } } else { i64 size = lb_sizeof(type); if (size <= 16) { LLVMTypeRef cast_type = nullptr; if (size <= 1) { - cast_type = LLVMIntTypeInContext(c, 8); + cast_type = LLVMInt8TypeInContext(c); } else if (size <= 2) { - cast_type = LLVMIntTypeInContext(c, 16); + cast_type = LLVMInt16TypeInContext(c); } else if (size <= 4) { - cast_type = LLVMIntTypeInContext(c, 32); + cast_type = LLVMInt32TypeInContext(c); } else if (size <= 8) { - cast_type = LLVMIntTypeInContext(c, 64); + cast_type = LLVMInt64TypeInContext(c); } else { unsigned count = cast(unsigned)((size+7)/8); - cast_type = LLVMArrayType(LLVMIntTypeInContext(c, 64), count); + cast_type = LLVMArrayType(LLVMInt64TypeInContext(c), count); } return lb_arg_type_direct(type, cast_type, nullptr, nullptr); } else { @@ -999,7 +1012,7 @@ namespace lbAbiArm64 { } } } - + Array<lbArgType> compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count) { auto args = array_make<lbArgType>(heap_allocator(), arg_count); @@ -1171,16 +1184,24 @@ LB_ABI_INFO(lb_get_abi_info) { ft->calling_convention = calling_convention; return ft; } + case ProcCC_Win64: + GB_ASSERT(build_context.metrics.arch == TargetArch_amd64); + return lbAbiAmd64Win64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention); + case ProcCC_SysV: + GB_ASSERT(build_context.metrics.arch == TargetArch_amd64); + return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention); } switch (build_context.metrics.arch) { case TargetArch_amd64: - if (build_context.metrics.os == TargetOs_windows) { + if (build_context.metrics.os == TargetOs_windows || build_context.metrics.abi == TargetABI_Win64) { return lbAbiAmd64Win64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention); + } else if (build_context.metrics.abi == TargetABI_SysV) { + return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention); } else { return lbAbiAmd64SysV::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention); } - case TargetArch_386: + case TargetArch_i386: return lbAbi386::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention); case TargetArch_arm64: return lbAbiArm64::abi_info(c, arg_types, arg_count, return_type, return_is_defined, calling_convention); |