From 37e1c98b1f2ddf4f3c69b40e09d7ba281d86f2c6 Mon Sep 17 00:00:00 2001 From: kalsprite Date: Mon, 10 Aug 2026 22:08:15 -0700 Subject: [PATCH] i386: return aggregates through the hidden pointer on System V targets --- src/llvm_abi.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/llvm_abi.cpp b/src/llvm_abi.cpp index 528ddca88..ffc224bda 100644 --- a/src/llvm_abi.cpp +++ b/src/llvm_abi.cpp @@ -450,12 +450,21 @@ namespace lbAbi386 { if (!return_is_defined) { return lb_arg_type_direct(LLVMVoidTypeInContext(c)); } else if (lb_is_type_kind(return_type, LLVMStructTypeKind) || lb_is_type_kind(return_type, LLVMArrayTypeKind)) { + // Only some i386 targets return a small aggregate in EDX:EAX. The Intel386 System V + // psABI returns every structure and union through the hidden pointer, with no size + // threshold; Windows and the BSDs return one of eight bytes or fewer in registers. + bool small_in_registers = build_context.metrics.os == TargetOs_windows || + build_context.metrics.os == TargetOs_freebsd || + build_context.metrics.os == TargetOs_openbsd; + i64 sz = lb_sizeof(return_type); - switch (sz) { - case 1: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 8), nullptr, nullptr); - case 2: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 16), nullptr, nullptr); - case 4: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 32), nullptr, nullptr); - case 8: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 64), nullptr, nullptr); + if (small_in_registers) { + switch (sz) { + case 1: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 8), nullptr, nullptr); + case 2: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 16), nullptr, nullptr); + case 4: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 32), nullptr, nullptr); + case 8: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 64), nullptr, nullptr); + } } LB_ABI_MODIFY_RETURN_IF_TUPLE_MACRO();