Skip to content

Commit 2c5a26b

Browse files
authored
Rollup merge of rust-lang#117671 - kjetilkjeka:nvptx_c_abi_avoid_direct, r=davidtwco
NVPTX: Avoid PassMode::Direct for args in C abi Fixes rust-lang#117480 I must admit that I'm confused about `PassMode` altogether, is there a good sum-up threads for this anywhere? I'm especially confused about how "indirect" and "byval" goes together. To me it seems like "indirect" basically means "use a indirection through a pointer", while "byval" basically means "do not use indirection through a pointer". The return used to keep `PassMode::Direct` for small aggregates. It turns out that `make_indirect` messes up the tests and one way to fix it is to keep `PassMode::Direct` for all aggregates. I have mostly seen this PassMode mentioned for args. Is it also a problem for returns? When experimenting with `byval` as an alternative i ran into [this assert](https://github.com/rust-lang/rust/blob/61a3eea8043cc1c7a09c2adda884e27ffa8a1172/compiler/rustc_codegen_llvm/src/abi.rs#L463C22-L463C22) I have added tests for the same kind of types that is already tested for the "ptx-kernel" abi. The tests cannot be enabled until something like rust-lang#117458 is completed and merged. CC: `@RalfJung` since you seem to be the expert on this and have already helped me out tremendously CC: `@RDambrosio016` in case this influence your work on `rustc_codegen_nvvm` `@rustbot` label +O-NVPTX
2 parents f989d2f + ead02ba commit 2c5a26b

File tree

3 files changed

+440
-5
lines changed

3 files changed

+440
-5
lines changed

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

+4-5
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@ fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
1111
}
1212

