Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 52e34ca

Browse files
committedMar 6, 2024·
Auto merge of rust-lang#122053 - erikdesjardins:alloca, r=<try>
Stop using LLVM struct types for alloca The alloca type has no semantic meaning, only the size (and alignment, but we specify it explicitly) matter. Using `[N x i8]` is a more direct way to specify that we want `N` bytes, and avoids relying on LLVM's struct layout. It is likely that a future LLVM version will change to an untyped alloca representation. Split out from rust-lang#121577. r? `@ghost`
2 parents 8039906 + 26be569 commit 52e34ca

28 files changed

+106
-108
lines changed
 

‎compiler/rustc_codegen_gcc/src/builder.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -734,7 +734,18 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
734734
self.gcc_checked_binop(oop, typ, lhs, rhs)
735735
}
736736

737-
fn alloca(&mut self, ty: Type<'gcc>, align: Align) -> RValue<'gcc> {
737+
fn alloca(&mut self, size: Size, align: Align) -> RValue<'gcc> {
738+
let ty = self.cx.type_array(self.cx.type_i8(), size.bytes()).get_aligned(align.bytes());
739+
// TODO(antoyo): It might be better to return a LValue, but fixing the rustc API is non-trivial.
740+
self.stack_var_count.set(self.stack_var_count.get() + 1);
741+
self.current_func().new_local(None, ty, &format!("stack_var_{}", self.stack_var_count.get())).get_address(None)
742+
}
743+
744+
fn dynamic_alloca(&mut self, _len: RValue<'gcc>, _align: Align) -> RValue<'gcc> {
745+
unimplemented!();
746+
}
747+
748+
fn typed_alloca(&mut self, ty: Type<'gcc>, align: Align) -> RValue<'gcc> {
738749
// FIXME(antoyo): this check that we don't call get_aligned() a second time on a type.
739750
// Ideally, we shouldn't need to do this check.
740751
let aligned_type =
@@ -749,10 +760,6 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
749760
self.current_func().new_local(None, aligned_type, &format!("stack_var_{}", self.stack_var_count.get())).get_address(None)
750761
}
751762

752-
fn byte_array_alloca(&mut self, _len: RValue<'gcc>, _align: Align) -> RValue<'gcc> {
753-
unimplemented!();
754-
}
755-
756763
fn load(&mut self, pointee_ty: Type<'gcc>, ptr: RValue<'gcc>, align: Align) -> RValue<'gcc> {
757764
let block = self.llbb();
758765
let function = block.get_function();

‎compiler/rustc_codegen_gcc/src/intrinsic/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
490490
// We instead thus allocate some scratch space...
491491
let scratch_size = cast.size(bx);
492492
let scratch_align = cast.align(bx);
493-
let llscratch = bx.alloca(cast.gcc_type(bx), scratch_align);
493+
let llscratch = bx.alloca(scratch_size, scratch_align);
494494
bx.lifetime_start(llscratch, scratch_size);
495495

496496
// ... where we first store the value...

‎compiler/rustc_codegen_gcc/src/intrinsic/simd.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_middle::span_bug;
1616
use rustc_middle::ty::layout::HasTyCtxt;
1717
use rustc_middle::ty::{self, Ty};
1818
use rustc_span::{sym, Span, Symbol};
19-
use rustc_target::abi::Align;
19+
use rustc_target::abi::{Align, Size};
2020

2121
use crate::builder::Builder;
2222
#[cfg(feature = "master")]
@@ -363,7 +363,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
363363
let ze = bx.zext(result, bx.type_ix(expected_bytes * 8));
364364

365365
// Convert the integer to a byte array
366-
let ptr = bx.alloca(bx.type_ix(expected_bytes * 8), Align::ONE);
366+
let ptr = bx.alloca(Size::from_bytes(expected_bytes), Align::ONE);
367367
bx.store(ze, ptr, Align::ONE);
368368
let array_ty = bx.type_array(bx.type_i8(), expected_bytes);
369369
let ptr = bx.pointercast(ptr, bx.cx.type_ptr_to(array_ty));

‎compiler/rustc_codegen_llvm/src/abi.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
234234
// We instead thus allocate some scratch space...
235235
let scratch_size = cast.size(bx);
236236
let scratch_align = cast.align(bx);
237-
let llscratch = bx.alloca(cast.llvm_type(bx), scratch_align);
237+
let llscratch = bx.alloca(scratch_size, scratch_align);
238238
bx.lifetime_start(llscratch, scratch_size);
239239

240240
// ... where we first store the value...

‎compiler/rustc_codegen_llvm/src/builder.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -466,20 +466,31 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
466466
val
467467
}
468468

469-
fn alloca(&mut self, ty: &'ll Type, align: Align) -> &'ll Value {
469+
fn alloca(&mut self, size: Size, align: Align) -> &'ll Value {
470470
let mut bx = Builder::with_cx(self.cx);
471471
bx.position_at_start(unsafe { llvm::LLVMGetFirstBasicBlock(self.llfn()) });
472+
let ty = self.cx().type_array(self.cx().type_i8(), size.bytes());
472473
unsafe {
473474
let alloca = llvm::LLVMBuildAlloca(bx.llbuilder, ty, UNNAMED);
474475
llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint);
475476
alloca
476477
}
477478
}
478479

479-
fn byte_array_alloca(&mut self, len: &'ll Value, align: Align) -> &'ll Value {
480+
fn dynamic_alloca(&mut self, size: &'ll Value, align: Align) -> &'ll Value {
480481
unsafe {
481482
let alloca =
482-
llvm::LLVMBuildArrayAlloca(self.llbuilder, self.cx().type_i8(), len, UNNAMED);
483+
llvm::LLVMBuildArrayAlloca(self.llbuilder, self.cx().type_i8(), size, UNNAMED);
484+
llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint);
485+
alloca
486+
}
487+
}
488+
489+
fn typed_alloca(&mut self, ty: &'ll Type, align: Align) -> &'ll Value {
490+
let mut bx = Builder::with_cx(self.cx);
491+
bx.position_at_start(unsafe { llvm::LLVMGetFirstBasicBlock(self.llfn()) });
492+
unsafe {
493+
let alloca = llvm::LLVMBuildAlloca(bx.llbuilder, ty, UNNAMED);
483494
llvm::LLVMSetAlignment(alloca, align.bytes() as c_uint);
484495
alloca
485496
}

‎compiler/rustc_codegen_llvm/src/intrinsic.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf};
1818
use rustc_middle::ty::{self, GenericArgsRef, Ty};
1919
use rustc_middle::{bug, span_bug};
2020
use rustc_span::{sym, Span, Symbol};
21-
use rustc_target::abi::{self, Align, HasDataLayout, Primitive};
21+
use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size};
2222
use rustc_target::spec::{HasTargetSpec, PanicStrategy};
2323

2424
use std::cmp::Ordering;
@@ -635,8 +635,9 @@ fn codegen_msvc_try<'ll>(
635635
// }
636636
//
637637
// More information can be found in libstd's seh.rs implementation.
638+
let ptr_size = bx.tcx().data_layout.pointer_size;
638639
let ptr_align = bx.tcx().data_layout.pointer_align.abi;
639-
let slot = bx.alloca(bx.type_ptr(), ptr_align);
640+
let slot = bx.alloca(ptr_size, ptr_align);
640641
let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void());
641642
bx.invoke(try_func_ty, None, None, try_func, &[data], normal, catchswitch, None);
642643

@@ -909,7 +910,7 @@ fn codegen_emcc_try<'ll>(
909910
let ptr_align = bx.tcx().data_layout.pointer_align.abi;
910911
let i8_align = bx.tcx().data_layout.i8_align.abi;
911912
let catch_data_type = bx.type_struct(&[bx.type_ptr(), bx.type_bool()], false);
912-
let catch_data = bx.alloca(catch_data_type, ptr_align);
913+
let catch_data = bx.typed_alloca(catch_data_type, ptr_align);
913914
let catch_data_0 =
914915
bx.inbounds_gep(catch_data_type, catch_data, &[bx.const_usize(0), bx.const_usize(0)]);
915916
bx.store(ptr, catch_data_0, ptr_align);
@@ -1360,7 +1361,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
13601361
let ze = bx.zext(i_, bx.type_ix(expected_bytes * 8));
13611362

13621363
// Convert the integer to a byte array
1363-
let ptr = bx.alloca(bx.type_ix(expected_bytes * 8), Align::ONE);
1364+
let ptr = bx.alloca(Size::from_bytes(expected_bytes), Align::ONE);
13641365
bx.store(ze, ptr, Align::ONE);
13651366
let array_ty = bx.type_array(bx.type_i8(), expected_bytes);
13661367
return Ok(bx.load(array_ty, ptr, Align::ONE));

‎compiler/rustc_codegen_ssa/src/base.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
511511
let param_handle = bx.get_param(0);
512512
let param_system_table = bx.get_param(1);
513513
let arg_argc = bx.const_int(cx.type_isize(), 2);
514-
let arg_argv = bx.alloca(cx.type_array(cx.type_ptr(), 2), Align::ONE);
514+
let arg_argv = bx.typed_alloca(cx.type_array(cx.type_ptr(), 2), Align::ONE);
515515
bx.store(param_handle, arg_argv, Align::ONE);
516516
let arg_argv_el1 = bx.gep(cx.type_ptr(), arg_argv, &[bx.const_int(cx.type_int(), 1)]);
517517
bx.store(param_system_table, arg_argv_el1, Align::ONE);

‎compiler/rustc_codegen_ssa/src/mir/operand.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
324324
let llfield_ty = bx.cx().backend_type(field);
325325

326326
// Can't bitcast an aggregate, so round trip through memory.
327-
let llptr = bx.alloca(llfield_ty, field.align.abi);
327+
let llptr = bx.alloca(field.size, field.align.abi);
328328
bx.store(*llval, llptr, field.align.abi);
329329
*llval = bx.load(llfield_ty, llptr, field.align.abi);
330330
}
@@ -472,7 +472,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
472472
let align_minus_1 = bx.sub(align, one);
473473
let size_extra = bx.add(size, align_minus_1);
474474
let min_align = Align::ONE;
475-
let alloca = bx.byte_array_alloca(size_extra, min_align);
475+
let alloca = bx.dynamic_alloca(size_extra, min_align);
476476
let address = bx.ptrtoint(alloca, bx.type_isize());
477477
let neg_address = bx.neg(address);
478478
let offset = bx.and(neg_address, align_minus_1);

‎compiler/rustc_codegen_ssa/src/mir/place.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
5757
align: Align,
5858
) -> Self {
5959
assert!(layout.is_sized(), "tried to statically allocate unsized place");
60-
let tmp = bx.alloca(bx.cx().backend_type(layout), align);
60+
let tmp = bx.alloca(layout.size, align);
6161
Self::new_sized_aligned(tmp, layout, align)
6262
}
6363

‎compiler/rustc_codegen_ssa/src/traits/builder.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,12 @@ pub trait BuilderMethods<'a, 'tcx>:
141141
}
142142
fn to_immediate_scalar(&mut self, val: Self::Value, scalar: Scalar) -> Self::Value;
143143

144-
fn alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value;
145-
fn byte_array_alloca(&mut self, len: Self::Value, align: Align) -> Self::Value;
144+
/// Used for all fixed-size Rust types.
145+
fn alloca(&mut self, size: Size, align: Align) -> Self::Value;
146+
/// Used for DSTs and unsized locals.
147+
fn dynamic_alloca(&mut self, size: Self::Value, align: Align) -> Self::Value;
148+
/// Should only be used for types without a Rust layout, e.g. C++ EH catch data.
149+
fn typed_alloca(&mut self, ty: Self::Type, align: Align) -> Self::Value;
146150

147151
fn load(&mut self, ty: Self::Type, ptr: Self::Value, align: Align) -> Self::Value;
148152
fn volatile_load(&mut self, ty: Self::Type, ptr: Self::Value) -> Self::Value;

‎tests/assembly/stack-protector/stack-protector-heuristics-effect.rs

+15-40
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
//@ compile-flags: -C opt-level=2 -Z merge-functions=disabled
1212
//@ min-llvm-version: 17.0.2
1313

14+
// NOTE: the heuristics for stack smash protection inappropriately rely on types in LLVM IR,
15+
// despite those types having no semantic meaning. This means that the `basic` and `strong`
16+
// settings do not behave in a coherent way. This is a known issue in LLVM.
17+
// See comments on https://github.com/rust-lang/rust/issues/114903.
18+
1419
#![crate_type = "lib"]
1520

1621
#![allow(incomplete_features)]
@@ -39,23 +44,9 @@ pub fn array_char(f: fn(*const char)) {
3944
f(&b as *const _);
4045
f(&c as *const _);
4146

42-
// Any type of local array variable leads to stack protection with the
43-
// "strong" heuristic. The 'basic' heuristic only adds stack protection to
44-
// functions with local array variables of a byte-sized type, however. Since
45-
// 'char' is 4 bytes in Rust, this function is not protected by the 'basic'
46-
// heuristic
47-
//
48-
// (This test *also* takes the address of the local stack variables. We
49-
// cannot know that this isn't what triggers the `strong` heuristic.
50-
// However, the test strategy of passing the address of a stack array to an
51-
// external function is sufficient to trigger the `basic` heuristic (see
52-
// test `array_u8_large()`). Since the `basic` heuristic only checks for the
53-
// presence of stack-local array variables, we can be confident that this
54-
// test also captures this part of the `strong` heuristic specification.)
55-
5647
// all: __stack_chk_fail
5748
// strong: __stack_chk_fail
58-
// basic-NOT: __stack_chk_fail
49+
// basic: __stack_chk_fail
5950
// none-NOT: __stack_chk_fail
6051
// missing-NOT: __stack_chk_fail
6152
}
@@ -163,26 +154,11 @@ pub fn local_string_addr_taken(f: fn(&String)) {
163154
f(&x);
164155

165156
// Taking the address of the local variable `x` leads to stack smash
166-
// protection with the `strong` heuristic, but not with the `basic`
167-
// heuristic. It does not matter that the reference is not mut.
168-
//
169-
// An interesting note is that a similar function in C++ *would* be
170-
// protected by the `basic` heuristic, because `std::string` has a char
171-
// array internally as a small object optimization:
172-
// ```
173-
// cat <<EOF | clang++ -O2 -fstack-protector -S -x c++ - -o - | grep stack_chk
174-
// #include <string>
175-
// void f(void (*g)(const std::string&)) {
176-
// std::string x;
177-
// g(x);
178-
// }
179-
// EOF
180-
// ```
181-
//
157+
// protection. It does not matter that the reference is not mut.
182158

183159
// all: __stack_chk_fail
184160
// strong: __stack_chk_fail
185-
// basic-NOT: __stack_chk_fail
161+
// basic: __stack_chk_fail
186162
// none-NOT: __stack_chk_fail
187163
// missing-NOT: __stack_chk_fail
188164
}
@@ -233,8 +209,8 @@ pub fn local_large_var_moved(f: fn(Gigastruct)) {
233209
// Even though the local variable conceptually doesn't have its address
234210
// taken, it's so large that the "move" is implemented with a reference to a
235211
// stack-local variable in the ABI. Consequently, this function *is*
236-
// protected by the `strong` heuristic. This is also the case for
237-
// rvalue-references in C++, regardless of struct size:
212+
// protected. This is also the case for rvalue-references in C++,
213+
// regardless of struct size:
238214
// ```
239215
// cat <<EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk
240216
// #include <cstdint>
@@ -248,7 +224,7 @@ pub fn local_large_var_moved(f: fn(Gigastruct)) {
248224

249225
// all: __stack_chk_fail
250226
// strong: __stack_chk_fail
251-
// basic-NOT: __stack_chk_fail
227+
// basic: __stack_chk_fail
252228
// none-NOT: __stack_chk_fail
253229
// missing-NOT: __stack_chk_fail
254230
}
@@ -261,9 +237,9 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) {
261237
// A new instance of `Gigastruct` is passed to `f()`, without any apparent
262238
// connection to this stack frame. Still, since instances of `Gigastruct`
263239
// are sufficiently large, it is allocated in the caller stack frame and
264-
// passed as a pointer. As such, this function is *also* protected by the
265-
// `strong` heuristic, just like `local_large_var_moved`. This is also the
266-
// case for pass-by-value of sufficiently large structs in C++:
240+
// passed as a pointer. As such, this function is *also* protected, just
241+
// like `local_large_var_moved`. This is also the case for pass-by-value
242+
// of sufficiently large structs in C++:
267243
// ```
268244
// cat <<EOF | clang++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk
269245
// #include <cstdint>
@@ -275,10 +251,9 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) {
275251
// EOF
276252
// ```
277253

278-
279254
// all: __stack_chk_fail
280255
// strong: __stack_chk_fail
281-
// basic-NOT: __stack_chk_fail
256+
// basic: __stack_chk_fail
282257
// none-NOT: __stack_chk_fail
283258
// missing-NOT: __stack_chk_fail
284259
}

‎tests/codegen/align-byval.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -106,20 +106,20 @@ pub struct ForceAlign16 {
106106
pub unsafe fn call_na1(x: NaturalAlign1) {
107107
// CHECK: start:
108108

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

112-
// wasm: [[ALLOCA:%[a-z0-9+]]] = alloca %NaturalAlign1, align 1
112+
// wasm: [[ALLOCA:%[a-z0-9+]]] = alloca [2 x i8], align 1
113113
// wasm: call void @natural_align_1({{.*}}byval(%NaturalAlign1) 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

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

122-
// i686-windows: [[ALLOCA:%[a-z0-9+]]] = alloca %NaturalAlign1, align 4
122+
// i686-windows: [[ALLOCA:%[a-z0-9+]]] = alloca [2 x i8], align 4
123123
// i686-windows: call void @natural_align_1({{.*}}byval(%NaturalAlign1) align 4{{.*}} [[ALLOCA]])
124124
natural_align_1(x);
125125
}
@@ -134,10 +134,10 @@ pub unsafe fn call_na2(x: NaturalAlign2) {
134134
// x86_64-linux-NEXT: call void @natural_align_2
135135
// x86_64-windows-NEXT: call void @natural_align_2
136136

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

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

‎tests/codegen/align-enum.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub struct Nested64 {
1919
// CHECK-LABEL: @align64
2020
#[no_mangle]
2121
pub fn align64(a: u32) -> Align64 {
22-
// CHECK: %a64 = alloca %Align64, align 64
22+
// CHECK: %a64 = alloca [64 x i8], align 64
2323
// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 64 %{{.*}}, ptr align 64 %{{.*}}, i{{[0-9]+}} 64, i1 false)
2424
let a64 = Align64::A(a);
2525
a64
@@ -28,7 +28,7 @@ pub fn align64(a: u32) -> Align64 {
2828
// CHECK-LABEL: @nested64
2929
#[no_mangle]
3030
pub fn nested64(a: u8, b: u32, c: u16) -> Nested64 {
31-
// CHECK: %n64 = alloca %Nested64, align 64
31+
// CHECK: %n64 = alloca [128 x i8], align 64
3232
let n64 = Nested64 { a, b: Align64::B(b), c };
3333
n64
3434
}

‎tests/codegen/align-struct.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub enum Enum64 {
3030
// CHECK-LABEL: @align64
3131
#[no_mangle]
3232
pub fn align64(i : i32) -> Align64 {
33-
// CHECK: %a64 = alloca %Align64, align 64
33+
// CHECK: %a64 = alloca [64 x i8], align 64
3434
// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 64 %{{.*}}, ptr align 64 %{{.*}}, i{{[0-9]+}} 64, i1 false)
3535
let a64 = Align64(i);
3636
a64
@@ -48,23 +48,23 @@ pub fn align64_load(a: Align64) -> i32 {
4848
// CHECK-LABEL: @nested64
4949
#[no_mangle]
5050
pub fn nested64(a: Align64, b: i32, c: i32, d: i8) -> Nested64 {
51-
// CHECK: %n64 = alloca %Nested64, align 64
51+
// CHECK: %n64 = alloca [128 x i8], align 64
5252
let n64 = Nested64 { a, b, c, d };
5353
n64
5454
}
5555

5656
// CHECK-LABEL: @enum4
5757
#[no_mangle]
5858
pub fn enum4(a: i32) -> Enum4 {
59-
// CHECK: %e4 = alloca %Enum4, align 4
59+
// CHECK: %e4 = alloca [8 x i8], align 4
6060
let e4 = Enum4::A(a);
6161
e4
6262
}
6363

6464
// CHECK-LABEL: @enum64
6565
#[no_mangle]
6666
pub fn enum64(a: Align64) -> Enum64 {
67-
// CHECK: %e64 = alloca %Enum64, align 64
67+
// CHECK: %e64 = alloca [128 x i8], align 64
6868
let e64 = Enum64::A(a);
6969
e64
7070
}

0 commit comments

Comments
 (0)
Please sign in to comment.