Skip to content

Commit 8118dc6

Browse files
committed
x86: Correctly pass larger structs/types in registers with -Zregparm
Fixes #145694. The -Zregparm option for 32-bit x86 modifies the calling convention to pass a number of arguments in registers instead of on the stack. (This is primarily used by the Linux kernel.) Currently, rustc will only pass primitive integer types in registers, which seems to match the gcc documentation[1], which says that arguments "of integral type" are passed as registers. This also matches the fastcall and vectorcall conventions on windows. However, it seems that _any_ type — most particularly structs — should be passed as a register if possible. This matches what clang and gcc do, and so avoids an ABI mismatch when linking with C code (which, after all, is the whole point of supporting -Zregparm).
1 parent 3be6803 commit 8118dc6

File tree

1 file changed

+3
-1
lines changed
  • compiler/rustc_target/src/callconv

1 file changed

+3
-1
lines changed

compiler/rustc_target/src/callconv/x86.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,9 @@ pub(crate) fn fill_inregs<'a, Ty, C>(
183183

184184
free_regs -= size_in_regs;
185185

186-
if arg.layout.size.bits() <= 32 && unit.kind == RegKind::Integer {
186+
if opts.flavor != Flavor::FastcallOrVectorcall
187+
|| arg.layout.size.bits() <= 32 && unit.kind == RegKind::Integer
188+
{
187189
attrs.set(ArgAttribute::InReg);
188190
}
189191

0 commit comments

Comments
 (0)