Skip to content
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

Put noundef on all scalars that don't allow uninit #106294

Merged
merged 3 commits into from
Jan 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
layout: TyAndLayout<'tcx>,
offset: Size,
) {
if !scalar.is_always_valid(bx) {
if !scalar.is_uninit_valid() {
Noratrieb marked this conversation as resolved.
Show resolved Hide resolved
bx.noundef_metadata(load);
}

Expand Down
8 changes: 1 addition & 7 deletions compiler/rustc_ty_utils/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,7 @@ fn adjust_for_rust_scalar<'tcx>(
return;
}

// Scalars which have invalid values cannot be undef.
if !scalar.is_always_valid(&cx) {
if !scalar.is_uninit_valid() {
Noratrieb marked this conversation as resolved.
Show resolved Hide resolved
attrs.set(ArgAttribute::NoUndef);
}

Expand All @@ -246,11 +245,6 @@ fn adjust_for_rust_scalar<'tcx>(
PointerKind::SharedMutable | PointerKind::UniqueOwned => Size::ZERO,
};

// `Box`, `&T`, and `&mut T` cannot be undef.
// Note that this only applies to the value of the pointer itself;
// this attribute doesn't make it UB for the pointed-to data to be undef.
attrs.set(ArgAttribute::NoUndef);

// The aliasing rules for `Box<T>` are still not decided, but currently we emit
// `noalias` for it. This can be turned off using an unstable flag.
// See https://github.com/rust-lang/unsafe-code-guidelines/issues/326
Expand Down
2 changes: 1 addition & 1 deletion tests/codegen/abi-sysv64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// of the sysv64 abi.
//
// needs-llvm-components: x86
// compile-flags: -C no-prepopulate-passes --target=x86_64-unknown-linux-gnu
// compile-flags: -C no-prepopulate-passes --target=x86_64-unknown-linux-gnu -Copt-level=0

#![crate_type = "lib"]
#![no_core]
Expand Down
2 changes: 1 addition & 1 deletion tests/codegen/abi-x86-interrupt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// of the x86-interrupt abi.

// needs-llvm-components: x86
// compile-flags: -C no-prepopulate-passes --target=x86_64-unknown-linux-gnu
// compile-flags: -C no-prepopulate-passes --target=x86_64-unknown-linux-gnu -Copt-level=0

#![crate_type = "lib"]
#![no_core]
Expand Down
2 changes: 1 addition & 1 deletion tests/codegen/adjustments.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// compile-flags: -C no-prepopulate-passes
// compile-flags: -C no-prepopulate-passes -Copt-level=0

#![crate_type = "lib"]

Expand Down
2 changes: 1 addition & 1 deletion tests/codegen/box-maybe-uninit-llvm14.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ pub fn box_uninitialized2() -> Box<MaybeUninit<[usize; 1024 * 1024]>> {
// Hide the LLVM 15+ `allocalign` attribute in the declaration of __rust_alloc
// from the CHECK-NOT above. We don't check the attributes here because we can't rely
// on all of them being set until LLVM 15.
// CHECK: declare noalias{{.*}} @__rust_alloc(i{{[0-9]+}}, i{{[0-9]+.*}})
// CHECK: declare noalias{{.*}} @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+.*}} noundef)
2 changes: 1 addition & 1 deletion tests/codegen/box-maybe-uninit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ pub fn box_uninitialized2() -> Box<MaybeUninit<[usize; 1024 * 1024]>> {

// Hide the `allocalign` attribute in the declaration of __rust_alloc
// from the CHECK-NOT above, and also verify the attributes got set reasonably.
// CHECK: declare noalias ptr @__rust_alloc(i{{[0-9]+}}, i{{[0-9]+}} allocalign) unnamed_addr [[RUST_ALLOC_ATTRS:#[0-9]+]]
// CHECK: declare noalias noundef ptr @__rust_alloc(i{{[0-9]+}} noundef, i{{[0-9]+}} allocalign noundef) unnamed_addr [[RUST_ALLOC_ATTRS:#[0-9]+]]

// CHECK-DAG: attributes [[RUST_ALLOC_ATTRS]] = { {{.*}} allockind("alloc,uninitialized,aligned") allocsize(0) uwtable "alloc-family"="__rust_alloc" {{.*}} }
2 changes: 1 addition & 1 deletion tests/codegen/c-variadic.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// ignore-wasm32-bare compiled with panic=abort by default
// compile-flags: -C no-prepopulate-passes
// compile-flags: -C no-prepopulate-passes -Copt-level=0
//

#![crate_type = "lib"]
Expand Down
2 changes: 1 addition & 1 deletion tests/codegen/call-llvm-intrinsics.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// compile-flags: -C no-prepopulate-passes
// compile-flags: -C no-prepopulate-passes -Copt-level=0

// ignore-riscv64

Expand Down
8 changes: 4 additions & 4 deletions tests/codegen/comparison-operators-newtype.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use std::cmp::Ordering;
pub struct Foo(u16);

// CHECK-LABEL: @check_lt
// CHECK-SAME: (i16 %[[A:.+]], i16 %[[B:.+]])
// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
#[no_mangle]
pub fn check_lt(a: Foo, b: Foo) -> bool {
// CHECK: %[[R:.+]] = icmp ult i16 %[[A]], %[[B]]
Expand All @@ -22,7 +22,7 @@ pub fn check_lt(a: Foo, b: Foo) -> bool {
}

// CHECK-LABEL: @check_le
// CHECK-SAME: (i16 %[[A:.+]], i16 %[[B:.+]])
// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
#[no_mangle]
pub fn check_le(a: Foo, b: Foo) -> bool {
// CHECK: %[[R:.+]] = icmp ule i16 %[[A]], %[[B]]
Expand All @@ -31,7 +31,7 @@ pub fn check_le(a: Foo, b: Foo) -> bool {
}

// CHECK-LABEL: @check_gt
// CHECK-SAME: (i16 %[[A:.+]], i16 %[[B:.+]])
// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
#[no_mangle]
pub fn check_gt(a: Foo, b: Foo) -> bool {
// CHECK: %[[R:.+]] = icmp ugt i16 %[[A]], %[[B]]
Expand All @@ -40,7 +40,7 @@ pub fn check_gt(a: Foo, b: Foo) -> bool {
}

// CHECK-LABEL: @check_ge
// CHECK-SAME: (i16 %[[A:.+]], i16 %[[B:.+]])
// CHECK-SAME: (i16 noundef %[[A:.+]], i16 noundef %[[B:.+]])
#[no_mangle]
pub fn check_ge(a: Foo, b: Foo) -> bool {
// CHECK: %[[R:.+]] = icmp uge i16 %[[A]], %[[B]]
Expand Down
10 changes: 5 additions & 5 deletions tests/codegen/dllimports/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// This test is for *-windows-msvc only.
// This test is for *-windows-msvc only.
// only-windows
// ignore-gnu

Expand All @@ -15,10 +15,10 @@ extern crate wrapper;
// CHECK: @static_global1 = external local_unnamed_addr global i32
// CHECK: @static_global2 = external local_unnamed_addr global i32

// CHECK: declare dllimport i32 @dylib_func1(i32)
// CHECK: declare dllimport i32 @dylib_func2(i32)
// CHECK: declare i32 @static_func1(i32)
// CHECK: declare i32 @static_func2(i32)
// CHECK: declare dllimport noundef i32 @dylib_func1(i32 noundef)
// CHECK: declare dllimport noundef i32 @dylib_func2(i32 noundef)
// CHECK: declare noundef i32 @static_func1(i32 noundef)
// CHECK: declare noundef i32 @static_func2(i32 noundef)

#[link(name = "dummy", kind="dylib")]
extern "C" {
Expand Down
6 changes: 3 additions & 3 deletions tests/codegen/enum-match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub enum Enum0 {
B,
}

// CHECK: define i8 @match0{{.*}}
// CHECK: define noundef i8 @match0{{.*}}
// CHECK-NEXT: start:
// CHECK-NEXT: %1 = icmp eq i8 %0, 2
// CHECK-NEXT: %2 = and i8 %0, 1
Expand All @@ -32,7 +32,7 @@ pub enum Enum1 {
C,
}

// CHECK: define i8 @match1{{.*}}
// CHECK: define noundef i8 @match1{{.*}}
// CHECK-NEXT: start:
// CHECK-NEXT: [[DISCR:%.*]] = {{.*}}call i8 @llvm.usub.sat.i8(i8 %0, i8 1)
// CHECK-NEXT: switch i8 [[DISCR]], label {{.*}} [
Expand Down Expand Up @@ -88,7 +88,7 @@ pub enum Enum2 {
E,
}

// CHECK: define i8 @match2{{.*}}
// CHECK: define noundef i8 @match2{{.*}}
// CHECK-NEXT: start:
// CHECK-NEXT: %1 = add i8 %0, 2
// CHECK-NEXT: %2 = zext i8 %1 to i64
Expand Down
12 changes: 6 additions & 6 deletions tests/codegen/fastcall-inreg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,27 @@ trait Sized {}
trait Copy {}

pub mod tests {
// CHECK: @f1(i32 inreg %_1, i32 inreg %_2, i32 %_3)
// CHECK: @f1(i32 inreg noundef %_1, i32 inreg noundef %_2, i32 noundef %_3)
#[no_mangle]
pub extern "fastcall" fn f1(_: i32, _: i32, _: i32) {}

// CHECK: @f2({{i32\*|ptr}} inreg %_1, {{i32\*|ptr}} inreg %_2, {{i32\*|ptr}} %_3)
// CHECK: @f2({{i32\*|ptr}} inreg noundef %_1, {{i32\*|ptr}} inreg noundef %_2, {{i32\*|ptr}} noundef %_3)
#[no_mangle]
pub extern "fastcall" fn f2(_: *const i32, _: *const i32, _: *const i32) {}

// CHECK: @f3(float %_1, i32 inreg %_2, i32 inreg %_3, i32 %_4)
// CHECK: @f3(float noundef %_1, i32 inreg noundef %_2, i32 inreg noundef %_3, i32 noundef %_4)
#[no_mangle]
pub extern "fastcall" fn f3(_: f32, _: i32, _: i32, _: i32) {}

// CHECK: @f4(i32 inreg %_1, float %_2, i32 inreg %_3, i32 %_4)
// CHECK: @f4(i32 inreg noundef %_1, float noundef %_2, i32 inreg noundef %_3, i32 noundef %_4)
#[no_mangle]
pub extern "fastcall" fn f4(_: i32, _: f32, _: i32, _: i32) {}

// CHECK: @f5(i64 %_1, i32 %_2)
// CHECK: @f5(i64 noundef %_1, i32 noundef %_2)
#[no_mangle]
pub extern "fastcall" fn f5(_: i64, _: i32) {}

// CHECK: @f6(i1 inreg noundef zeroext %_1, i32 inreg %_2, i32 %_3)
// CHECK: @f6(i1 inreg noundef zeroext %_1, i32 inreg noundef %_2, i32 noundef %_3)
#[no_mangle]
pub extern "fastcall" fn f6(_: bool, _: i32, _: i32) {}
}
4 changes: 2 additions & 2 deletions tests/codegen/fewer-names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@

#[no_mangle]
pub fn sum(x: u32, y: u32) -> u32 {
// YES-LABEL: define{{.*}}i32 @sum(i32 %0, i32 %1)
// YES-LABEL: define{{.*}}i32 @sum(i32 noundef %0, i32 noundef %1)
// YES-NEXT: %3 = add i32 %1, %0
// YES-NEXT: ret i32 %3

// NO-LABEL: define{{.*}}i32 @sum(i32 %x, i32 %y)
// NO-LABEL: define{{.*}}i32 @sum(i32 noundef %x, i32 noundef %y)
// NO-NEXT: start:
// NO-NEXT: %z = add i32 %y, %x
// NO-NEXT: ret i32 %z
Expand Down
2 changes: 1 addition & 1 deletion tests/codegen/frame-pointer.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// compile-flags: --crate-type=rlib
// compile-flags: --crate-type=rlib -Copt-level=0
// revisions: aarch64-apple aarch64-linux force x64-apple x64-linux
// [aarch64-apple] needs-llvm-components: aarch64
// [aarch64-apple] compile-flags: --target=aarch64-apple-darwin
Expand Down
58 changes: 42 additions & 16 deletions tests/codegen/function-arguments.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// compile-flags: -O -C no-prepopulate-passes

#![crate_type = "lib"]
#![feature(rustc_attrs)]

use std::mem::MaybeUninit;
use std::num::NonZeroU64;
use std::marker::PhantomPinned;
use std::ptr::NonNull;

pub struct S {
_field: [i32; 8],
Expand Down Expand Up @@ -61,7 +61,7 @@ pub fn maybeuninit_char(x: MaybeUninit<char>) -> MaybeUninit<char> {
x
}

// CHECK: i64 @int(i64 %x)
// CHECK: noundef i64 @int(i64 noundef %x)
#[no_mangle]
pub fn int(x: u64) -> u64 {
x
Expand All @@ -73,7 +73,7 @@ pub fn nonzero_int(x: NonZeroU64) -> NonZeroU64 {
x
}

// CHECK: i64 @option_nonzero_int(i64 %x)
// CHECK: noundef i64 @option_nonzero_int(i64 noundef %x)
#[no_mangle]
pub fn option_nonzero_int(x: Option<NonZeroU64>) -> Option<NonZeroU64> {
x
Expand Down Expand Up @@ -138,11 +138,27 @@ pub fn indirect_struct(_: S) {
pub fn borrowed_struct(_: &S) {
}

// CHECK: @raw_struct({{%S\*|ptr}} %_1)
// CHECK: @option_borrow({{i32\*|ptr}} noalias noundef readonly align 4 dereferenceable_or_null(4) %x)
#[no_mangle]
pub fn option_borrow(x: Option<&i32>) {
}

// CHECK: @option_borrow_mut({{i32\*|ptr}} noalias noundef align 4 dereferenceable_or_null(4) %x)
#[no_mangle]
pub fn option_borrow_mut(x: Option<&mut i32>) {
}

// CHECK: @raw_struct({{%S\*|ptr}} noundef %_1)
#[no_mangle]
pub fn raw_struct(_: *const S) {
}

// CHECK: @raw_option_nonnull_struct({{i32\*|ptr}} noundef %_1)
#[no_mangle]
pub fn raw_option_nonnull_struct(_: Option<NonNull<S>>) {
}


// `Box` can get deallocated during execution of the function, so it should
// not get `dereferenceable`.
// CHECK: noundef nonnull align 4 {{i32\*|ptr}} @_box({{i32\*|ptr}} noalias noundef nonnull align 4 %x)
Expand All @@ -160,35 +176,35 @@ pub fn struct_return() -> S {
}

// Hack to get the correct size for the length part in slices
// CHECK: @helper([[USIZE:i[0-9]+]] %_1)
// CHECK: @helper([[USIZE:i[0-9]+]] noundef %_1)
#[no_mangle]
pub fn helper(_: usize) {
}

// CHECK: @slice({{\[0 x i8\]\*|ptr}} noalias noundef nonnull readonly align 1 %_1.0, [[USIZE]] %_1.1)
// CHECK: @slice({{\[0 x i8\]\*|ptr}} noalias noundef nonnull readonly align 1 %_1.0, [[USIZE]] noundef %_1.1)
// FIXME #25759 This should also have `nocapture`
#[no_mangle]
pub fn slice(_: &[u8]) {
}

// CHECK: @mutable_slice({{\[0 x i8\]\*|ptr}} noalias noundef nonnull align 1 %_1.0, [[USIZE]] %_1.1)
// CHECK: @mutable_slice({{\[0 x i8\]\*|ptr}} noalias noundef nonnull align 1 %_1.0, [[USIZE]] noundef %_1.1)
// FIXME #25759 This should also have `nocapture`
#[no_mangle]
pub fn mutable_slice(_: &mut [u8]) {
}

// CHECK: @unsafe_slice({{\[0 x i16\]\*|ptr}} noundef nonnull align 2 %_1.0, [[USIZE]] %_1.1)
// CHECK: @unsafe_slice({{\[0 x i16\]\*|ptr}} noundef nonnull align 2 %_1.0, [[USIZE]] noundef %_1.1)
// unsafe interior means this isn't actually readonly and there may be aliases ...
#[no_mangle]
pub fn unsafe_slice(_: &[UnsafeInner]) {
}

// CHECK: @raw_slice({{\[0 x i8\]\*|ptr}} %_1.0, [[USIZE]] %_1.1)
// CHECK: @raw_slice({{\[0 x i8\]\*|ptr}} noundef %_1.0, [[USIZE]] noundef %_1.1)
#[no_mangle]
pub fn raw_slice(_: *const [u8]) {
}

// CHECK: @str({{\[0 x i8\]\*|ptr}} noalias noundef nonnull readonly align 1 %_1.0, [[USIZE]] %_1.1)
// CHECK: @str({{\[0 x i8\]\*|ptr}} noalias noundef nonnull readonly align 1 %_1.0, [[USIZE]] noundef %_1.1)
// FIXME #25759 This should also have `nocapture`
#[no_mangle]
pub fn str(_: &[u8]) {
Expand All @@ -197,26 +213,36 @@ pub fn str(_: &[u8]) {
// CHECK: @trait_borrow({{\{\}\*|ptr}} noundef nonnull align 1 %_1.0, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}) %_1.1)
// FIXME #25759 This should also have `nocapture`
#[no_mangle]
pub fn trait_borrow(_: &Drop) {
pub fn trait_borrow(_: &dyn Drop) {
}

// CHECK: @option_trait_borrow({{i8\*|ptr}} noundef align 1 %x.0, {{i8\*|ptr}} %x.1)
#[no_mangle]
pub fn option_trait_borrow(x: Option<&dyn Drop>) {
}

// CHECK: @option_trait_borrow_mut({{i8\*|ptr}} noundef align 1 %x.0, {{i8\*|ptr}} %x.1)
#[no_mangle]
pub fn option_trait_borrow_mut(x: Option<&mut dyn Drop>) {
}

// CHECK: @trait_raw({{\{\}\*|ptr}} %_1.0, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}) %_1.1)
// CHECK: @trait_raw({{\{\}\*|ptr}} noundef %_1.0, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}) %_1.1)
#[no_mangle]
pub fn trait_raw(_: *const Drop) {
pub fn trait_raw(_: *const dyn Drop) {
}

// CHECK: @trait_box({{\{\}\*|ptr}} noalias noundef nonnull align 1{{( %0)?}}, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}){{( %1)?}})
#[no_mangle]
pub fn trait_box(_: Box<Drop>) {
pub fn trait_box(_: Box<dyn Drop>) {
}

// CHECK: { {{i8\*|ptr}}, {{i8\*|ptr}} } @trait_option({{i8\*|ptr}} noalias noundef align 1 %x.0, {{i8\*|ptr}} %x.1)
#[no_mangle]
pub fn trait_option(x: Option<Box<Drop>>) -> Option<Box<Drop>> {
pub fn trait_option(x: Option<Box<dyn Drop>>) -> Option<Box<dyn Drop>> {
x
}

// CHECK: { {{\[0 x i16\]\*|ptr}}, [[USIZE]] } @return_slice({{\[0 x i16\]\*|ptr}} noalias noundef nonnull readonly align 2 %x.0, [[USIZE]] %x.1)
// CHECK: { {{\[0 x i16\]\*|ptr}}, [[USIZE]] } @return_slice({{\[0 x i16\]\*|ptr}} noalias noundef nonnull readonly align 2 %x.0, [[USIZE]] noundef %x.1)
#[no_mangle]
pub fn return_slice(x: &[u16]) -> &[u16] {
x
Expand Down
2 changes: 1 addition & 1 deletion tests/codegen/intrinsics/const_eval_select.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// compile-flags: -C no-prepopulate-passes
// compile-flags: -C no-prepopulate-passes -Copt-level=0

#![crate_type = "lib"]
#![feature(const_eval_select)]
Expand Down
3 changes: 2 additions & 1 deletion tests/codegen/intrinsics/mask.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// compile-flags: -Copt-level=0
#![crate_type = "lib"]
#![feature(core_intrinsics)]

Expand All @@ -6,6 +7,6 @@
#[no_mangle]
pub fn mask_ptr(ptr: *const u16, mask: usize) -> *const u16 {
// CHECK: call
// CHECK-SAME: @llvm.ptrmask.{{p0|p0i8}}.[[WORD]]({{ptr|i8\*}} {{%ptr|%0}}, [[WORD]] %mask)
// CHECK-SAME: @llvm.ptrmask.{{p0|p0i8}}.[[WORD]]({{ptr|i8\*}} {{%ptr|%1}}, [[WORD]] %mask)
core::intrinsics::ptr_mask(ptr, mask)
}
2 changes: 1 addition & 1 deletion tests/codegen/issue-32031.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// compile-flags: -C no-prepopulate-passes
// compile-flags: -C no-prepopulate-passes -Copt-level=0

#![crate_type = "lib"]

Expand Down
2 changes: 1 addition & 1 deletion tests/codegen/issue-58881.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// compile-flags: -C no-prepopulate-passes
// compile-flags: -C no-prepopulate-passes -Copt-level=0
//
// only-x86_64
// ignore-windows
Expand Down
Loading