Skip to content

Commit b1493ba

Browse files
committedAug 2, 2024
Move ZST ABI handling to rustc_target
1 parent a886938 commit b1493ba

19 files changed

+766
-43
lines changed
 

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

+9-4
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
642642
pub fn make_indirect(&mut self) {
643643
match self.mode {
644644
PassMode::Direct(_) | PassMode::Pair(_, _) => {
645-
self.mode = Self::indirect_pass_mode(&self.layout);
645+
self.make_indirect_force();
646646
}
647647
PassMode::Indirect { attrs: _, meta_attrs: _, on_stack: false } => {
648648
// already indirect
@@ -652,6 +652,11 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
652652
}
653653
}
654654

655+
/// Same as make_indirect, but doesn't check the current `PassMode`.
656+
pub fn make_indirect_force(&mut self) {
657+
self.mode = Self::indirect_pass_mode(&self.layout);
658+
}
659+
655660
/// Pass this argument indirectly, by placing it at a fixed stack offset.
656661
/// This corresponds to the `byval` LLVM argument attribute.
657662
/// This is only valid for sized arguments.
@@ -871,10 +876,10 @@ impl<'a, Ty> FnAbi<'a, Ty> {
871876
}
872877
"x86_64" => match abi {
873878
spec::abi::Abi::SysV64 { .. } => x86_64::compute_abi_info(cx, self),
874-
spec::abi::Abi::Win64 { .. } => x86_win64::compute_abi_info(self),
879+
spec::abi::Abi::Win64 { .. } => x86_win64::compute_abi_info(cx, self),
875880
_ => {
876881
if cx.target_spec().is_like_windows {
877-
x86_win64::compute_abi_info(self)
882+
x86_win64::compute_abi_info(cx, self)
878883
} else {
879884
x86_64::compute_abi_info(cx, self)
880885
}
@@ -898,7 +903,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
898903
"csky" => csky::compute_abi_info(self),
899904
"mips" | "mips32r6" => mips::compute_abi_info(cx, self),
900905
"mips64" | "mips64r6" => mips64::compute_abi_info(cx, self),
901-
"powerpc" => powerpc::compute_abi_info(self),
906+
"powerpc" => powerpc::compute_abi_info(cx, self),
902907
"powerpc64" => powerpc64::compute_abi_info(cx, self),
903908
"s390x" => s390x::compute_abi_info(cx, self),
904909
"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, Float, Primitive};
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 } => {}
@@ -37,6 +38,13 @@ pub fn compute_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) {
3738
}
3839
for arg in fn_abi.args.iter_mut() {
3940
if arg.is_ignore() {
41+
// x86_64-pc-windows-gnu doesn't ignore ZSTs.
42+
if cx.target_spec().os == "windows"
43+
&& cx.target_spec().env == "gnu"
44+
&& arg.layout.is_zst()
45+
{
46+
arg.make_indirect_force();
47+
}
4048
continue;
4149
}
4250
fixup(arg);

‎compiler/rustc_ty_utils/src/abi.rs

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

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

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

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

@@ -659,18 +647,7 @@ fn fn_abi_new_uncached<'tcx>(
659647
});
660648

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

676653
Ok(arg)

‎src/tools/compiletest/src/command-list.rs

+5
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,12 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
9191
"ignore-nvptx64-nvidia-cuda",
9292
"ignore-openbsd",
9393
"ignore-pass",
94+
"ignore-powerpc",
9495
"ignore-remote",
9596
"ignore-riscv64",
9697
"ignore-s390x",
9798
"ignore-sgx",
99+
"ignore-sparc64",
98100
"ignore-spirv",
99101
"ignore-stable",
100102
"ignore-stage1",
@@ -122,6 +124,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
122124
"ignore-x86",
123125
"ignore-x86_64",
124126
"ignore-x86_64-apple-darwin",
127+
"ignore-x86_64-pc-windows-gnu",
125128
"ignore-x86_64-unknown-linux-gnu",
126129
"incremental",
127130
"known-bug",
@@ -189,7 +192,9 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
189192
"only-msvc",
190193
"only-nightly",
191194
"only-nvptx64",
195+
"only-powerpc",
192196
"only-riscv64",
197+
"only-s390x",
193198
"only-sparc",
194199
"only-sparc64",
195200
"only-stable",

‎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: $SOME_ALIGN,
10+
pref: $SOME_ALIGN,
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: $SOME_ALIGN,
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: $SOME_ALIGN,
37+
pref: $SOME_ALIGN,
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: $SOME_ALIGN,
52+
},
53+
},
54+
mode: Ignore,
55+
},
56+
c_variadic: false,
57+
fixed_count: 1,
58+
conv: C,
59+
can_unwind: false,
60+
}
61+
--> $DIR/c-zst.rs:27: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)
Please sign in to comment.