i386: return aggregates through the hidden pointer on System V targets

This commit is contained in:
kalsprite
2026-08-10 22:08:15 -07:00
parent 9932b4d2d4
commit 37e1c98b1f

View File

@@ -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();