1313
fn classify_arg<Ty>(arg: &mut ArgAbi<'_, Ty>) {
14-
if arg.layout.is_aggregate() && arg.layout.size.bits() > 64 {
15-
arg.make_indirect();
16-
} else {
17-
// FIXME: this is wrong! Need to decide which ABI we really want here.
18-
arg.make_direct_deprecated();
14+
if arg.layout.is_aggregate() {
15+
arg.make_indirect_byval(None);
16+
} else if arg.layout.size.bits() < 32 {
17+
arg.extend_integer_width_to(32);
1918
}
2019
}
2120

tests/assembly/nvptx-c-abi-arg-v7.rs

+206
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
//@ assembly-output: ptx-linker
2+
//@ compile-flags: --crate-type cdylib -C target-cpu=sm_86 -Z unstable-options -Clinker-flavor=llbc
3+
//@ only-nvptx64
4+
5+
// The PTX ABI stability is tied to major versions of the PTX ISA
6+
// These tests assume major version 7
7+
8+
// CHECK: .version 7
9+
10+
#![feature(abi_ptx, lang_items, no_core)]
11+
#![no_core]
12+
13+
#[lang = "sized"]
14+
trait Sized {}
15+
#[lang = "copy"]
16+
trait Copy {}
17+
18+
#[repr(C)]
19+
pub struct SingleU8 {
20+
f: u8,
21+
}
22+
23+
#[repr(C)]
24+
pub struct DoubleU8 {
25+
f: u8,
26+
g: u8,
27+
}
28+
29+
#[repr(C)]
30+
pub struct TripleU8 {
31+
f: u8,
32+
g: u8,
33+
h: u8,
34+
}
35+
36+
#[repr(C)]
37+
pub struct TripleU16 {
38+
f: u16,
39+
g: u16,
40+
h: u16,
41+
}
42+
#[repr(C)]
43+
pub struct TripleU32 {
44+
f: u32,
45+
g: u32,
46+
h: u32,
47+
}
48+
#[repr(C)]
49+
pub struct TripleU64 {
50+
f: u64,
51+
g: u64,
52+
h: u64,
53+
}
54+
55+
#[repr(C)]
56+
pub struct DoubleFloat {
57+
f: f32,
58+
g: f32,
59+
}
60+
61+
#[repr(C)]
62+
pub struct TripleFloat {
63+
f: f32,
64+
g: f32,
65+
h: f32,
66+
}
67+
68+
#[repr(C)]
69+
pub struct TripleDouble {
70+
f: f64,
71+
g: f64,
72+
h: f64,
73+
}
74+
75+
#[repr(C)]
76+
pub struct ManyIntegers {
77+
f: u8,
78+
g: u16,
79+
h: u32,
80+
i: u64,
81+
}
82+
83+
#[repr(C)]
84+
pub struct ManyNumerics {
85+
f: u8,
86+
g: u16,
87+
h: u32,
88+
i: u64,
89+
j: f32,
90+
k: f64,
91+
}
92+
93+
// CHECK: .visible .func f_u8_arg(
94+
// CHECK: .param .b32 f_u8_arg_param_0
95+
#[no_mangle]
96+
pub unsafe extern "C" fn f_u8_arg(_a: u8) {}
97+
98+
// CHECK: .visible .func f_u16_arg(
99+
// CHECK: .param .b32 f_u16_arg_param_0
100+
#[no_mangle]
101+
pub unsafe extern "C" fn f_u16_arg(_a: u16) {}
102+
103+
// CHECK: .visible .func f_u32_arg(
104+
// CHECK: .param .b32 f_u32_arg_param_0
105+
#[no_mangle]
106+
pub unsafe extern "C" fn f_u32_arg(_a: u32) {}
107+
108+
// CHECK: .visible .func f_u64_arg(
109+
// CHECK: .param .b64 f_u64_arg_param_0
110+
#[no_mangle]
111+
pub unsafe extern "C" fn f_u64_arg(_a: u64) {}
112+
113+
// CHECK: .visible .func f_u128_arg(
114+
// CHECK: .param .align 16 .b8 f_u128_arg_param_0[16]
115+
#[no_mangle]
116+
pub unsafe extern "C" fn f_u128_arg(_a: u128) {}
117+
118+
// CHECK: .visible .func f_i8_arg(
119+
// CHECK: .param .b32 f_i8_arg_param_0
120+
#[no_mangle]
121+
pub unsafe extern "C" fn f_i8_arg(_a: i8) {}
122+
123+
// CHECK: .visible .func f_i16_arg(
124+
// CHECK: .param .b32 f_i16_arg_param_0
125+
#[no_mangle]
126+
pub unsafe extern "C" fn f_i16_arg(_a: i16) {}
127+
128+
// CHECK: .visible .func f_i32_arg(
129+
// CHECK: .param .b32 f_i32_arg_param_0
130+
#[no_mangle]
131+
pub unsafe extern "C" fn f_i32_arg(_a: i32) {}
132+
133+
// CHECK: .visible .func f_i64_arg(
134+
// CHECK: .param .b64 f_i64_arg_param_0
135+
#[no_mangle]
136+
pub unsafe extern "C" fn f_i64_arg(_a: i64) {}
137+
138+
// CHECK: .visible .func f_i128_arg(
139+
// CHECK: .param .align 16 .b8 f_i128_arg_param_0[16]
140+
#[no_mangle]
141+
pub unsafe extern "C" fn f_i128_arg(_a: i128) {}
142+
143+
// CHECK: .visible .func f_f32_arg(
144+
// CHECK: .param .b32 f_f32_arg_param_0
145+
#[no_mangle]
146+
pub unsafe extern "C" fn f_f32_arg(_a: f32) {}
147+
148+
// CHECK: .visible .func f_f64_arg(
149+
// CHECK: .param .b64 f_f64_arg_param_0
150+
#[no_mangle]
151+
pub unsafe extern "C" fn f_f64_arg(_a: f64) {}
152+
153+
// CHECK: .visible .func f_single_u8_arg(
154+
// CHECK: .param .align 1 .b8 f_single_u8_arg_param_0[1]
155+
#[no_mangle]
156+
pub unsafe extern "C" fn f_single_u8_arg(_a: SingleU8) {}
157+
158+
// CHECK: .visible .func f_double_u8_arg(
159+
// CHECK: .param .align 1 .b8 f_double_u8_arg_param_0[2]
160+
#[no_mangle]
161+
pub unsafe extern "C" fn f_double_u8_arg(_a: DoubleU8) {}
162+
163+
// CHECK: .visible .func f_triple_u8_arg(
164+
// CHECK: .param .align 1 .b8 f_triple_u8_arg_param_0[3]
165+
#[no_mangle]
166+
pub unsafe extern "C" fn f_triple_u8_arg(_a: TripleU8) {}
167+
168+
// CHECK: .visible .func f_triple_u16_arg(
169+
// CHECK: .param .align 2 .b8 f_triple_u16_arg_param_0[6]
170+
#[no_mangle]
171+
pub unsafe extern "C" fn f_triple_u16_arg(_a: TripleU16) {}
172+
173+
// CHECK: .visible .func f_triple_u32_arg(
174+
// CHECK: .param .align 4 .b8 f_triple_u32_arg_param_0[12]
175+
#[no_mangle]
176+
pub unsafe extern "C" fn f_triple_u32_arg(_a: TripleU32) {}
177+
178+
// CHECK: .visible .func f_triple_u64_arg(
179+
// CHECK: .param .align 8 .b8 f_triple_u64_arg_param_0[24]
180+
#[no_mangle]
181+
pub unsafe extern "C" fn f_triple_u64_arg(_a: TripleU64) {}
182+
183+
// CHECK: .visible .func f_many_integers_arg(
184+
// CHECK: .param .align 8 .b8 f_many_integers_arg_param_0[16]
185+
#[no_mangle]
186+
pub unsafe extern "C" fn f_many_integers_arg(_a: ManyIntegers) {}
187+
188+
// CHECK: .visible .func f_double_float_arg(
189+
// CHECK: .param .align 4 .b8 f_double_float_arg_param_0[8]
190+
#[no_mangle]
191+
pub unsafe extern "C" fn f_double_float_arg(_a: DoubleFloat) {}
192+
193+
// CHECK: .visible .func f_triple_float_arg(
194+
// CHECK: .param .align 4 .b8 f_triple_float_arg_param_0[12]
195+
#[no_mangle]
196+
pub unsafe extern "C" fn f_triple_float_arg(_a: TripleFloat) {}
197+
198+
// CHECK: .visible .func f_triple_double_arg(
199+
// CHECK: .param .align 8 .b8 f_triple_double_arg_param_0[24]
200+
#[no_mangle]
201+
pub unsafe extern "C" fn f_triple_double_arg(_a: TripleDouble) {}
202+
203+
// CHECK: .visible .func f_many_numerics_arg(
204+
// CHECK: .param .align 8 .b8 f_many_numerics_arg_param_0[32]
205+
#[no_mangle]
206+
pub unsafe extern "C" fn f_many_numerics_arg(_a: ManyNumerics) {}

0 commit comments

Comments
 (0)