Skip to content

Commit c8970c5

Browse files
committed
rust_for_linux: -Zreg-struct-return commandline flag for X86 (rust-lang#116973)
1 parent caecc18 commit c8970c5

File tree

8 files changed

+83
-4
lines changed

8 files changed

+83
-4
lines changed

compiler/rustc_codegen_gcc/src/context.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,10 @@ impl<'gcc, 'tcx> HasWasmCAbiOpt for CodegenCx<'gcc, 'tcx> {
575575

576576
impl<'gcc, 'tcx> HasX86AbiOpt for CodegenCx<'gcc, 'tcx> {
577577
fn x86_abi_opt(&self) -> X86Abi {
578-
X86Abi { regparm: self.tcx.sess.opts.unstable_opts.regparm }
578+
X86Abi {
579+
regparm: self.tcx.sess.opts.unstable_opts.regparm,
580+
reg_struct_return: self.tcx.sess.opts.unstable_opts.reg_struct_return,
581+
}
579582
}
580583
}
581584

compiler/rustc_interface/src/tests.rs

+1
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,7 @@ fn test_unstable_options_tracking_hash() {
834834
tracked!(profile_emit, Some(PathBuf::from("abc")));
835835
tracked!(profile_sample_use, Some(PathBuf::from("abc")));
836836
tracked!(profiler_runtime, "abc".to_string());
837+
tracked!(reg_struct_return, true);
837838
tracked!(regparm, Some(3));
838839
tracked!(relax_elf_relocations, Some(true));
839840
tracked!(remap_cwd_prefix, Some(PathBuf::from("abc")));

compiler/rustc_middle/src/ty/layout.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,10 @@ impl<'tcx> HasWasmCAbiOpt for TyCtxt<'tcx> {
538538

539539
impl<'tcx> HasX86AbiOpt for TyCtxt<'tcx> {
540540
fn x86_abi_opt(&self) -> X86Abi {
541-
X86Abi { regparm: self.sess.opts.unstable_opts.regparm }
541+
X86Abi {
542+
regparm: self.sess.opts.unstable_opts.regparm,
543+
reg_struct_return: self.sess.opts.unstable_opts.reg_struct_return,
544+
}
542545
}
543546
}
544547

compiler/rustc_session/src/options.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1978,6 +1978,9 @@ options! {
19781978
"enable queries of the dependency graph for regression testing (default: no)"),
19791979
randomize_layout: bool = (false, parse_bool, [TRACKED],
19801980
"randomize the layout of types (default: no)"),
1981+
reg_struct_return: bool = (false, parse_bool, [TRACKED],
1982+
"On x86-32 targets, it overrides the default ABI to return small structs in registers.
1983+
It is UNSOUND to link together crates that use different values for this flag!"),
19811984
regparm: Option<u32> = (None, parse_opt_number, [TRACKED],
19821985
"On x86-32 targets, setting this to N causes the compiler to pass N arguments \
19831986
in registers EAX, EDX, and ECX instead of on the stack.\

compiler/rustc_target/src/abi/call/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -899,7 +899,9 @@ impl<'a, Ty> FnAbi<'a, Ty> {
899899
}
900900
_ => (x86::Flavor::General, None),
901901
};
902-
x86::compute_abi_info(cx, self, x86::X86Options { flavor, regparm });
902+
let reg_struct_return = cx.x86_abi_opt().reg_struct_return;
903+
let opts = x86::X86Options { flavor, regparm, reg_struct_return };
904+
x86::compute_abi_info(cx, self, opts);
903905
}
904906
"x86_64" => match abi {
905907
spec::abi::Abi::SysV64 { .. } => x86_64::compute_abi_info(cx, self),

compiler/rustc_target/src/abi/call/x86.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ pub(crate) enum Flavor {
1111
pub(crate) struct X86Options {
1212
pub flavor: Flavor,
1313
pub regparm: Option<u32>,
14+
pub reg_struct_return: bool,
1415
}
1516

1617
pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, opts: X86Options)
@@ -29,7 +30,7 @@ where
2930
// https://www.angelcode.com/dev/callconv/callconv.html
3031
// Clang's ABI handling is in lib/CodeGen/TargetInfo.cpp
3132
let t = cx.target_spec();
32-
if t.abi_return_struct_as_int {
33+
if t.abi_return_struct_as_int || opts.reg_struct_return {
3334
// According to Clang, everyone but MSVC returns single-element
3435
// float aggregates directly in a floating-point register.
3536
if !t.is_like_msvc && fn_abi.ret.layout.is_single_fp_element(cx) {

compiler/rustc_target/src/spec/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2056,6 +2056,8 @@ pub struct X86Abi {
20562056
/// On x86-32 targets, the regparm N causes the compiler to pass arguments
20572057
/// in registers EAX, EDX, and ECX instead of on the stack.
20582058
pub regparm: Option<u32>,
2059+
/// Override the default ABI to return small structs in registers
2060+
pub reg_struct_return: bool,
20592061
}
20602062

20612063
pub trait HasX86AbiOpt {

tests/codegen/reg-struct-return.rs

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Checks how `reg-struct-return` flag works with different calling conventions:
2+
// Return struct with 8/16/32/64 bit size will be converted into i8/i16/i32/i64
3+
// (like abi_return_struct_as_int target spec).
4+
// x86 only.
5+
6+
//@ compile-flags: --target i686-unknown-linux-gnu -Zreg-struct-return -O -C no-prepopulate-passes
7+
//@ needs-llvm-components: x86
8+
9+
#![crate_type = "lib"]
10+
#![no_std]
11+
#![no_core]
12+
#![feature(no_core, lang_items)]
13+
14+
#[lang = "sized"]
15+
trait Sized {}
16+
#[lang = "copy"]
17+
trait Copy {}
18+
19+
#[repr(C)]
20+
pub struct Foo {
21+
x: u32,
22+
y: u32,
23+
}
24+
25+
pub mod tests {
26+
use Foo;
27+
28+
// CHECK: i64 @f1()
29+
#[no_mangle]
30+
pub extern "fastcall" fn f1() -> Foo {
31+
Foo { x: 1, y: 2 }
32+
}
33+
34+
// reg-struct-return doesn't work for "Rust" calling conv
35+
// CHECK: { i32, i32 } @f2()
36+
#[no_mangle]
37+
pub extern "Rust" fn f2() -> Foo {
38+
Foo { x: 1, y: 2 }
39+
}
40+
41+
// CHECK: i64 @f3()
42+
#[no_mangle]
43+
pub extern "C" fn f3() -> Foo {
44+
Foo { x: 1, y: 2 }
45+
}
46+
47+
// CHECK: i64 @f4()
48+
#[no_mangle]
49+
pub extern "cdecl" fn f4() -> Foo {
50+
Foo { x: 1, y: 2 }
51+
}
52+
53+
// CHECK: i64 @f5()
54+
#[no_mangle]
55+
pub extern "stdcall" fn f5() -> Foo {
56+
Foo { x: 1, y: 2 }
57+
}
58+
59+
// CHECK: i64 @f6()
60+
#[no_mangle]
61+
pub extern "thiscall" fn f6() -> Foo {
62+
Foo { x: 1, y: 2 }
63+
}
64+
}

0 commit comments

Comments
 (0)