Skip to content

Commit

Permalink
Auto merge of rust-lang#123936 - Mark-Simulacrum:zst-no-alloc, r=<try>
Browse files Browse the repository at this point in the history
Codegen ZSTs without an allocation

This makes sure that &[] is equivalent to unsafe code (from_raw_parts(dangling, 0)). No new stable guarantee is intended about whether or not we do this, this is just an optimization.

This regressed in rust-lang#67000 (no comments I can see about that regression in the PR, though it did change the test modified here). We had previously performed this optimization since rust-lang#63635.
  • Loading branch information
bors committed Apr 14, 2024
2 parents a8a88fe + 1266e22 commit f266dba
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 22 deletions.
41 changes: 27 additions & 14 deletions compiler/rustc_codegen_llvm/src/common.rs
Expand Up @@ -255,21 +255,34 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
let (prov, offset) = ptr.into_parts();
let (base_addr, base_addr_space) = match self.tcx.global_alloc(prov.alloc_id()) {
GlobalAlloc::Memory(alloc) => {
let init = const_alloc_to_llvm(self, alloc);
let alloc = alloc.inner();
let value = match alloc.mutability {
Mutability::Mut => self.static_addr_of_mut(init, alloc.align, None),
_ => self.static_addr_of(init, alloc.align, None),
};
if !self.sess().fewer_names() && llvm::get_value_name(value).is_empty() {
let hash = self.tcx.with_stable_hashing_context(|mut hcx| {
let mut hasher = StableHasher::new();
alloc.hash_stable(&mut hcx, &mut hasher);
hasher.finish::<Hash128>()
});
llvm::set_value_name(value, format!("alloc_{hash:032x}").as_bytes());
// For ZSTs directly codegen an aligned pointer.
// This avoids generating a zero-sized constant value and actually needing a
// real address at runtime.
if alloc.inner().len() == 0 {
let llval = self.const_usize(alloc.inner().align.bytes());
let llval = unsafe { llvm::LLVMConstIntToPtr(llval, llty) };
(llval, AddressSpace::DATA)
} else {
let init = const_alloc_to_llvm(self, alloc);
let alloc = alloc.inner();
let value = match alloc.mutability {
Mutability::Mut => self.static_addr_of_mut(init, alloc.align, None),
_ => self.static_addr_of(init, alloc.align, None),
};
if !self.sess().fewer_names() && llvm::get_value_name(value).is_empty()
{
let hash = self.tcx.with_stable_hashing_context(|mut hcx| {
let mut hasher = StableHasher::new();
alloc.hash_stable(&mut hcx, &mut hasher);
hasher.finish::<Hash128>()
});
llvm::set_value_name(
value,
format!("alloc_{hash:032x}").as_bytes(),
);
}
(value, AddressSpace::DATA)
}
(value, AddressSpace::DATA)
}
GlobalAlloc::Function(fn_instance) => (
self.get_fn_addr(fn_instance.polymorphize(self.tcx)),
Expand Down
21 changes: 13 additions & 8 deletions tests/ui/consts/zst_no_llvm_alloc.rs
Expand Up @@ -6,16 +6,21 @@ struct Foo;
static FOO: Foo = Foo;

fn main() {
// There's no stable guarantee that these are true.
// However, we want them to be true so that our LLVM IR and runtime are a bit faster:
// a constant address is cheap and doesn't result in relocations in comparison to a "real"
// global somewhere in the data section.
let x: &'static () = &();
assert_ne!(x as *const () as usize, 1);
assert_eq!(x as *const () as usize, 1);
let x: &'static Foo = &Foo;
assert_ne!(x as *const Foo as usize, 4);
assert_eq!(x as *const Foo as usize, 4);

// statics must have a unique address
assert_ne!(&FOO as *const Foo as usize, 4);
// The exact addresses returned by these library functions are not necessarily stable guarantees
// but for now we assert that we're still matching.
assert_eq!(<Vec<i32>>::new().as_ptr(), <&[i32]>::default().as_ptr());
assert_eq!(<Box<[i32]>>::default().as_ptr(), (&[]).as_ptr());

// FIXME this two tests should be assert_eq!
// this stopped working since we are promoting to constants instead of statics
assert_ne!(<Vec<i32>>::new().as_ptr(), <&[i32]>::default().as_ptr());
assert_ne!(<Box<[i32]>>::default().as_ptr(), (&[]).as_ptr());
// statics must have a unique address (see https://github.com/rust-lang/rust/issues/18297, not
// clear whether this is a stable guarantee)
assert_ne!(&FOO as *const Foo as usize, 4);
}

0 comments on commit f266dba

Please sign in to comment.