mirror of
https://github.com/rust-lang/rust.git
synced 2025-11-25 22:36:43 +00:00
Fix `-Zregparm` for LLVM builtins
This fixes the issue where `-Zregparm=N` was not working correctly when calling LLVM intrinsics
By default on `x86-32`, arguments are passed on the stack. The `-Zregparm=N` flag allows the first `N` arguments to be passed in registers instead.
When calling intrinsics like `memset`, LLVM still passes parameters on the stack, which prevents optimizations like tail calls.
As proposed by ````@tgross35,```` I fixed this by setting the `NumRegisterParameters` LLVM module flag to `N` when the `-Zregparm=N` is set.
```rust
// compiler/rust_codegen_llvm/src/context.rs#375-382
if let Some(regparm_count) = sess.opts.unstable_opts.regparm {
llvm::add_module_flag_u32(
llmod,
llvm::ModuleFlagMergeBehavior::Error,
"NumRegisterParameters",
regparm_count,
);
}
```
[Here](https://rust.godbolt.org/z/YMezreo48) is a before/after compiler explorer.
Here is the final result for the code snippet in the original issue:
```asm
entrypoint:
push esi
mov esi, eax
mov eax, ecx
mov ecx, esi
pop esi
jmp memset ; Tail call parameters in registers
```
Fixes: https://github.com/rust-lang/rust/issues/145271
The codegen crate contains the code to convert from MIR into LLVM IR,
and then from LLVM IR into machine code. In general it contains code
that runs towards the end of the compilation process.
For more information about how codegen works, see the rustc dev guide.