`-Zregparm` doesn't put 64-bit arguments in registers
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
The -Zregparm option on 32-bit x86 should pass arguments in registers where possible, but for 64-bit arguments, it will push them onto the stack, whereas C compilers (both gcc and clang) will put them in a pair of registers.
For example, the following rust code:
unsafe extern "C" {
pub fn test(s: i64) -> i64;
}
#[unsafe(no_mangle)]
pub fn f1() {
unsafe {
let r = test(42);
}
}
compiles to (with -Zregparm=3):
f1:
sub esp, 20
push 0
push 42
call test
add esp, 28
ret
Note the 64-bit value is put on the stack.
However, the equivalent C code:
extern long long test(long long s);
void f1(void)
{
long long r = test(42);
}
compiles to (gcc 15.2 with -mregparm=3, but clang produces something similar):
f1():
push ebp
mov ebp, esp
sub esp, 24
mov eax, 42
mov edx, 0
call test(long long)
mov DWORD PTR [ebp-16], eax
mov DWORD PTR [ebp-12], edx
nop
leave
ret
Note that the 64-bit value is put in edx:eax.
This can cause crashes/incorrect results due to an ABI mismatch, particularly in Rust-for-Linux on 32-bit x86.
Note that 64-bit return values seem to be functioning correctly, and are placed in edx:eax.
Compiler explorer link with the above examples: https://godbolt.org/z/feb7addG7
Rust-for-Linux tracking issue for 32-bit x86: https://github.com/Rust-for-Linux/linux/issues/78
Tracking issue for -Zregparm: https://github.com/rust-lang/rust/issues/131749
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the -Zregparm behavior and compare the Rust output in the linked Compiler Explorer example with the gcc and clang outputs. Use the -Zregparm tracking issue and Rust-for-Linux issue for context; done means 64-bit arguments on 32-bit x86 follow the expected register ABI without breaking the existing return-value behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100