diff options
| author | Erik Desjardins <erikdesjardins@users.noreply.github.com> | 2024-02-28 00:09:24 -0500 |
|---|---|---|
| committer | Erik Desjardins <erikdesjardins@users.noreply.github.com> | 2024-03-04 09:32:33 -0500 |
| commit | 8ebd307d2a95840e193ff03aff21c87b5c643ef4 (patch) | |
| tree | d0a733ea5935ef049ccf91dcb393aa5bb5839c57 /tests/codegen | |
| parent | 7606c13961ddc1174b70638e934df0439b7dc515 (diff) | |
| download | rust-8ebd307d2a95840e193ff03aff21c87b5c643ef4.tar.gz rust-8ebd307d2a95840e193ff03aff21c87b5c643ef4.zip | |
use GEP inbounds for ZST and DST field offsets
For the former, it's fine for `inbounds` offsets to be one-past-the-end, so it's okay even if the ZST is the last field in the layout: > The base pointer has an in bounds address of an allocated object, > which means that it points into an allocated object, or to its end. https://llvm.org/docs/LangRef.html#getelementptr-instruction For the latter, even DST fields must always be inside the layout (or to its end for ZSTs), so using inbounds is also fine there.
Diffstat (limited to 'tests/codegen')
| -rw-r--r-- | tests/codegen/dst-offset.rs | 69 | ||||
| -rw-r--r-- | tests/codegen/zst-offset.rs | 6 |
2 files changed, 72 insertions, 3 deletions
diff --git a/tests/codegen/dst-offset.rs b/tests/codegen/dst-offset.rs new file mode 100644 index 00000000000..55212112b3d --- /dev/null +++ b/tests/codegen/dst-offset.rs @@ -0,0 +1,69 @@ +//! This file tests that we correctly generate GEP instructions for DST +//! field offsets. +//@ compile-flags: -C no-prepopulate-passes -Copt-level=0 + +#![crate_type = "lib"] + +use std::ptr::addr_of; + +// Hack to get the correct type for usize +// CHECK: @helper([[USIZE:i[0-9]+]] %_1) +#[no_mangle] +pub fn helper(_: usize) { +} + +struct Dst<T: ?Sized> { + x: u32, + y: u8, + z: T, +} + +// CHECK: @dst_dyn_trait_offset(ptr align {{[0-9]+}} [[DATA_PTR:%.+]], ptr align {{[0-9]+}} [[VTABLE_PTR:%.+]]) +#[no_mangle] +pub fn dst_dyn_trait_offset(s: &Dst<dyn Drop>) -> &dyn Drop { +// The alignment of dyn trait is unknown, so we compute the offset based on align from the vtable. + +// CHECK: [[SIZE_PTR:%[0-9]+]] = getelementptr inbounds {{.+}} [[VTABLE_PTR]] +// CHECK: load [[USIZE]], ptr [[SIZE_PTR]] +// CHECK: [[ALIGN_PTR:%[0-9]+]] = getelementptr inbounds {{.+}} [[VTABLE_PTR]] +// CHECK: load [[USIZE]], ptr [[ALIGN_PTR]] + +// CHECK: getelementptr inbounds i8, ptr [[DATA_PTR]] +// CHECK-NEXT: insertvalue +// CHECK-NEXT: insertvalue +// CHECK-NEXT: ret + &s.z +} + +// CHECK-LABEL: @dst_slice_offset +#[no_mangle] +pub fn dst_slice_offset(s: &Dst<[u16]>) -> &[u16] { +// The alignment of [u16] is known, so we generate a GEP directly. + +// CHECK: start: +// CHECK-NEXT: getelementptr inbounds i8, {{.+}}, [[USIZE]] 6 +// CHECK-NEXT: insertvalue +// CHECK-NEXT: insertvalue +// CHECK-NEXT: ret + &s.z +} + +#[repr(packed)] +struct PackedDstSlice { + x: u32, + y: u8, + z: [u16], +} + +// CHECK-LABEL: @packed_dst_slice_offset +#[no_mangle] +pub fn packed_dst_slice_offset(s: &PackedDstSlice) -> *const [u16] { +// The alignment of [u16] is known, so we generate a GEP directly. + +// CHECK: start: +// CHECK-NEXT: getelementptr inbounds i8, {{.+}}, [[USIZE]] 5 +// CHECK-NEXT: insertvalue +// CHECK-NEXT: insertvalue +// CHECK-NEXT: ret + addr_of!(s.z) +} diff --git a/tests/codegen/zst-offset.rs b/tests/codegen/zst-offset.rs index 65d9cf39c4c..b623d492d9d 100644 --- a/tests/codegen/zst-offset.rs +++ b/tests/codegen/zst-offset.rs @@ -13,7 +13,7 @@ pub fn helper(_: usize) { // CHECK-LABEL: @scalar_layout #[no_mangle] pub fn scalar_layout(s: &(u64, ())) { -// CHECK: getelementptr i8, {{.+}}, [[USIZE]] 8 +// CHECK: getelementptr inbounds i8, {{.+}}, [[USIZE]] 8 let x = &s.1; witness(&x); // keep variable in an alloca } @@ -22,7 +22,7 @@ pub fn scalar_layout(s: &(u64, ())) { // CHECK-LABEL: @scalarpair_layout #[no_mangle] pub fn scalarpair_layout(s: &(u64, u32, ())) { -// CHECK: getelementptr i8, {{.+}}, [[USIZE]] 12 +// CHECK: getelementptr inbounds i8, {{.+}}, [[USIZE]] 12 let x = &s.2; witness(&x); // keep variable in an alloca } @@ -34,7 +34,7 @@ pub struct U64x4(u64, u64, u64, u64); // CHECK-LABEL: @vector_layout #[no_mangle] pub fn vector_layout(s: &(U64x4, ())) { -// CHECK: getelementptr i8, {{.+}}, [[USIZE]] 32 +// CHECK: getelementptr inbounds i8, {{.+}}, [[USIZE]] 32 let x = &s.1; witness(&x); // keep variable in an alloca } |
