aboutsummaryrefslogtreecommitdiff
path: root/src/llvm_abi.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2023-03-19 00:51:57 +0000
committergingerBill <bill@gingerbill.org>2023-03-19 00:51:57 +0000
commit1f5bb99548d4164b3225cb145a44850909d6e0d7 (patch)
treecb6bf16ddbb4fbe32725e060791256b48d7bf213 /src/llvm_abi.cpp
parentb7f953b2eeb8561509bc516cc87b416684cd89cb (diff)
Improve SysV ABI for multiple return values that fit into a single register; Fixes #2384
Diffstat (limited to 'src/llvm_abi.cpp')
-rw-r--r--src/llvm_abi.cpp12
1 files changed, 8 insertions, 4 deletions
diff --git a/src/llvm_abi.cpp b/src/llvm_abi.cpp
index 1204050ef..9b8a39514 100644
--- a/src/llvm_abi.cpp
+++ b/src/llvm_abi.cpp
@@ -563,7 +563,7 @@ namespace lbAbiAmd64SysV {
gb_internal void fixup(LLVMTypeRef t, Array<RegClass> *cls);
gb_internal lbArgType amd64_type(LLVMContextRef c, LLVMTypeRef type, Amd64TypeAttributeKind attribute_kind, ProcCallingConvention calling_convention);
gb_internal Array<RegClass> classify(LLVMTypeRef t);
- gb_internal LLVMTypeRef llreg(LLVMContextRef c, Array<RegClass> const &reg_classes);
+ gb_internal LLVMTypeRef llreg(LLVMContextRef c, Array<RegClass> const &reg_classes, LLVMTypeRef type);
gb_internal LB_ABI_INFO(abi_info) {
lbFunctionType *ft = gb_alloc_item(permanent_allocator(), lbFunctionType);
@@ -662,7 +662,7 @@ namespace lbAbiAmd64SysV {
// the ABI rules for SysV
reg_type = type;
} else {
- reg_type = llreg(c, cls);
+ reg_type = llreg(c, cls, type);
}
return lb_arg_type_direct(type, reg_type, nullptr, nullptr);
}
@@ -785,13 +785,17 @@ namespace lbAbiAmd64SysV {
}
- gb_internal LLVMTypeRef llreg(LLVMContextRef c, Array<RegClass> const &reg_classes) {
+ gb_internal LLVMTypeRef llreg(LLVMContextRef c, Array<RegClass> const &reg_classes, LLVMTypeRef type) {
auto types = array_make<LLVMTypeRef>(heap_allocator(), 0, reg_classes.count);
for (isize i = 0; i < reg_classes.count; /**/) {
RegClass reg_class = reg_classes[i];
switch (reg_class) {
case RegClass_Int:
- array_add(&types, LLVMIntTypeInContext(c, 64));
+ if (reg_classes.count == 1) {
+ array_add(&types, LLVMIntTypeInContext(c, cast(unsigned)(lb_sizeof(type)*8)));
+ } else {
+ array_add(&types, LLVMIntTypeInContext(c, 64));
+ }
break;
case RegClass_SSEFv:
case RegClass_SSEDv: