about summary refs log tree commit diff
path: root/compiler/rustc_codegen_llvm/src/common.rs
AgeCommit message (Collapse)AuthorLines
2025-02-16Move hashes from rustc_data_structure to rustc_hashes so they can be shared ↵Ben Kimock-1/+2
with rust-analyzer
2025-02-11Document some safety constraints and use more safe wrappersOli Scherer-1/+1
2025-01-31Auto merge of #135318 - compiler-errors:vtable-fixes, r=lcnrbors-1/+6
Fix deduplication mismatches in vtables leading to upcasting unsoundness We currently have two cases where subtleties in supertraits can trigger disagreements in the vtable layout, e.g. leading to a different vtable layout being accessed at a callsite compared to what was prepared during unsizing. Namely: ### #135315 In this example, we were not normalizing supertraits when preparing vtables. In the example, ``` trait Supertrait<T> { fn _print_numbers(&self, mem: &[usize; 100]) { println!("{mem:?}"); } } impl<T> Supertrait<T> for () {} trait Identity { type Selff; } impl<Selff> Identity for Selff { type Selff = Selff; } trait Middle<T>: Supertrait<()> + Supertrait<T> { fn say_hello(&self, _: &usize) { println!("Hello!"); } } impl<T> Middle<T> for () {} trait Trait: Middle<<() as Identity>::Selff> {} impl Trait for () {} fn main() { (&() as &dyn Trait as &dyn Middle<()>).say_hello(&0); } ``` When we prepare `dyn Trait`, we see a supertrait of `Middle<<() as Identity>::Selff>`, which itself has two supertraits `Supertrait<()>` and `Supertrait<<() as Identity>::Selff>`. These two supertraits are identical, but they are not duplicated because we were using structural equality and *not* considering normalization. This leads to a vtable layout with two trait pointers. When we upcast to `dyn Middle<()>`, those two supertraits are now the same, leading to a vtable layout with only one trait pointer. This leads to an offset error, and we call the wrong method. ### #135316 This one is a bit more interesting, and is the bulk of the changes in this PR. It's a bit similar, except it uses binder equality instead of normalization to make the compiler get confused about two vtable layouts. In the example, ``` trait Supertrait<T> { fn _print_numbers(&self, mem: &[usize; 100]) { println!("{mem:?}"); } } impl<T> Supertrait<T> for () {} trait Trait<T, U>: Supertrait<T> + Supertrait<U> { fn say_hello(&self, _: &usize) { println!("Hello!"); } } impl<T, U> Trait<T, U> for () {} fn main() { (&() as &'static dyn for<'a> Trait<&'static (), &'a ()> as &'static dyn Trait<&'static (), &'static ()>) .say_hello(&0); } ``` When we prepare the vtable for `dyn for<'a> Trait<&'static (), &'a ()>`, we currently consider the PolyTraitRef of the vtable as the key for a supertrait. This leads two two supertraits -- `Supertrait<&'static ()>` and `for<'a> Supertrait<&'a ()>`. However, we can upcast[^up] without offsetting the vtable from `dyn for<'a> Trait<&'static (), &'a ()>` to `dyn Trait<&'static (), &'static ()>`. This is just instantiating the principal trait ref for a specific `'a = 'static`. However, when considering those supertraits, we now have only one distinct supertrait -- `Supertrait<&'static ()>` (which is deduplicated since there are two supertraits with the same substitutions). This leads to similar offsetting issues, leading to the wrong method being called. [^up]: I say upcast but this is a cast that is allowed on stable, since it's not changing the vtable at all, just instantiating the binder of the principal trait ref for some lifetime. The solution here is to recognize that a vtable isn't really meaningfully higher ranked, and to just treat a vtable as corresponding to a `TraitRef` so we can do this deduplication more faithfully. That is to say, the vtable for `dyn for<'a> Tr<'a>` and `dyn Tr<'x>` are always identical, since they both would correspond to a set of free regions on an impl... Do note that `Tr<for<'a> fn(&'a ())>` and `Tr<fn(&'static ())>` are still distinct. ---- There's a bit more that can be cleaned up. In codegen, we can stop using `PolyExistentialTraitRef` basically everywhere. We can also fix SMIR to stop storing `PolyExistentialTraitRef` in its vtable allocations. As for testing, it's difficult to actually turn this into something that can be tested with `rustc_dump_vtable`, since having multiple supertraits that are identical is a recipe for ambiguity errors. Maybe someone else is more creative with getting that attr to work, since the tests I added being run-pass tests is a bit unsatisfying. Miri also doesn't help here, since it doesn't really generate vtables that are offset by an index in the same way as codegen. r? `@lcnr` for the vibe check? Or reassign, idk. Maybe let's talk about whether this makes sense. <sup>(I guess an alternative would also be to not do any deduplication of vtable supertraits (or only a really conservative subset) rather than trying to normalize and deduplicate more faithfully here. Not sure if that works and is sufficient tho.)</sup> cc `@steffahn` -- ty for the minimizations cc `@WaffleLapkin` -- since you're overseeing the feature stabilization :3 Fixes #135315 Fixes #135316
2025-01-30Rollup merge of #135026 - Flakebi:global-addrspace, r=saethlinMatthias Krüger-3/+6
Cast global variables to default address space Pointers for variables all need to be in the same address space for correct compilation. Therefore ensure that even if a global variable is created in a different address space, it is casted to the default address space before its value is used. This is necessary for the amdgpu target and others where the default address space for global variables is not 0. For example `core` does not compile in debug mode when not casting the address space to the default one because it tries to emit the following (simplified) LLVM IR, containing a type mismatch: ```llvm `@alloc_0` = addrspace(1) constant <{ [6 x i8] }> <{ [6 x i8] c"bit.rs" }>, align 1 `@alloc_1` = addrspace(1) constant <{ ptr }> <{ ptr addrspace(1) `@alloc_0` }>, align 8 ; ^ here a struct containing a `ptr` is needed, but it is created using a `ptr addrspace(1)` ``` For this to compile, we need to insert a constant `addrspacecast` before we use a global variable: ```llvm `@alloc_0` = addrspace(1) constant <{ [6 x i8] }> <{ [6 x i8] c"bit.rs" }>, align 1 `@alloc_1` = addrspace(1) constant <{ ptr }> <{ ptr addrspacecast (ptr addrspace(1) `@alloc_0` to ptr) }>, align 8 ``` As vtables are global variables as well, they are also created with an `addrspacecast`. In the SSA backend, after a vtable global is created, metadata is added to it. To add metadata, we need the non-casted global variable. Therefore we strip away an addrspacecast if there is one, to get the underlying global. Tracking issue: #135024
2025-01-30Do not treat vtable supertraits as distinct when bound with different bound varsMichael Goulet-1/+6
2025-01-24Add comments about address spacesFlakebi-0/+2
2025-01-21Treat undef bytes as equal to any other byteOli Scherer-0/+4
2025-01-02Cast global variables to default address spaceFlakebi-3/+4
Pointers for variables all need to be in the same address space for correct compilation. Therefore ensure that even if a global variable is created in a different address space, it is casted to the default address space before its value is used. This is necessary for the amdgpu target and others where the default address space for global variables is not 0. For example `core` does not compile in debug mode when not casting the address space to the default one because it tries to emit the following (simplified) LLVM IR, containing a type mismatch: ```llvm @alloc_0 = addrspace(1) constant <{ [6 x i8] }> <{ [6 x i8] c"bit.rs" }>, align 1 @alloc_1 = addrspace(1) constant <{ ptr }> <{ ptr addrspace(1) @alloc_0 }>, align 8 ; ^ here a struct containing a `ptr` is needed, but it is created using a `ptr addrspace(1)` ``` For this to compile, we need to insert a constant `addrspacecast` before we use a global variable: ```llvm @alloc_0 = addrspace(1) constant <{ [6 x i8] }> <{ [6 x i8] c"bit.rs" }>, align 1 @alloc_1 = addrspace(1) constant <{ ptr }> <{ ptr addrspacecast (ptr addrspace(1) @alloc_0 to ptr) }>, align 8 ``` As vtables are global variables as well, they are also created with an `addrspacecast`. In the SSA backend, after a vtable global is created, metadata is added to it. To add metadata, we need the non-casted global variable. Therefore we strip away an addrspacecast if there is one, to get the underlying global.
2024-12-06Remove polymorphizationBen Kimock-4/+3
2024-10-30Clean up FFI calls for operand bundlesZalathar-4/+4
2024-10-28Use a type-safe helper to cast `&str` and `&[u8]` to `*const c_char`Zalathar-0/+18
2024-10-26Use safe wrappers `get_linkage` and `set_linkage`Zalathar-1/+1
2024-10-12`LLVMConstInt` only allows integer typesDianQK-0/+13
2024-10-08compiler: Factor rustc_target::abi out of cg_llvmJubilee Young-1/+3
2024-09-24Auto merge of #130389 - Luv-Ray:LLVMMDNodeInContext2, r=nikicbors-1/+2
llvm: replace some deprecated functions `LLVMMDStringInContext` and `LLVMMDNodeInContext` are deprecated, replace them with `LLVMMDStringInContext2` and `LLVMMDNodeInContext2`. Also replace `Value` with `Metadata` in some function signatures for better consistency.
2024-09-23Check vtable projections for validity in miriMichael Goulet-2/+2
2024-09-19Reorder `ConstMethods`.Nicholas Nethercote-19/+19
It's crazy to have the integer methods in something close to random order. The reordering makes the gaps clear: `const_i64`, `const_i128`, `const_isize`, and `const_u16`. I guess they just aren't needed.
2024-09-19replace some deprecated functionsLuv-Ray-1/+2
2024-09-17Rename supertraits of `CodegenMethods`.Nicholas Nethercote-1/+1
Supertraits of `BuilderMethods` are all called `XyzBuilderMethods`. Supertraits of `CodegenMethods` are all called `XyzMethods`. This commit changes the latter to `XyzCodegenMethods`, for consistency.
2024-08-16Add `warn(unreachable_pub)` to `rustc_codegen_llvm`.Nicholas Nethercote-11/+11
2024-08-12Rollup merge of #128537 - Jamesbarford:118980-const-vector, r=RalfJung,nikicGuillaume Gomez-5/+5
const vector passed through to codegen This allows constant vectors using a repr(simd) type to be propagated through to the backend by reusing the functionality used to do a similar thing for the simd_shuffle intrinsic #118209 r​? RalfJung
2024-08-08const vector passed to codegenJames Barford-Evans-5/+5
2024-07-30Move is_mingw_gnu_toolchain and i686_decorated_name to cg_ssabjorn3-65/+1
2024-07-29Reformat `use` declarations.Nicholas Nethercote-8/+8
The previous commit updated `rustfmt.toml` appropriately. This commit is the outcome of running `x fmt --all` with the new formatting options.
2024-07-02Miri function identity hack: account for possible inliningRalf Jung-2/+2
2024-06-21Remove const_bitcast from ConstMethodsbjorn3-4/+0
2024-06-10ScalarInt: size mismatches are a bug, do not delay the panicRalf Jung-1/+1
2024-05-23Remove `#[macro_use] extern crate tracing` from `rustc_codegen_llvm`.Nicholas Nethercote-0/+1
2024-04-16Codegen ZSTs without an allocationMark Rousskov-16/+33
This makes sure that &[] is just as efficient as indirecting through unsafe code (from_raw_parts). No new stable guarantee is intended about whether or not we do this, this is just an optimization. Co-authored-by: Ralf Jung <post@ralfj.de>
2024-03-23Add+Use `mir::BinOp::Cmp`Scott McMurray-0/+4
2024-03-10Fix 32-bit overflows in LLVM composite constantserer1243-8/+9
2023-12-07ctfe interpreter: extend provenance so that it can track whether a pointer ↵Ralf Jung-2/+2
is immutable
2023-11-15Ensure strings created with `const_str` get the `unnamed_addr` attributeThom Chiovoloni-0/+1
2023-08-01Auto merge of #105545 - erikdesjardins:ptrclean, r=bjorn3bors-14/+4
cleanup: remove pointee types This can't be merged until the oldest LLVM version we support uses opaque pointers, which will be the case after #114148. (Also note `-Cllvm-args="-opaque-pointers=0"` can technically be used in LLVM 15, though I don't think we should support that configuration.) I initially hoped this would provide some minor perf win, but in https://github.com/rust-lang/rust/pull/105412#issuecomment-1341224450 it had very little impact, so this is only valuable as a cleanup. As a followup, this will enable #96242 to be resolved. r? `@ghost` `@rustbot` label S-blocked
2023-07-30inline format!() args up to and including rustc_codegen_llvmMatthias Krüger-2/+2
2023-07-29cg_ssa: remove pointee types and pointercast/bitcast-of-ptrErik Desjardins-5/+1
2023-07-29cg_llvm: remove pointee types and pointercast/bitcast-of-ptrErik Desjardins-9/+3
2023-07-10Reuse LLVMConstInBoundsGEP2Jubilee Young-2/+2
We have had LLVM 14 as our minimum for a bit now.
2023-06-10Support 128-bit enum variant in debuginfo codegenDonoughLiu-0/+4
2023-05-26Stop creating intermediate places just to immediate convert them to operandsOli Scherer-32/+17
2023-04-18Store hashes in special types so they aren't accidentally encoded as numbersBen Kimock-2/+2
2023-04-01use and_then/flat_map for map().flatten()Matthias Krüger-2/+1
2023-03-16Use poison instead of undefNikita Popov-0/+4
In cases where it is legal, we should prefer poison values over undef values. This replaces undef with poison for aggregate construction and for uninhabited types. There are more places where we can likely use poison, but I wanted to stay conservative to start with. In particular the aggregate case is important for newer LLVM versions, which are not able to handle an undef base value during early optimization due to poison-propagation concerns.
2023-02-25Name LLVM anonymous constants by a hash of their contentsJohn Kåre Alsaker-2/+8
2023-01-22abi: add `AddressSpace` field to `Primitive::Pointer`Erik Desjardins-2/+2
...and remove it from `PointeeInfo`, which isn't meant for this. There are still various places (marked with FIXMEs) that assume all pointers have the same size and alignment. Fixing this requires parsing non-default address spaces in the data layout string, which will be done in a followup.
2022-09-09Introduce a fallible variant of LLVMConstIntGetZExtValueTomasz Miąsko-1/+5
which verifies that a constant bit width is within 64 bits or fails.
2022-09-06Remove dead broken code from const zst handling in backendsOli Scherer-4/+0
2022-09-01Always import all tracing macros for the entire crate instead of piecemeal ↵Oli Scherer-1/+0
by module
2022-08-26Implementation of import_name_typeDaniel Paoliello-0/+76
2022-07-20slightly cleaner, if more verbose, vtable handling in codegen backendsRalf Jung-8/+9