Skip to content

Commit a6d93ac

Browse files
committedMar 11, 2024·
Auto merge of rust-lang#122050 - erikdesjardins:sret, r=nikic
Stop using LLVM struct types for byval/sret For `byval` and `sret`, the type has no semantic meaning, only the size matters\*†. Using `[N x i8]` is a more direct way to specify that we want `N` bytes, and avoids relying on LLVM's struct layout. \*: The alignment would matter, if we didn't explicitly specify it. From what I can tell, we always specified the alignment for `sret`; for `byval`, we didn't until rust-lang#112157. †: For `byval`, the hidden copy may be impacted by padding in the LLVM struct type, i.e. padding bytes may not be copied. (I'm not sure if this is done today, but I think it would be legal.) But we manually pad our LLVM struct types specifically to avoid there ever being LLVM-visible padding, so that shouldn't be an issue. Split out from rust-lang#121577. r? `@nikic`
2 parents c69fda7 + f18c2f8 commit a6d93ac

17 files changed

+329
-132
lines changed
 

‎compiler/rustc_codegen_llvm/src/abi.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,10 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
424424
PassMode::Indirect { attrs, meta_attrs: _, on_stack } => {
425425
assert!(!on_stack);
426426
let i = apply(attrs);
427-
let sret = llvm::CreateStructRetAttr(cx.llcx, self.ret.layout.llvm_type(cx));
427+
let sret = llvm::CreateStructRetAttr(
428+
cx.llcx,
429+
cx.type_array(cx.type_i8(), self.ret.layout.size.bytes()),
430+
);
428431
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Argument(i), &[sret]);
429432
}
430433
PassMode::Cast { cast, pad_i32: _ } => {
@@ -437,7 +440,10 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
437440
PassMode::Ignore => {}
438441
PassMode::Indirect { attrs, meta_attrs: None, on_stack: true } => {
439442
let i = apply(attrs);
440-
let byval = llvm::CreateByValAttr(cx.llcx, arg.layout.llvm_type(cx));
443+
let byval = llvm::CreateByValAttr(
444+
cx.llcx,
445+
cx.type_array(cx.type_i8(), arg.layout.size.bytes()),
446+
);
441447
attributes::apply_to_llfn(llfn, llvm::AttributePlace::Argument(i), &[byval]);
442448
}
443449
PassMode::Direct(attrs)
@@ -486,7 +492,10 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
486492
PassMode::Indirect { attrs, meta_attrs: _, on_stack } => {
487493
assert!(!on_stack);
488494
let i = apply(bx.cx, attrs);
489-
let sret = llvm::CreateStructRetAttr(bx.cx.llcx, self.ret.layout.llvm_type(bx));
495+
let sret = llvm::CreateStructRetAttr(
496+
bx.cx.llcx,
497+
bx.cx.type_array(bx.cx.type_i8(), self.ret.layout.size.bytes()),
498+
);
490499
attributes::apply_to_callsite(callsite, llvm::AttributePlace::Argument(i), &[sret]);
491500
}
492501
PassMode::Cast { cast, pad_i32: _ } => {
@@ -513,7 +522,10 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
513522
PassMode::Ignore => {}
514523
PassMode::Indirect { attrs, meta_attrs: None, on_stack: true } => {
515524
let i = apply(bx.cx, attrs);
516-
let byval = llvm::CreateByValAttr(bx.cx.llcx, arg.layout.llvm_type(bx));
525+
let byval = llvm::CreateByValAttr(
526+
bx.cx.llcx,
527+
bx.cx.type_array(bx.cx.type_i8(), arg.layout.size.bytes()),
528+
);
517529
attributes::apply_to_callsite(
518530
callsite,
519531
llvm::AttributePlace::Argument(i),

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

+33-4
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,24 @@ pub enum PassMode {
4646
///
4747
/// The argument has a layout abi of `ScalarPair`.
4848
Pair(ArgAttributes, ArgAttributes),
49-
/// Pass the argument after casting it. See the `CastTarget` docs for details. The bool
50-
/// indicates if a `Reg::i32()` dummy argument is emitted before the real argument.
49+
/// Pass the argument after casting it. See the `CastTarget` docs for details.
50+
///
51+
/// `pad_i32` indicates if a `Reg::i32()` dummy argument is emitted before the real argument.
5152
Cast { pad_i32: bool, cast: Box<CastTarget> },
5253
/// Pass the argument indirectly via a hidden pointer.
54+
///
5355
/// The `meta_attrs` value, if any, is for the metadata (vtable or length) of an unsized
5456
/// argument. (This is the only mode that supports unsized arguments.)
57+
///
5558
/// `on_stack` defines that the value should be passed at a fixed stack offset in accordance to
5659
/// the ABI rather than passed using a pointer. This corresponds to the `byval` LLVM argument
57-
/// attribute (using the Rust type of this argument). `on_stack` cannot be true for unsized
58-
/// arguments, i.e., when `meta_attrs` is `Some`.
60+
/// attribute. The `byval` argument will use a byte array with the same size as the Rust type
61+
/// (which ensures that padding is preserved and that we do not rely on LLVM's struct layout),
62+
/// and will use the alignment specified in `attrs.pointee_align` (if `Some`) or the type's
63+
/// alignment (if `None`). This means that the alignment will not always
64+
/// match the Rust type's alignment; see documentation of `make_indirect_byval` for more info.
65+
///
66+
/// `on_stack` cannot be true for unsized arguments, i.e., when `meta_attrs` is `Some`.
5967
Indirect { attrs: ArgAttributes, meta_attrs: Option<ArgAttributes>, on_stack: bool },
6068
}
6169

@@ -596,6 +604,8 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
596604
}
597605
}
598606

607+
/// Pass this argument indirectly, by passing a (thin or fat) pointer to the argument instead.
608+
/// This is valid for both sized and unsized arguments.
599609
pub fn make_indirect(&mut self) {
600610
match self.mode {
601611
PassMode::Direct(_) | PassMode::Pair(_, _) => {
@@ -609,7 +619,26 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
609619
}
610620
}
611621

622+
/// Pass this argument indirectly, by placing it at a fixed stack offset.
623+
/// This corresponds to the `byval` LLVM argument attribute.
624+
/// This is only valid for sized arguments.
625+
///
626+
/// `byval_align` specifies the alignment of the `byval` stack slot, which does not need to
627+
/// correspond to the type's alignment. This will be `Some` if the target's ABI specifies that
628+
/// stack slots used for arguments passed by-value have specific alignment requirements which
629+
/// differ from the alignment used in other situations.
630+
///
631+
/// If `None`, the type's alignment is used.
632+
///
633+
/// If the resulting alignment differs from the type's alignment,
634+
/// the argument will be copied to an alloca with sufficient alignment,
635+
/// either in the caller (if the type's alignment is lower than the byval alignment)
636+
/// or in the callee† (if the type's alignment is higher than the byval alignment),
637+
/// to ensure that Rust code never sees an underaligned pointer.
638+
///
639+
/// † This is currently broken, see <https://github.com/rust-lang/rust/pull/122212>.
612640
pub fn make_indirect_byval(&mut self, byval_align: Option<Align>) {
641+
assert!(!self.layout.is_unsized(), "used byval ABI for unsized layout");
613642
self.make_indirect();
614643
match self.mode {
615644
PassMode::Indirect { ref mut attrs, meta_attrs: _, ref mut on_stack } => {

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

+2
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,8 @@ where
217217
match cls_or_mem {
218218
Err(Memory) => {
219219
if is_arg {
220+
// The x86_64 ABI doesn't have any special requirements for `byval` alignment,
221+
// the type's alignment is always used.
220222
arg.make_indirect_byval(None);
221223
} else {
222224
// `sret` parameter thus one less integer register available

‎tests/codegen/align-byval-vector.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@ pub struct DoubleFoo {
3737
}
3838

3939
extern "C" {
40-
// x86-linux: declare void @f({{.*}}byval(%Foo) align 4{{.*}})
41-
// x86-darwin: declare void @f({{.*}}byval(%Foo) align 16{{.*}})
40+
// x86-linux: declare void @f({{.*}}byval([32 x i8]) align 4{{.*}})
41+
// x86-darwin: declare void @f({{.*}}byval([32 x i8]) align 16{{.*}})
4242
fn f(foo: Foo);
4343

44-
// x86-linux: declare void @g({{.*}}byval(%DoubleFoo) align 4{{.*}})
45-
// x86-darwin: declare void @g({{.*}}byval(%DoubleFoo) align 16{{.*}})
44+
// x86-linux: declare void @g({{.*}}byval([64 x i8]) align 4{{.*}})
45+
// x86-darwin: declare void @g({{.*}}byval([64 x i8]) align 16{{.*}})
4646
fn g(foo: DoubleFoo);
4747
}
4848

‎tests/codegen/align-byval.rs

+46-46
Original file line numberDiff line numberDiff line change
@@ -107,20 +107,20 @@ pub unsafe fn call_na1(x: NaturalAlign1) {
107107
// CHECK: start:
108108

109109
// m68k: [[ALLOCA:%[a-z0-9+]]] = alloca %NaturalAlign1, align 1
110-
// m68k: call void @natural_align_1({{.*}}byval(%NaturalAlign1) align 1{{.*}} [[ALLOCA]])
110+
// m68k: call void @natural_align_1({{.*}}byval([2 x i8]) align 1{{.*}} [[ALLOCA]])
111111

112112
// wasm: [[ALLOCA:%[a-z0-9+]]] = alloca %NaturalAlign1, align 1
113-
// wasm: call void @natural_align_1({{.*}}byval(%NaturalAlign1) align 1{{.*}} [[ALLOCA]])
113+
// wasm: call void @natural_align_1({{.*}}byval([2 x i8]) align 1{{.*}} [[ALLOCA]])
114114

115115
// x86_64-linux: call void @natural_align_1(i16
116116

117117
// x86_64-windows: call void @natural_align_1(i16
118118

119119
// i686-linux: [[ALLOCA:%[a-z0-9+]]] = alloca %NaturalAlign1, align 4
120-
// i686-linux: call void @natural_align_1({{.*}}byval(%NaturalAlign1) align 4{{.*}} [[ALLOCA]])
120+
// i686-linux: call void @natural_align_1({{.*}}byval([2 x i8]) align 4{{.*}} [[ALLOCA]])
121121

122122
// i686-windows: [[ALLOCA:%[a-z0-9+]]] = alloca %NaturalAlign1, align 4
123-
// i686-windows: call void @natural_align_1({{.*}}byval(%NaturalAlign1) align 4{{.*}} [[ALLOCA]])
123+
// i686-windows: call void @natural_align_1({{.*}}byval([2 x i8]) align 4{{.*}} [[ALLOCA]])
124124
natural_align_1(x);
125125
}
126126

@@ -135,10 +135,10 @@ pub unsafe fn call_na2(x: NaturalAlign2) {
135135
// x86_64-windows-NEXT: call void @natural_align_2
136136

137137
// i686-linux: [[ALLOCA:%[0-9]+]] = alloca %NaturalAlign2, align 4
138-
// i686-linux: call void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}} [[ALLOCA]])
138+
// i686-linux: call void @natural_align_2({{.*}}byval([34 x i8]) align 4{{.*}} [[ALLOCA]])
139139

140140
// i686-windows: [[ALLOCA:%[0-9]+]] = alloca %NaturalAlign2, align 4
141-
// i686-windows: call void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}} [[ALLOCA]])
141+
// i686-windows: call void @natural_align_2({{.*}}byval([34 x i8]) align 4{{.*}} [[ALLOCA]])
142142
natural_align_2(x);
143143
}
144144

@@ -199,141 +199,141 @@ pub unsafe fn call_fa16(x: ForceAlign16) {
199199
}
200200

201201
extern "C" {
202-
// m68k: declare void @natural_align_1({{.*}}byval(%NaturalAlign1) align 1{{.*}})
202+
// m68k: declare void @natural_align_1({{.*}}byval([2 x i8]) align 1{{.*}})
203203

204-
// wasm: declare void @natural_align_1({{.*}}byval(%NaturalAlign1) align 1{{.*}})
204+
// wasm: declare void @natural_align_1({{.*}}byval([2 x i8]) align 1{{.*}})
205205

206206
// x86_64-linux: declare void @natural_align_1(i16)
207207

208208
// x86_64-windows: declare void @natural_align_1(i16)
209209

210-
// i686-linux: declare void @natural_align_1({{.*}}byval(%NaturalAlign1) align 4{{.*}})
210+
// i686-linux: declare void @natural_align_1({{.*}}byval([2 x i8]) align 4{{.*}})
211211

212-
// i686-windows: declare void @natural_align_1({{.*}}byval(%NaturalAlign1) align 4{{.*}})
212+
// i686-windows: declare void @natural_align_1({{.*}}byval([2 x i8]) align 4{{.*}})
213213
fn natural_align_1(x: NaturalAlign1);
214214

215-
// m68k: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 2{{.*}})
215+
// m68k: declare void @natural_align_2({{.*}}byval([34 x i8]) align 2{{.*}})
216216

217-
// wasm: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 2{{.*}})
217+
// wasm: declare void @natural_align_2({{.*}}byval([34 x i8]) align 2{{.*}})
218218

219-
// x86_64-linux: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 2{{.*}})
219+
// x86_64-linux: declare void @natural_align_2({{.*}}byval([34 x i8]) align 2{{.*}})
220220

221221
// x86_64-windows: declare void @natural_align_2(
222222
// x86_64-windows-NOT: byval
223223
// x86_64-windows-SAME: align 2{{.*}})
224224

225-
// i686-linux: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}})
225+
// i686-linux: declare void @natural_align_2({{.*}}byval([34 x i8]) align 4{{.*}})
226226

227-
// i686-windows: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}})
227+
// i686-windows: declare void @natural_align_2({{.*}}byval([34 x i8]) align 4{{.*}})
228228
fn natural_align_2(x: NaturalAlign2);
229229

230-
// m68k: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}})
230+
// m68k: declare void @force_align_4({{.*}}byval([20 x i8]) align 4{{.*}})
231231

232-
// wasm: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}})
232+
// wasm: declare void @force_align_4({{.*}}byval([20 x i8]) align 4{{.*}})
233233

234-
// x86_64-linux: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}})
234+
// x86_64-linux: declare void @force_align_4({{.*}}byval([20 x i8]) align 4{{.*}})
235235

236236
// x86_64-windows: declare void @force_align_4(
237237
// x86_64-windows-NOT: byval
238238
// x86_64-windows-SAME: align 4{{.*}})
239239

240-
// i686-linux: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}})
240+
// i686-linux: declare void @force_align_4({{.*}}byval([20 x i8]) align 4{{.*}})
241241

242-
// i686-windows: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}})
242+
// i686-windows: declare void @force_align_4({{.*}}byval([20 x i8]) align 4{{.*}})
243243
fn force_align_4(x: ForceAlign4);
244244

245-
// m68k: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 4{{.*}})
245+
// m68k: declare void @natural_align_8({{.*}}byval([24 x i8]) align 4{{.*}})
246246

247-
// wasm: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 8{{.*}})
247+
// wasm: declare void @natural_align_8({{.*}}byval([24 x i8]) align 8{{.*}})
248248

249-
// x86_64-linux: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 8{{.*}})
249+
// x86_64-linux: declare void @natural_align_8({{.*}}byval([24 x i8]) align 8{{.*}})
250250

251251
// x86_64-windows: declare void @natural_align_8(
252252
// x86_64-windows-NOT: byval
253253
// x86_64-windows-SAME: align 8{{.*}})
254254

255-
// i686-linux: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 4{{.*}})
255+
// i686-linux: declare void @natural_align_8({{.*}}byval([24 x i8]) align 4{{.*}})
256256

257-
// i686-windows: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 4{{.*}})
257+
// i686-windows: declare void @natural_align_8({{.*}}byval([24 x i8]) align 4{{.*}})
258258
fn natural_align_8(x: NaturalAlign8);
259259

260-
// m68k: declare void @force_align_8({{.*}}byval(%ForceAlign8) align 8{{.*}})
260+
// m68k: declare void @force_align_8({{.*}}byval([24 x i8]) align 8{{.*}})
261261

262-
// wasm: declare void @force_align_8({{.*}}byval(%ForceAlign8) align 8{{.*}})
262+
// wasm: declare void @force_align_8({{.*}}byval([24 x i8]) align 8{{.*}})
263263

264-
// x86_64-linux: declare void @force_align_8({{.*}}byval(%ForceAlign8) align 8{{.*}})
264+
// x86_64-linux: declare void @force_align_8({{.*}}byval([24 x i8]) align 8{{.*}})
265265

266266
// x86_64-windows: declare void @force_align_8(
267267
// x86_64-windows-NOT: byval
268268
// x86_64-windows-SAME: align 8{{.*}})
269269

270-
// i686-linux: declare void @force_align_8({{.*}}byval(%ForceAlign8) align 4{{.*}})
270+
// i686-linux: declare void @force_align_8({{.*}}byval([24 x i8]) align 4{{.*}})
271271

272272
// i686-windows: declare void @force_align_8(
273273
// i686-windows-NOT: byval
274274
// i686-windows-SAME: align 8{{.*}})
275275
fn force_align_8(x: ForceAlign8);
276276

277-
// m68k: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 4{{.*}})
277+
// m68k: declare void @lower_fa8({{.*}}byval([24 x i8]) align 4{{.*}})
278278

279-
// wasm: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 8{{.*}})
279+
// wasm: declare void @lower_fa8({{.*}}byval([24 x i8]) align 8{{.*}})
280280

281-
// x86_64-linux: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 8{{.*}})
281+
// x86_64-linux: declare void @lower_fa8({{.*}}byval([24 x i8]) align 8{{.*}})
282282

283283
// x86_64-windows: declare void @lower_fa8(
284284
// x86_64-windows-NOT: byval
285285
// x86_64-windows-SAME: align 8{{.*}})
286286

287-
// i686-linux: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 4{{.*}})
287+
// i686-linux: declare void @lower_fa8({{.*}}byval([24 x i8]) align 4{{.*}})
288288

289-
// i686-windows: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 4{{.*}})
289+
// i686-windows: declare void @lower_fa8({{.*}}byval([24 x i8]) align 4{{.*}})
290290
fn lower_fa8(x: LowerFA8);
291291

292-
// m68k: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 8{{.*}})
292+
// m68k: declare void @wrapped_fa8({{.*}}byval([24 x i8]) align 8{{.*}})
293293

294-
// wasm: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 8{{.*}})
294+
// wasm: declare void @wrapped_fa8({{.*}}byval([24 x i8]) align 8{{.*}})
295295

296-
// x86_64-linux: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 8{{.*}})
296+
// x86_64-linux: declare void @wrapped_fa8({{.*}}byval([24 x i8]) align 8{{.*}})
297297

298298
// x86_64-windows: declare void @wrapped_fa8(
299299
// x86_64-windows-NOT: byval
300300
// x86_64-windows-SAME: align 8{{.*}})
301301

302-
// i686-linux: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 4{{.*}})
302+
// i686-linux: declare void @wrapped_fa8({{.*}}byval([24 x i8]) align 4{{.*}})
303303

304304
// i686-windows: declare void @wrapped_fa8(
305305
// i686-windows-NOT: byval
306306
// i686-windows-SAME: align 8{{.*}})
307307
fn wrapped_fa8(x: WrappedFA8);
308308

309-
// m68k: declare void @transparent_fa8({{.*}}byval(%TransparentFA8) align 8{{.*}})
309+
// m68k: declare void @transparent_fa8({{.*}}byval([24 x i8]) align 8{{.*}})
310310

311-
// wasm: declare void @transparent_fa8({{.*}}byval(%TransparentFA8) align 8{{.*}})
311+
// wasm: declare void @transparent_fa8({{.*}}byval([24 x i8]) align 8{{.*}})
312312

313-
// x86_64-linux: declare void @transparent_fa8({{.*}}byval(%TransparentFA8) align 8{{.*}})
313+
// x86_64-linux: declare void @transparent_fa8({{.*}}byval([24 x i8]) align 8{{.*}})
314314

315315
// x86_64-windows: declare void @transparent_fa8(
316316
// x86_64-windows-NOT: byval
317317
// x86_64-windows-SAME: align 8{{.*}})
318318

319-
// i686-linux: declare void @transparent_fa8({{.*}}byval(%TransparentFA8) align 4{{.*}})
319+
// i686-linux: declare void @transparent_fa8({{.*}}byval([24 x i8]) align 4{{.*}})
320320

321321
// i686-windows: declare void @transparent_fa8(
322322
// i686-windows-NOT: byval
323323
// i686-windows-SAME: align 8{{.*}})
324324
fn transparent_fa8(x: TransparentFA8);
325325

326-
// m68k: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 16{{.*}})
326+
// m68k: declare void @force_align_16({{.*}}byval([80 x i8]) align 16{{.*}})
327327

328-
// wasm: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 16{{.*}})
328+
// wasm: declare void @force_align_16({{.*}}byval([80 x i8]) align 16{{.*}})
329329

330-
// x86_64-linux: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 16{{.*}})
330+
// x86_64-linux: declare void @force_align_16({{.*}}byval([80 x i8]) align 16{{.*}})
331331

332332
// x86_64-windows: declare void @force_align_16(
333333
// x86_64-windows-NOT: byval
334334
// x86_64-windows-SAME: align 16{{.*}})
335335

336-
// i686-linux: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 4{{.*}})
336+
// i686-linux: declare void @force_align_16({{.*}}byval([80 x i8]) align 4{{.*}})
337337

338338
// i686-windows: declare void @force_align_16(
339339
// i686-windows-NOT: byval

‎tests/codegen/align-enum.rs

-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ pub enum Align64 {
88
A(u32),
99
B(u32),
1010
}
11-
// CHECK: %Align64 = type { i32, [15 x i32] }
1211

1312
pub struct Nested64 {
1413
a: u8,

‎tests/codegen/align-struct.rs

-4
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,23 @@
55

66
#[repr(align(64))]
77
pub struct Align64(i32);
8-
// CHECK: %Align64 = type { i32, [15 x i32] }
98

109
pub struct Nested64 {
1110
a: Align64,
1211
b: i32,
1312
c: i32,
1413
d: i8,
1514
}
16-
// CHECK: %Nested64 = type { %Align64, i32, i32, i8, [55 x i8] }
1715

1816
pub enum Enum4 {
1917
A(i32),
2018
B(i32),
2119
}
22-
// No Aggregate type, and hence nothing in LLVM IR.
2320

2421
pub enum Enum64 {
2522
A(Align64),
2623
B(i32),
2724
}
28-
// CHECK: %Enum64 = type { i32, [31 x i32] }
2925

3026
// CHECK-LABEL: @align64
3127
#[no_mangle]

‎tests/codegen/function-arguments-noopt.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ pub fn borrow_call(x: &i32, f: fn(&i32) -> &i32) -> &i32 {
4242
f(x)
4343
}
4444

45-
// CHECK: void @struct_(ptr sret(%S) align 4{{( %_0)?}}, ptr align 4 %x)
45+
// CHECK: void @struct_(ptr sret([32 x i8]) align 4{{( %_0)?}}, ptr align 4 %x)
4646
#[no_mangle]
4747
pub fn struct_(x: S) -> S {
4848
x
@@ -51,7 +51,7 @@ pub fn struct_(x: S) -> S {
5151
// CHECK-LABEL: @struct_call
5252
#[no_mangle]
5353
pub fn struct_call(x: S, f: fn(S) -> S) -> S {
54-
// CHECK: call void %f(ptr sret(%S) align 4{{( %_0)?}}, ptr align 4 %{{.+}})
54+
// CHECK: call void %f(ptr sret([32 x i8]) align 4{{( %_0)?}}, ptr align 4 %{{.+}})
5555
f(x)
5656
}
5757

‎tests/codegen/function-arguments.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ pub fn notunpin_box(x: Box<NotUnpin>) -> Box<NotUnpin> {
198198
x
199199
}
200200

201-
// CHECK: @struct_return(ptr noalias nocapture noundef sret(%S) align 4 dereferenceable(32){{( %_0)?}})
201+
// CHECK: @struct_return(ptr noalias nocapture noundef sret([32 x i8]) align 4 dereferenceable(32){{( %_0)?}})
202202
#[no_mangle]
203203
pub fn struct_return() -> S {
204204
S {

‎tests/codegen/loongarch-abi/loongarch64-lp64d-abi.rs

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1-
//@ compile-flags: -C no-prepopulate-passes
2-
//@ only-loongarch64
3-
//@ only-linux
1+
//@ compile-flags: -O -C no-prepopulate-passes --target loongarch64-unknown-linux-gnu
2+
//@ needs-llvm-components: loongarch
43

4+
#![feature(no_core, lang_items)]
55
#![crate_type = "lib"]
6+
#![no_std]
7+
#![no_core]
8+
9+
#[lang="sized"] trait Sized { }
10+
#[lang="freeze"] trait Freeze { }
11+
#[lang="copy"] trait Copy { }
612

713
// CHECK: define void @f_fpr_tracking(double %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7, i8 noundef zeroext %i)
814
#[no_mangle]
@@ -254,7 +260,7 @@ pub struct IntDoubleInt {
254260
#[no_mangle]
255261
pub extern "C" fn f_int_double_int_s_arg(a: IntDoubleInt) {}
256262

257-
// CHECK: define void @f_ret_int_double_int_s(ptr noalias nocapture noundef sret(%IntDoubleInt) align 8 dereferenceable(24) %_0)
263+
// CHECK: define void @f_ret_int_double_int_s(ptr noalias nocapture noundef sret([24 x i8]) align 8 dereferenceable(24) %_0)
258264
#[no_mangle]
259265
pub extern "C" fn f_ret_int_double_int_s() -> IntDoubleInt {
260266
IntDoubleInt { a: 1, b: 2., c: 3 }

‎tests/codegen/mem-replace-big-type.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub fn replace_big(dst: &mut Big, src: Big) -> Big {
2323
// CHECK-NOT: call void @llvm.memcpy
2424

2525
// For a large type, we expect exactly three `memcpy`s
26-
// CHECK-LABEL: define internal void @{{.+}}mem{{.+}}replace{{.+}}sret(%Big)
26+
// CHECK-LABEL: define internal void @{{.+}}mem{{.+}}replace{{.+}}sret([56 x i8])
2727
// CHECK-NOT: call void @llvm.memcpy
2828
// CHECK: call void @llvm.memcpy.{{.+}}(ptr align 8 %result, ptr align 8 %dest, i{{.*}} 56, i1 false)
2929
// CHECK-NOT: call void @llvm.memcpy
+37-20
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,40 @@
1-
//@ revisions: arm mips thumb wasm32
2-
//@ compile-flags: -C no-prepopulate-passes
3-
//
4-
//@[arm] only-arm
5-
//@[mips] only-mips
6-
//@[thumb] only-thumb
7-
//@[wasm32] only-wasm32
8-
//@ ignore-emscripten
1+
//@ revisions: arm-linux arm-android armv7-linux armv7-android mips thumb sparc
2+
//@ compile-flags: -O -C no-prepopulate-passes
3+
4+
//@[arm-linux] compile-flags: --target arm-unknown-linux-gnueabi
5+
//@[arm-linux] needs-llvm-components: arm
6+
//@[arm-android] compile-flags: --target arm-linux-androideabi
7+
//@[arm-android] needs-llvm-components: arm
8+
//@[armv7-linux] compile-flags: --target armv7-unknown-linux-gnueabi
9+
//@[armv7-linux] needs-llvm-components: arm
10+
//@[armv7-android] compile-flags: --target armv7-linux-androideabi
11+
//@[armv7-android] needs-llvm-components: arm
12+
//@[mips] compile-flags: --target mips-unknown-linux-gnu
13+
//@[mips] needs-llvm-components: mips
14+
//@[thumb] compile-flags: --target thumbv7neon-linux-androideabi
15+
//@[thumb] needs-llvm-components: arm
16+
//@[sparc] compile-flags: --target sparc-unknown-linux-gnu
17+
//@[sparc] needs-llvm-components: sparc
18+
919
// See ./transparent.rs
1020
// Some platforms pass large aggregates using immediate arrays in LLVMIR
1121
// Other platforms pass large aggregates using struct pointer in LLVMIR
1222
// This covers the "immediate array" case.
1323

14-
#![feature(transparent_unions)]
24+
#![feature(no_core, lang_items, transparent_unions)]
25+
#![crate_type = "lib"]
26+
#![no_std]
27+
#![no_core]
28+
29+
#[lang="sized"] trait Sized { }
30+
#[lang="freeze"] trait Freeze { }
31+
#[lang="copy"] trait Copy { }
1532

16-
#![crate_type="lib"]
33+
impl Copy for [u32; 16] {}
34+
impl Copy for BigS {}
35+
impl Copy for BigU {}
1736

1837

19-
#[derive(Clone, Copy)]
2038
#[repr(C)]
2139
pub struct BigS([u32; 16]);
2240

@@ -33,24 +51,23 @@ pub enum TeBigS {
3351
Variant(BigS),
3452
}
3553

36-
// CHECK: define void @test_BigS(ptr [[BIGS_RET_ATTRS1:.*]] sret(%BigS) [[BIGS_RET_ATTRS2:.*]], [16 x i32]
54+
// CHECK: define void @test_BigS(ptr [[BIGS_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGS_RET_ATTRS2:.*]], [16 x i32]
3755
#[no_mangle]
3856
pub extern fn test_BigS(_: BigS) -> BigS { loop {} }
3957

40-
// CHECK: define void @test_TsBigS(ptr [[BIGS_RET_ATTRS1]] sret(%TsBigS) [[BIGS_RET_ATTRS2]], [16 x i32]
58+
// CHECK: define void @test_TsBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], [16 x i32]
4159
#[no_mangle]
4260
pub extern fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} }
4361

44-
// CHECK: define void @test_TuBigS(ptr [[BIGS_RET_ATTRS1]] sret(%TuBigS) [[BIGS_RET_ATTRS2]], [16 x i32]
62+
// CHECK: define void @test_TuBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], [16 x i32]
4563
#[no_mangle]
4664
pub extern fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} }
4765

48-
// CHECK: define void @test_TeBigS(ptr [[BIGS_RET_ATTRS1]] sret(%"TeBigS::Variant") [[BIGS_RET_ATTRS2]], [16 x i32]
66+
// CHECK: define void @test_TeBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], [16 x i32]
4967
#[no_mangle]
5068
pub extern fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} }
5169

5270

53-
#[derive(Clone, Copy)]
5471
#[repr(C)]
5572
pub union BigU {
5673
foo: [u32; 16],
@@ -69,18 +86,18 @@ pub enum TeBigU {
6986
Variant(BigU),
7087
}
7188

72-
// CHECK: define void @test_BigU(ptr [[BIGU_RET_ATTRS1:.*]] sret(%BigU) [[BIGU_RET_ATTRS2:.*]], [16 x i32]
89+
// CHECK: define void @test_BigU(ptr [[BIGU_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], [16 x i32]
7390
#[no_mangle]
7491
pub extern fn test_BigU(_: BigU) -> BigU { loop {} }
7592

76-
// CHECK: define void @test_TsBigU(ptr [[BIGU_RET_ATTRS1]] sret(%TsBigU) [[BIGU_RET_ATTRS2]], [16 x i32]
93+
// CHECK: define void @test_TsBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2]], [16 x i32]
7794
#[no_mangle]
7895
pub extern fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} }
7996

80-
// CHECK: define void @test_TuBigU(ptr [[BIGU_RET_ATTRS1]] sret(%TuBigU) [[BIGU_RET_ATTRS2]], [16 x i32]
97+
// CHECK: define void @test_TuBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2]], [16 x i32]
8198
#[no_mangle]
8299
pub extern fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} }
83100

84-
// CHECK: define void @test_TeBigU(ptr [[BIGU_RET_ATTRS1]] sret(%"TeBigU::Variant") [[BIGU_RET_ATTRS2]], [16 x i32]
101+
// CHECK: define void @test_TeBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2]], [16 x i32]
85102
#[no_mangle]
86103
pub extern fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} }

‎tests/codegen/repr/transparent-mips64.rs

+25-15
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,26 @@
1-
//@ compile-flags: -C no-prepopulate-passes
2-
//
1+
//@ revisions: mips64 mips64el
2+
//@ compile-flags: -O -C no-prepopulate-passes
3+
4+
//@[mips64] compile-flags: --target mips64-unknown-linux-gnuabi64
5+
//@[mips64] needs-llvm-components: mips
6+
//@[mips64el] compile-flags: --target mips64el-unknown-linux-gnuabi64
7+
//@[mips64el] needs-llvm-components: mips
38

4-
//@ only-mips64
59
// See ./transparent.rs
610

7-
#![feature(transparent_unions)]
11+
#![feature(no_core, lang_items, transparent_unions)]
12+
#![crate_type = "lib"]
13+
#![no_std]
14+
#![no_core]
815

9-
#![crate_type="lib"]
16+
#[lang="sized"] trait Sized { }
17+
#[lang="freeze"] trait Freeze { }
18+
#[lang="copy"] trait Copy { }
1019

20+
impl Copy for [u32; 16] {}
21+
impl Copy for BigS {}
22+
impl Copy for BigU {}
1123

12-
#[derive(Clone, Copy)]
1324
#[repr(C)]
1425
pub struct BigS([u32; 16]);
1526

@@ -26,24 +37,23 @@ pub enum TeBigS {
2637
Variant(BigS),
2738
}
2839

29-
// CHECK: define void @test_BigS(%BigS* [[BIGS_RET_ATTRS1:.*]] sret(%BigS) [[BIGS_RET_ATTRS2:.*]], [8 x i64]
40+
// CHECK: define void @test_BigS(ptr [[BIGS_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGS_RET_ATTRS2:.*]], [8 x i64]
3041
#[no_mangle]
3142
pub extern fn test_BigS(_: BigS) -> BigS { loop {} }
3243

33-
// CHECK: define void @test_TsBigS(%TsBigS* [[BIGS_RET_ATTRS1]] sret(%TsBigS) [[BIGS_RET_ATTRS2]], [8 x i64]
44+
// CHECK: define void @test_TsBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], [8 x i64]
3445
#[no_mangle]
3546
pub extern fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} }
3647

37-
// CHECK: define void @test_TuBigS(%TuBigS* [[BIGS_RET_ATTRS1]] sret(%TuBigS) [[BIGS_RET_ATTRS2]], [8 x i64]
48+
// CHECK: define void @test_TuBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], [8 x i64]
3849
#[no_mangle]
3950
pub extern fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} }
4051

41-
// CHECK: define void @test_TeBigS(%"TeBigS::Variant"* [[BIGS_RET_ATTRS1]] sret(%"TeBigS::Variant") [[BIGS_RET_ATTRS2]], [8 x i64]
52+
// CHECK: define void @test_TeBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], [8 x i64]
4253
#[no_mangle]
4354
pub extern fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} }
4455

4556

46-
#[derive(Clone, Copy)]
4757
#[repr(C)]
4858
pub union BigU {
4959
foo: [u32; 16],
@@ -62,18 +72,18 @@ pub enum TeBigU {
6272
Variant(BigU),
6373
}
6474

65-
// CHECK: define void @test_BigU(%BigU* [[BIGU_RET_ATTRS1:.*]] sret(%BigU) [[BIGU_RET_ATTRS2:.*]], [8 x i64]
75+
// CHECK: define void @test_BigU(ptr [[BIGU_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], [8 x i64]
6676
#[no_mangle]
6777
pub extern fn test_BigU(_: BigU) -> BigU { loop {} }
6878

69-
// CHECK: define void @test_TsBigU(%TsBigU* [[BIGU_RET_ATTRS1]] sret(%TsBigU) [[BIGU_RET_ATTRS2]], [8 x i64]
79+
// CHECK: define void @test_TsBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2]], [8 x i64]
7080
#[no_mangle]
7181
pub extern fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} }
7282

73-
// CHECK: define void @test_TuBigU(%TuBigU* [[BIGU_RET_ATTRS1]] sret(%TuBigU) [[BIGU_RET_ATTRS2]], [8 x i64]
83+
// CHECK: define void @test_TuBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2]], [8 x i64]
7484
#[no_mangle]
7585
pub extern fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} }
7686

77-
// CHECK: define void @test_TeBigU(%"TeBigU::Variant"* [[BIGU_RET_ATTRS1]] sret(%"TeBigU::Variant") [[BIGU_RET_ATTRS2]], [8 x i64]
87+
// CHECK: define void @test_TeBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2]], [8 x i64]
7888
#[no_mangle]
7989
pub extern fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} }
+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
//@ compile-flags: -O -C no-prepopulate-passes --target sparc64-unknown-linux-gnu
2+
//@ needs-llvm-components: sparc
3+
4+
// See ./transparent.rs
5+
6+
#![feature(no_core, lang_items, transparent_unions)]
7+
#![crate_type = "lib"]
8+
#![no_std]
9+
#![no_core]
10+
11+
#[lang="sized"] trait Sized { }
12+
#[lang="freeze"] trait Freeze { }
13+
#[lang="copy"] trait Copy { }
14+
15+
impl Copy for [u32; 16] {}
16+
impl Copy for BigS {}
17+
impl Copy for BigU {}
18+
19+
20+
#[repr(C)]
21+
pub struct BigS([u32; 16]);
22+
23+
#[repr(transparent)]
24+
pub struct TsBigS(BigS);
25+
26+
#[repr(transparent)]
27+
pub union TuBigS {
28+
field: BigS,
29+
}
30+
31+
#[repr(transparent)]
32+
pub enum TeBigS {
33+
Variant(BigS),
34+
}
35+
36+
// CHECK: define{{.*}}void @test_BigS(ptr [[BIGS_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGS_RET_ATTRS2:.*]], ptr
37+
// CHECK-NOT: byval
38+
// CHECK-SAME: %{{[0-9a-z_]+}})
39+
#[no_mangle]
40+
pub extern "C" fn test_BigS(_: BigS) -> BigS { loop {} }
41+
42+
// CHECK: define{{.*}}void @test_TsBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], ptr
43+
// CHECK-NOT: byval
44+
// CHECK-SAME: %{{[0-9a-z_]+}})
45+
#[no_mangle]
46+
pub extern "C" fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} }
47+
48+
// CHECK: define{{.*}}void @test_TuBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], ptr
49+
// CHECK-NOT: byval
50+
// CHECK-SAME: %{{[0-9a-z_]+}})
51+
#[no_mangle]
52+
pub extern "C" fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} }
53+
54+
// CHECK: define{{.*}}void @test_TeBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], ptr
55+
// CHECK-NOT: byval
56+
// CHECK-SAME: %{{[0-9a-z_]+}})
57+
#[no_mangle]
58+
pub extern "C" fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} }
59+
60+
61+
#[repr(C)]
62+
pub union BigU {
63+
foo: [u32; 16],
64+
}
65+
66+
#[repr(transparent)]
67+
pub struct TsBigU(BigU);
68+
69+
#[repr(transparent)]
70+
pub union TuBigU {
71+
field: BigU,
72+
}
73+
74+
#[repr(transparent)]
75+
pub enum TeBigU {
76+
Variant(BigU),
77+
}
78+
79+
// CHECK: define{{.*}}void @test_BigU(ptr [[BIGU_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], ptr
80+
// CHECK-NOT: byval
81+
// CHECK-SAME: %{{[0-9a-z_]+}})
82+
#[no_mangle]
83+
pub extern "C" fn test_BigU(_: BigU) -> BigU { loop {} }
84+
85+
// CHECK: define{{.*}}void @test_TsBigU(ptr [[BIGU_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], ptr
86+
// CHECK-NOT: byval
87+
// CHECK-SAME: %{{[0-9a-z_]+}})
88+
#[no_mangle]
89+
pub extern "C" fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} }
90+
91+
// CHECK: define{{.*}}void @test_TuBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], ptr
92+
// CHECK-NOT: byval
93+
// CHECK-SAME: %{{[0-9a-z_]+}})
94+
#[no_mangle]
95+
pub extern "C" fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} }
96+
97+
// CHECK: define{{.*}}void @test_TeBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], ptr
98+
// CHECK-NOT: byval
99+
// CHECK-SAME: %{{[0-9a-z_]+}})
100+
#[no_mangle]
101+
pub extern "C" fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} }

‎tests/codegen/repr/transparent-struct-ptr.rs

+31-19
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,36 @@
1-
//@ revisions: x32 x64 sparc sparc64
1+
//@ revisions: i686-linux i686-freebsd x64-linux x64-apple wasm32
22
//@ compile-flags: -O -C no-prepopulate-passes
3-
//
4-
//@[x32] only-x86
5-
//@[x64] only-x86_64
6-
//@[sparc] only-sparc
7-
//@[sparc64] only-sparc64
8-
//@ ignore-windows
3+
4+
//@[i686-linux] compile-flags: --target i686-unknown-linux-gnu
5+
//@[i686-linux] needs-llvm-components: x86
6+
//@[i686-freebsd] compile-flags: --target i686-unknown-freebsd
7+
//@[i686-freebsd] needs-llvm-components: x86
8+
//@[x64-linux] compile-flags: --target x86_64-unknown-linux-gnu
9+
//@[x64-linux] needs-llvm-components: x86
10+
//@[x64-apple] compile-flags: --target x86_64-apple-darwin
11+
//@[x64-apple] needs-llvm-components: x86
12+
//@[wasm32] compile-flags: --target wasm32-wasi
13+
//@[wasm32] needs-llvm-components: webassembly
14+
915
// See ./transparent.rs
1016
// Some platforms pass large aggregates using immediate arrays in LLVMIR
1117
// Other platforms pass large aggregates using struct pointer in LLVMIR
1218
// This covers the "struct pointer" case.
1319

20+
#![feature(no_core, lang_items, transparent_unions)]
21+
#![crate_type = "lib"]
22+
#![no_std]
23+
#![no_core]
1424

15-
#![feature(transparent_unions)]
25+
#[lang="sized"] trait Sized { }
26+
#[lang="freeze"] trait Freeze { }
27+
#[lang="copy"] trait Copy { }
1628

17-
#![crate_type="lib"]
29+
impl Copy for [u32; 16] {}
30+
impl Copy for BigS {}
31+
impl Copy for BigU {}
1832

1933

20-
#[derive(Clone, Copy)]
2134
#[repr(C)]
2235
pub struct BigS([u32; 16]);
2336

@@ -34,24 +47,23 @@ pub enum TeBigS {
3447
Variant(BigS),
3548
}
3649

37-
// CHECK: define{{.*}}void @test_BigS(ptr [[BIGS_RET_ATTRS1:.*]] sret(%BigS) [[BIGS_RET_ATTRS2:.*]], ptr [[BIGS_ARG_ATTRS1:.*]] byval(%BigS) [[BIGS_ARG_ATTRS2:.*]])
50+
// CHECK: define{{.*}}void @test_BigS(ptr [[BIGS_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGS_RET_ATTRS2:.*]], ptr [[BIGS_ARG_ATTRS1:.*]] byval([64 x i8]) [[BIGS_ARG_ATTRS2:.*]])
3851
#[no_mangle]
3952
pub extern "C" fn test_BigS(_: BigS) -> BigS { loop {} }
4053

41-
// CHECK: define{{.*}}void @test_TsBigS(ptr [[BIGS_RET_ATTRS1]] sret(%TsBigS) [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval(%TsBigS) [[BIGS_ARG_ATTRS2:.*]])
54+
// CHECK: define{{.*}}void @test_TsBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval([64 x i8]) [[BIGS_ARG_ATTRS2:.*]])
4255
#[no_mangle]
4356
pub extern "C" fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} }
4457

45-
// CHECK: define{{.*}}void @test_TuBigS(ptr [[BIGS_RET_ATTRS1]] sret(%TuBigS) [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval(%TuBigS) [[BIGS_ARG_ATTRS2:.*]])
58+
// CHECK: define{{.*}}void @test_TuBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval([64 x i8]) [[BIGS_ARG_ATTRS2:.*]])
4659
#[no_mangle]
4760
pub extern "C" fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} }
4861

49-
// CHECK: define{{.*}}void @test_TeBigS(ptr [[BIGS_RET_ATTRS1]] sret(%"TeBigS::Variant") [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval(%"TeBigS::Variant") [[BIGS_ARG_ATTRS2]])
62+
// CHECK: define{{.*}}void @test_TeBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval([64 x i8]) [[BIGS_ARG_ATTRS2]])
5063
#[no_mangle]
5164
pub extern "C" fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} }
5265

5366

54-
#[derive(Clone, Copy)]
5567
#[repr(C)]
5668
pub union BigU {
5769
foo: [u32; 16],
@@ -70,18 +82,18 @@ pub enum TeBigU {
7082
Variant(BigU),
7183
}
7284

73-
// CHECK: define{{.*}}void @test_BigU(ptr [[BIGU_RET_ATTRS1:.*]] sret(%BigU) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1:.*]] byval(%BigU) [[BIGU_ARG_ATTRS2:.*]])
85+
// CHECK: define{{.*}}void @test_BigU(ptr [[BIGU_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1:.*]] byval([64 x i8]) [[BIGU_ARG_ATTRS2:.*]])
7486
#[no_mangle]
7587
pub extern "C" fn test_BigU(_: BigU) -> BigU { loop {} }
7688

77-
// CHECK: define{{.*}}void @test_TsBigU(ptr [[BIGU_RET_ATTRS1:.*]] sret(%TsBigU) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval(%TsBigU) [[BIGU_ARG_ATTRS2]])
89+
// CHECK: define{{.*}}void @test_TsBigU(ptr [[BIGU_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval([64 x i8]) [[BIGU_ARG_ATTRS2]])
7890
#[no_mangle]
7991
pub extern "C" fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} }
8092

81-
// CHECK: define{{.*}}void @test_TuBigU(ptr [[BIGU_RET_ATTRS1]] sret(%TuBigU) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval(%TuBigU) [[BIGU_ARG_ATTRS2]])
93+
// CHECK: define{{.*}}void @test_TuBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval([64 x i8]) [[BIGU_ARG_ATTRS2]])
8294
#[no_mangle]
8395
pub extern "C" fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} }
8496

85-
// CHECK: define{{.*}}void @test_TeBigU(ptr [[BIGU_RET_ATTRS1]] sret(%"TeBigU::Variant") [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval(%"TeBigU::Variant") [[BIGU_ARG_ATTRS2]])
97+
// CHECK: define{{.*}}void @test_TeBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval([64 x i8]) [[BIGU_ARG_ATTRS2]])
8698
#[no_mangle]
8799
pub extern "C" fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} }

‎tests/codegen/repr/transparent-sysv64.rs

+18-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,21 @@
1-
//@ only-x86_64
2-
3-
//@ compile-flags: -C no-prepopulate-passes
4-
5-
#![crate_type="lib"]
1+
//@ revisions: linux apple windows
2+
//@ compile-flags: -O -C no-prepopulate-passes
3+
4+
//@[linux] compile-flags: --target x86_64-unknown-linux-gnu
5+
//@[linux] needs-llvm-components: x86
6+
//@[apple] compile-flags: --target x86_64-apple-darwin
7+
//@[apple] needs-llvm-components: x86
8+
//@[windows] compile-flags: --target x86_64-pc-windows-msvc
9+
//@[windows] needs-llvm-components: x86
10+
11+
#![feature(no_core, lang_items)]
12+
#![crate_type = "lib"]
13+
#![no_std]
14+
#![no_core]
15+
16+
#[lang="sized"] trait Sized { }
17+
#[lang="freeze"] trait Freeze { }
18+
#[lang="copy"] trait Copy { }
619

720
#[repr(C)]
821
pub struct Rgb8 { r: u8, g: u8, b: u8 }

‎tests/codegen/simd/unpadded-simd.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// See #87254.
44

55
#![crate_type = "lib"]
6-
#![feature(repr_simd)]
6+
#![feature(repr_simd, abi_unadjusted)]
77

88
#[derive(Copy, Clone)]
99
#[repr(simd)]
@@ -14,6 +14,6 @@ pub struct int16x4x2_t(pub int16x4_t, pub int16x4_t);
1414

1515
// CHECK: %int16x4x2_t = type { <4 x i16>, <4 x i16> }
1616
#[no_mangle]
17-
fn takes_int16x4x2_t(t: int16x4x2_t) -> int16x4x2_t {
17+
extern "unadjusted" fn takes_int16x4x2_t(t: int16x4x2_t) -> int16x4x2_t {
1818
t
1919
}

0 commit comments

Comments
 (0)
Please sign in to comment.