Skip to content

Commit de728f7

Browse files
Fix ICE on offsetted ZST pointer
As far as I can tell, this was buggy between 1.39 (RUST-63635) and 1.42 (RUST-67000), and I probably copied the earlier code when performing this optimization again in RUST-123936. A grep for `const_usize.*align` found the same code copied to rustc_codegen_gcc but I don't see other cases where we get this wrong.
1 parent 9725c4b commit de728f7

File tree

4 files changed

+16
-6
lines changed

4 files changed

+16
-6
lines changed

compiler/rustc_codegen_cranelift/src/constant.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,7 @@ pub(crate) fn codegen_const_value<'tcx>(
138138
let base_addr = match fx.tcx.global_alloc(alloc_id) {
139139
GlobalAlloc::Memory(alloc) => {
140140
if alloc.inner().len() == 0 {
141-
assert_eq!(offset, Size::ZERO);
142-
fx.bcx.ins().iconst(fx.pointer_type, alloc.inner().align.bytes() as i64)
141+
fx.bcx.ins().iconst(fx.pointer_type, alloc.inner().align.bytes().wrapping_add(offset.bytes()) as i64)
143142
} else {
144143
let data_id = data_id_for_alloc_id(
145144
&mut fx.constants_cx,

compiler/rustc_codegen_gcc/src/common.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,8 +247,9 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
247247
// This avoids generating a zero-sized constant value and actually needing a
248248
// real address at runtime.
249249
if alloc.inner().len() == 0 {
250-
assert_eq!(offset.bytes(), 0);
251-
let val = self.const_usize(alloc.inner().align.bytes());
250+
let val = self.const_usize(
251+
alloc.inner().align.bytes().wrapping_add(offset.bytes()),
252+
);
252253
return if matches!(layout.primitive(), Pointer(_)) {
253254
self.context.new_cast(None, val, ty)
254255
} else {

compiler/rustc_codegen_llvm/src/common.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,9 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
281281
// This avoids generating a zero-sized constant value and actually needing a
282282
// real address at runtime.
283283
if alloc.inner().len() == 0 {
284-
assert_eq!(offset.bytes(), 0);
285-
let llval = self.const_usize(alloc.inner().align.bytes());
284+
let llval = self.const_usize(
285+
alloc.inner().align.bytes().wrapping_add(offset.bytes()),
286+
);
286287
return if matches!(layout.primitive(), Pointer(_)) {
287288
unsafe { llvm::LLVMConstIntToPtr(llval, llty) }
288289
} else {

tests/ui/consts/zst_no_llvm_alloc.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ struct Foo;
55

66
static FOO: Foo = Foo;
77

8+
// This tests for regression of https://github.com/rust-lang/rust/issues/147516
9+
const A: *const () = (&() as *const ()).wrapping_byte_add(2);
10+
const B: *const () = (&Foo as *const _ as *const ()).wrapping_byte_add(2);
11+
const C: *const () = (&Foo as *const _ as *const ()).wrapping_byte_add(usize::MAX);
12+
813
fn main() {
914
// There's no stable guarantee that these are true.
1015
// However, we want them to be true so that our LLVM IR and runtime are a bit faster:
@@ -15,6 +20,10 @@ fn main() {
1520
let x: &'static Foo = &Foo;
1621
assert_eq!(x as *const Foo as usize, 4);
1722

23+
assert_eq!(A.addr(), 3);
24+
assert_eq!(B.addr(), 6);
25+
assert_eq!(C.addr(), 3);
26+
1827
// The exact addresses returned by these library functions are not necessarily stable guarantees
1928
// but for now we assert that we're still matching.
2029
#[allow(dangling_pointers_from_temporaries)]

0 commit comments

Comments
 (0)