Skip to content

Commit 5236426

Browse files
committed
Move ZST ABI handling to rustc_target
1 parent 466be51 commit 5236426

19 files changed

+764
-43
lines changed

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

+9-4
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
632632
pub fn make_indirect(&mut self) {
633633
match self.mode {
634634
PassMode::Direct(_) | PassMode::Pair(_, _) => {
635-
self.mode = Self::indirect_pass_mode(&self.layout);
635+
self.make_indirect_force();
636636
}
637637
PassMode::Indirect { attrs: _, meta_attrs: _, on_stack: false } => {
638638
// already indirect
@@ -642,6 +642,11 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
642642
}
643643
}
644644

645+
/// Same as make_indirect, but doesn't check the current `PassMode`.
646+
pub fn make_indirect_force(&mut self) {
647+
self.mode = Self::indirect_pass_mode(&self.layout);
648+
}
649+
645650
/// Pass this argument indirectly, by placing it at a fixed stack offset.
646651
/// This corresponds to the `byval` LLVM argument attribute.
647652
/// This is only valid for sized arguments.
@@ -860,10 +865,10 @@ impl<'a, Ty> FnAbi<'a, Ty> {
860865
}
861866
"x86_64" => match abi {
862867
spec::abi::Abi::SysV64 { .. } => x86_64::compute_abi_info(cx, self),
863-
spec::abi::Abi::Win64 { .. } => x86_win64::compute_abi_info(self),
868+
spec::abi::Abi::Win64 { .. } => x86_win64::compute_abi_info(cx, self),
864869
_ => {
865870
if cx.target_spec().is_like_windows {
866-
x86_win64::compute_abi_info(self)
871+
x86_win64::compute_abi_info(cx, self)
867872
} else {
868873
x86_64::compute_abi_info(cx, self)
869874
}
@@ -887,7 +892,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
887892
"csky" => csky::compute_abi_info(self),
888893
"mips" | "mips32r6" => mips::compute_abi_info(cx, self),
889894
"mips64" | "mips64r6" => mips64::compute_abi_info(cx, self),
890-
"powerpc" => powerpc::compute_abi_info(self),
895+
"powerpc" => powerpc::compute_abi_info(cx, self),
891896
"powerpc64" => powerpc64::compute_abi_info(cx, self),
892897
"s390x" => s390x::compute_abi_info(cx, self),
893898
"msp430" => msp430::compute_abi_info(self),
+14-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::abi::call::{ArgAbi, FnAbi};
2+
use crate::spec::HasTargetSpec;
23

34
fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
45
if ret.layout.is_aggregate() {
@@ -8,23 +9,30 @@ fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
89
}
910
}
1011

11-
fn classify_arg<Ty>(arg: &mut ArgAbi<'_, Ty>) {
12+
fn classify_arg<Ty>(cx: &impl HasTargetSpec, arg: &mut ArgAbi<'_, Ty>) {
13+
if arg.is_ignore() {
14+
// powerpc-unknown-linux-{gnu,musl,uclibc} doesn't ignore ZSTs.
15+
if cx.target_spec().os == "linux"
16+
&& matches!(&*cx.target_spec().env, "gnu" | "musl" | "uclibc")
17+
&& arg.layout.is_zst()
18+
{
19+
arg.make_indirect_force();
20+
}
21+
return;
22+
}
1223
if arg.layout.is_aggregate() {
1324
arg.make_indirect();
1425
} else {
1526
arg.extend_integer_width_to(32);
1627
}
1728
}
1829

19-
pub fn compute_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) {
30+
pub fn compute_abi_info<Ty>(cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) {
2031
if !fn_abi.ret.is_ignore() {
2132
classify_ret(&mut fn_abi.ret);
2233
}
2334

2435
for arg in fn_abi.args.iter_mut() {
25-
if arg.is_ignore() {
26-
continue;
27-
}
28-
classify_arg(arg);
36+
classify_arg(cx, arg);
2937
}
3038
}

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

+13-5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
use crate::abi::call::{ArgAbi, FnAbi, Reg};
55
use crate::abi::{HasDataLayout, TyAbiInterface};
6+
use crate::spec::HasTargetSpec;
67

78
fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
89
if !ret.layout.is_aggregate() && ret.layout.size.bits() <= 64 {
@@ -15,12 +16,22 @@ fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
1516
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
1617
where
1718
Ty: TyAbiInterface<'a, C> + Copy,
18-
C: HasDataLayout,
19+
C: HasDataLayout + HasTargetSpec,
1920
{
2021
if !arg.layout.is_sized() {
2122
// Not touching this...
2223
return;
2324
}
25+
if arg.is_ignore() {
26+
// s390x-unknown-linux-{gnu,musl,uclibc} doesn't ignore ZSTs.
27+
if cx.target_spec().os == "linux"
28+
&& matches!(&*cx.target_spec().env, "gnu" | "musl" | "uclibc")
29+
&& arg.layout.is_zst()
30+
{
31+
arg.make_indirect_force();
32+
}
33+
return;
34+
}
2435
if !arg.layout.is_aggregate() && arg.layout.size.bits() <= 64 {
2536
arg.extend_integer_width_to(64);
2637
return;
@@ -46,16 +57,13 @@ where
4657
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
4758
where
4859
Ty: TyAbiInterface<'a, C> + Copy,
49-
C: HasDataLayout,
60+
C: HasDataLayout + HasTargetSpec,
5061
{
5162
if !fn_abi.ret.is_ignore() {
5263
classify_ret(&mut fn_abi.ret);
5364
}
5465

5566
for arg in fn_abi.args.iter_mut() {
56-
if arg.is_ignore() {
57-
continue;
58-
}
5967
classify_arg(cx, arg);
6068
}
6169
}

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

+10-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::abi::call::{
44
ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, Reg, Uniform,
55
};
66
use crate::abi::{self, HasDataLayout, Scalar, Size, TyAbiInterface, TyAndLayout};
7+
use crate::spec::HasTargetSpec;
78

89
#[derive(Clone, Debug)]
910
pub struct Sdata {
@@ -211,15 +212,22 @@ where
211212
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
212213
where
213214
Ty: TyAbiInterface<'a, C> + Copy,
214-
C: HasDataLayout,
215+
C: HasDataLayout + HasTargetSpec,
215216
{
216217
if !fn_abi.ret.is_ignore() {
217218
classify_arg(cx, &mut fn_abi.ret, Size::from_bytes(32));
218219
}
219220

220221
for arg in fn_abi.args.iter_mut() {
221222
if arg.is_ignore() {
222-
continue;
223+
// sparc64-unknown-linux-{gnu,musl,uclibc} doesn't ignore ZSTs.
224+
if cx.target_spec().os == "linux"
225+
&& matches!(&*cx.target_spec().env, "gnu" | "musl" | "uclibc")
226+
&& arg.layout.is_zst()
227+
{
228+
arg.make_indirect_force();
229+
}
230+
return;
223231
}
224232
classify_arg(cx, arg, Size::from_bytes(16));
225233
}

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

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
use crate::abi::call::{ArgAbi, FnAbi, Reg};
22
use crate::abi::Abi;
3+
use crate::spec::HasTargetSpec;
34

45
// Win64 ABI: https://docs.microsoft.com/en-us/cpp/build/parameter-passing
56

6-
pub fn compute_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) {
7+
pub fn compute_abi_info<Ty>(cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) {
78
let fixup = |a: &mut ArgAbi<'_, Ty>| {
89
match a.layout.abi {
910
Abi::Uninhabited | Abi::Aggregate { sized: false } => {}
@@ -33,6 +34,13 @@ pub fn compute_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) {
3334
}
3435
for arg in fn_abi.args.iter_mut() {
3536
if arg.is_ignore() {
37+
// x86_64-pc-windows-gnu doesn't ignore ZSTs.
38+
if cx.target_spec().os == "windows"
39+
&& cx.target_spec().env == "gnu"
40+
&& arg.layout.is_zst()
41+
{
42+
arg.make_indirect_force();
43+
}
3644
continue;
3745
}
3846
fixup(arg);

compiler/rustc_ty_utils/src/abi.rs

+2-25
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,7 @@ fn fn_abi_new_uncached<'tcx>(
585585
let conv = conv_from_spec_abi(cx.tcx(), sig.abi, sig.c_variadic);
586586

587587
let mut inputs = sig.inputs();
588-
let extra_args = if sig.abi == RustCall {
588+
let extra_args = if sig.abi == SpecAbi::RustCall {
589589
assert!(!sig.c_variadic && extra_args.is_empty());
590590

591591
if let Some(input) = sig.inputs().last() {
@@ -609,18 +609,6 @@ fn fn_abi_new_uncached<'tcx>(
609609
extra_args
610610
};
611611

612-
let target = &cx.tcx.sess.target;
613-
let target_env_gnu_like = matches!(&target.env[..], "gnu" | "musl" | "uclibc");
614-
let win_x64_gnu = target.os == "windows" && target.arch == "x86_64" && target.env == "gnu";
615-
let linux_s390x_gnu_like =
616-
target.os == "linux" && target.arch == "s390x" && target_env_gnu_like;
617-
let linux_sparc64_gnu_like =
618-
target.os == "linux" && target.arch == "sparc64" && target_env_gnu_like;
619-
let linux_powerpc_gnu_like =
620-
target.os == "linux" && target.arch == "powerpc" && target_env_gnu_like;
621-
use SpecAbi::*;
622-
let rust_abi = matches!(sig.abi, RustIntrinsic | Rust | RustCall);
623-
624612
let is_drop_in_place =
625613
fn_def_id.is_some() && fn_def_id == cx.tcx.lang_items().drop_in_place_fn();
626614

@@ -660,18 +648,7 @@ fn fn_abi_new_uncached<'tcx>(
660648
});
661649

662650
if arg.layout.is_zst() {
663-
// For some forsaken reason, x86_64-pc-windows-gnu
664-
// doesn't ignore zero-sized struct arguments.
665-
// The same is true for {s390x,sparc64,powerpc}-unknown-linux-{gnu,musl,uclibc}.
666-
if is_return
667-
|| rust_abi
668-
|| (!win_x64_gnu
669-
&& !linux_s390x_gnu_like
670-
&& !linux_sparc64_gnu_like
671-
&& !linux_powerpc_gnu_like)
672-
{
673-
arg.mode = PassMode::Ignore;
674-
}
651+
arg.mode = PassMode::Ignore;
675652
}
676653

677654
Ok(arg)

src/tools/compiletest/src/header.rs

+6
Original file line numberDiff line numberDiff line change
@@ -801,10 +801,12 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
801801
"ignore-nvptx64",
802802
"ignore-openbsd",
803803
"ignore-pass",
804+
"ignore-powerpc",
804805
"ignore-remote",
805806
"ignore-riscv64",
806807
"ignore-s390x",
807808
"ignore-sgx",
809+
"ignore-sparc64",
808810
"ignore-spirv",
809811
"ignore-stable",
810812
"ignore-stage1",
@@ -830,6 +832,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
830832
"ignore-x32",
831833
"ignore-x86",
832834
"ignore-x86_64",
835+
"ignore-x86_64-pc-windows-gnu",
833836
"ignore-x86_64-unknown-linux-gnu",
834837
"incremental",
835838
"known-bug",
@@ -895,7 +898,9 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
895898
"only-msvc",
896899
"only-nightly",
897900
"only-nvptx64",
901+
"only-powerpc",
898902
"only-riscv64",
903+
"only-s390x",
899904
"only-sparc",
900905
"only-sparc64",
901906
"only-stable",
@@ -908,6 +913,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
908913
"only-wasm32-wasip1",
909914
"only-watchos",
910915
"only-windows",
916+
"only-windows-gnu",
911917
"only-x86",
912918
"only-x86_64",
913919
"only-x86_64-fortanix-unknown-sgx",

tests/ui/abi/c-zst.other-linux.stderr

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
error: fn_abi_of(pass_zst) = FnAbi {
2+
args: [
3+
ArgAbi {
4+
layout: TyAndLayout {
5+
ty: (),
6+
layout: Layout {
7+
size: Size(0 bytes),
8+
align: AbiAndPrefAlign {
9+
abi: Align(1 bytes),
10+
pref: Align(8 bytes),
11+
},
12+
abi: Aggregate {
13+
sized: true,
14+
},
15+
fields: Arbitrary {
16+
offsets: [],
17+
memory_index: [],
18+
},
19+
largest_niche: None,
20+
variants: Single {
21+
index: 0,
22+
},
23+
max_repr_align: None,
24+
unadjusted_abi_align: Align(1 bytes),
25+
},
26+
},
27+
mode: Ignore,
28+
},
29+
],
30+
ret: ArgAbi {
31+
layout: TyAndLayout {
32+
ty: (),
33+
layout: Layout {
34+
size: Size(0 bytes),
35+
align: AbiAndPrefAlign {
36+
abi: Align(1 bytes),
37+
pref: Align(8 bytes),
38+
},
39+
abi: Aggregate {
40+
sized: true,
41+
},
42+
fields: Arbitrary {
43+
offsets: [],
44+
memory_index: [],
45+
},
46+
largest_niche: None,
47+
variants: Single {
48+
index: 0,
49+
},
50+
max_repr_align: None,
51+
unadjusted_abi_align: Align(1 bytes),
52+
},
53+
},
54+
mode: Ignore,
55+
},
56+
c_variadic: false,
57+
fixed_count: 1,
58+
conv: C,
59+
can_unwind: true,
60+
}
61+
--> $DIR/c-zst.rs:26:1
62+
|
63+
LL | extern "C" fn pass_zst(_: ()) {}
64+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
65+
66+
error: aborting due to 1 previous error
67+

0 commit comments

Comments
 (0)