-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Emit noundef LLVM attribute #74378
Comments
The bits you quote explicitly say
So it seems to me types with padding are fine? We should definitely be able to already add this for types like Cc @rust-lang/wg-unsafe-code-guidelines
To be clear, adding |
This attribute only refers to values, not memory pointed to by pointer arguments, right? I don't think there are many cases where we pass any aggregates by value in LLVM IR, except:
|
Sorry for being unclear on this point. Whether padding is fine depends on how the value is passed. E.g. if we have a boolean and pass it as
That's correct. On a pointer type noundef determines whether the pointer itself may be undef/poison, not the pointed-to memory. |
Booleans are always passed as i8 with zero extension rather than bit casting, so all bits are specified. This applies both for arguments and memory accesses. Only local variables can be i1. |
Apply noundef attribute to &T, &mut T, Box<T>, bool This doesn't handle `char` because it's a bit awkward to distinguish it from `u32` at this point in codegen. Note that this _does not_ change whether or not it is UB for `&`, `&mut`, or `Box` to point to undef. It only applies to the pointer itself, not the pointed-to memory. Fixes (partially) rust-lang#74378. r? `@nikic` cc `@RalfJung`
When generating LLVM types from Rust types, do we ever emit padding explicitly or something like that? I could imagine us "taking charge" of some aspects of enum lowering in this way. |
Yes. https://rust.godbolt.org/z/xd4er1hTY #[repr(C)]
pub struct Foo {
a: u8,
// 1 byte padding
b: u16,
// 4 bytes padding
c: u64,
}
pub fn foo(_: Foo) {} %Foo = type { i8, [1 x i8], i16, [2 x i16], i64 }
[...] |
Apply noundef attribute to all scalar types which do not permit raw init Beyond `&`/`&mut`/`Box`, this covers `char`, enum discriminants, `NonZero*`, etc. All such types currently cause a Miri error if left uninitialized, and an `invalid_value` lint in cases like `mem::uninitialized::<char>()`. Note that this _does not_ change whether or not it is UB for `u64` (or other integer types with no invalid values) to be undef. Fixes (partially) rust-lang#74378. r? `@ghost` (blocked on rust-lang#94127) `@rustbot` label S-blocked
…ikic Apply noundef metadata to loads of types that do not permit raw init This matches the noundef attributes we apply on arguments/return types. Fixes (partially) rust-lang#74378.
LLVM 11 introduces a new
noundef
attribute, with the following semantics:In LLVM 11 itself it doesn't do anything yet, but this will become important in the future to reduce the impact of
freeze
instructions.We need to figure out for which parameters / return values we can emit this attribute. We generally can't do so if any bits are unspecified, e.g. due to padding. More problematic for Rust is rust-lang/unsafe-code-guidelines#71, i.e. the question of whether integers are allowed to contain uninitialized bits without going through something like MaybeUninit.
If we go with aggressive emission of noundef, we probably need to
punishsafe-guardmem::uninitialized()
users with liberal application offreeze
.cc @RalfJung
The text was updated successfully, but these errors were encountered: