From 5979b681e6f7cfd760f45440624f8bc1759d2071 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sat, 12 Feb 2022 01:38:24 -0500 Subject: [PATCH 1/2] Apply noundef attribute to all scalar types which do not permit raw init Beyond `&`/`&mut`/`Box`, this covers `char`, discriminants, `NonZero*`, etc. All such types currently cause a Miri error if left uninitialized, and an `invalid_value` lint in cases like `mem::uninitialized::()` 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. --- compiler/rustc_middle/src/ty/layout.rs | 5 +++ src/test/codegen/abi-repr-ext.rs | 4 ++- src/test/codegen/call-metadata.rs | 4 +-- src/test/codegen/function-arguments.rs | 50 +++++++++++++++++++++++++- src/test/codegen/repr-transparent.rs | 4 +-- 5 files changed, 61 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index b7b36c4945978..c77047f8a2ec2 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -3053,6 +3053,11 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { return; } + // Scalars which have invalid values cannot be undef. + if !scalar.is_always_valid(self) { + attrs.set(ArgAttribute::NoUndef); + } + // Only pointer types handled below. if scalar.value != Pointer { return; diff --git a/src/test/codegen/abi-repr-ext.rs b/src/test/codegen/abi-repr-ext.rs index 9dba1718acd8b..2b34eaf94172b 100644 --- a/src/test/codegen/abi-repr-ext.rs +++ b/src/test/codegen/abi-repr-ext.rs @@ -1,3 +1,5 @@ +// compile-flags: -O + #![crate_type="lib"] #[repr(i8)] @@ -6,7 +8,7 @@ pub enum Type { Type2 = 1 } -// CHECK: define{{( dso_local)?}} signext i8 @test() +// CHECK: define{{( dso_local)?}} noundef signext i8 @test() #[no_mangle] pub extern "C" fn test() -> Type { Type::Type1 diff --git a/src/test/codegen/call-metadata.rs b/src/test/codegen/call-metadata.rs index 030a58441e304..1c30c08d3b2e2 100644 --- a/src/test/codegen/call-metadata.rs +++ b/src/test/codegen/call-metadata.rs @@ -1,12 +1,12 @@ // Checks that range metadata gets emitted on calls to functions returning a // scalar value. -// compile-flags: -C no-prepopulate-passes +// compile-flags: -O -C no-prepopulate-passes #![crate_type = "lib"] pub fn test() { - // CHECK: call i8 @some_true(), !range [[R0:![0-9]+]] + // CHECK: call noundef i8 @some_true(), !range [[R0:![0-9]+]] // CHECK: [[R0]] = !{i8 0, i8 3} some_true(); } diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs index 17b54d86cb09f..b1ccbdd934aa9 100644 --- a/src/test/codegen/function-arguments.rs +++ b/src/test/codegen/function-arguments.rs @@ -4,6 +4,7 @@ #![feature(rustc_attrs)] use std::mem::MaybeUninit; +use std::num::NonZeroU64; pub struct S { _field: [i32; 8], @@ -13,6 +14,11 @@ pub struct UnsafeInner { _field: std::cell::UnsafeCell, } +pub enum MyBool { + True, + False, +} + // CHECK: noundef zeroext i1 @boolean(i1 noundef zeroext %x) #[no_mangle] pub fn boolean(x: bool) -> bool { @@ -25,6 +31,48 @@ pub fn maybeuninit_boolean(x: MaybeUninit) -> MaybeUninit { x } +// CHECK: noundef zeroext i1 @enum_bool(i1 noundef zeroext %x) +#[no_mangle] +pub fn enum_bool(x: MyBool) -> MyBool { + x +} + +// CHECK: i8 @maybeuninit_enum_bool(i8 %x) +#[no_mangle] +pub fn maybeuninit_enum_bool(x: MaybeUninit) -> MaybeUninit { + x +} + +// CHECK: noundef i32 @char(i32 noundef %x) +#[no_mangle] +pub fn char(x: char) -> char { + x +} + +// CHECK: i32 @maybeuninit_char(i32 %x) +#[no_mangle] +pub fn maybeuninit_char(x: MaybeUninit) -> MaybeUninit { + x +} + +// CHECK: i64 @int(i64 %x) +#[no_mangle] +pub fn int(x: u64) -> u64 { + x +} + +// CHECK: noundef i64 @nonzero_int(i64 noundef %x) +#[no_mangle] +pub fn nonzero_int(x: NonZeroU64) -> NonZeroU64 { + x +} + +// CHECK: i64 @option_nonzero_int(i64 %x) +#[no_mangle] +pub fn option_nonzero_int(x: Option) -> Option { + x +} + // CHECK: @readonly_borrow(i32* noalias noundef readonly align 4 dereferenceable(4) %_1) // FIXME #25759 This should also have `nocapture` #[no_mangle] @@ -156,7 +204,7 @@ pub fn return_slice(x: &[u16]) -> &[u16] { x } -// CHECK: { i16, i16 } @enum_id_1(i16 %x.0, i16 %x.1) +// CHECK: { i16, i16 } @enum_id_1(i16 noundef %x.0, i16 %x.1) #[no_mangle] pub fn enum_id_1(x: Option>) -> Option> { x diff --git a/src/test/codegen/repr-transparent.rs b/src/test/codegen/repr-transparent.rs index 7add522c15893..53da573ae935d 100644 --- a/src/test/codegen/repr-transparent.rs +++ b/src/test/codegen/repr-transparent.rs @@ -1,4 +1,4 @@ -// compile-flags: -C no-prepopulate-passes +// compile-flags: -O -C no-prepopulate-passes // ignore-riscv64 riscv64 has an i128 type used with test_Vector // see codegen/riscv-abi for riscv functiona call tests @@ -56,7 +56,7 @@ pub struct GenericPlusZst(T, Zst2); #[repr(u8)] pub enum Bool { True, False, FileNotFound } -// CHECK: define{{( dso_local)?}}{{( zeroext)?}} i8 @test_Gpz(i8{{( zeroext)?}} %_1) +// CHECK: define{{( dso_local)?}} noundef{{( zeroext)?}} i8 @test_Gpz(i8 noundef{{( zeroext)?}} %_1) #[no_mangle] pub extern "C" fn test_Gpz(_: GenericPlusZst) -> GenericPlusZst { loop {} } From 45ee3fc700950da07e0682c6bf56b9c123fbf995 Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Sun, 27 Feb 2022 13:40:50 -0500 Subject: [PATCH 2/2] make pgo-branch-weights test not dependent on argument attributes --- .../pgo-branch-weights/filecheck-patterns.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/run-make-fulldeps/pgo-branch-weights/filecheck-patterns.txt b/src/test/run-make-fulldeps/pgo-branch-weights/filecheck-patterns.txt index 278d46d39df28..70d5a645c1454 100644 --- a/src/test/run-make-fulldeps/pgo-branch-weights/filecheck-patterns.txt +++ b/src/test/run-make-fulldeps/pgo-branch-weights/filecheck-patterns.txt @@ -2,10 +2,10 @@ # First, establish that certain !prof labels are attached to the expected # functions and branching instructions. -CHECK: define void @function_called_twice(i32 %c) {{.*}} !prof [[function_called_twice_id:![0-9]+]] { +CHECK: define void @function_called_twice(i32 {{.*}} !prof [[function_called_twice_id:![0-9]+]] { CHECK: br i1 {{.*}}, label {{.*}}, label {{.*}}, !prof [[branch_weights0:![0-9]+]] -CHECK: define void @function_called_42_times(i32 %c) {{.*}} !prof [[function_called_42_times_id:![0-9]+]] { +CHECK: define void @function_called_42_times(i32{{.*}} %c) {{.*}} !prof [[function_called_42_times_id:![0-9]+]] { CHECK: switch i32 %c, label {{.*}} [ CHECK-NEXT: i32 97, label {{.*}} CHECK-NEXT: i32 98, label {{.*}}