Skip to content

Commit 427cf81

Browse files
committed
Auto merge of #94158 - erikdesjardins:more-more-noundef, r=nikic
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) #74378.
2 parents ec0ab61 + fec4335 commit 427cf81

File tree

3 files changed

+98
-4
lines changed

3 files changed

+98
-4
lines changed

compiler/rustc_codegen_llvm/src/builder.rs

+14
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,10 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
479479
load: &'ll Value,
480480
scalar: abi::Scalar,
481481
) {
482+
if !scalar.is_always_valid(bx) {
483+
bx.noundef_metadata(load);
484+
}
485+
482486
match scalar.value {
483487
abi::Int(..) => {
484488
if !scalar.is_always_valid(bx) {
@@ -1215,6 +1219,16 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
12151219
}
12161220
}
12171221

1222+
fn noundef_metadata(&mut self, load: &'ll Value) {
1223+
unsafe {
1224+
llvm::LLVMSetMetadata(
1225+
load,
1226+
llvm::MD_noundef as c_uint,
1227+
llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0),
1228+
);
1229+
}
1230+
}
1231+
12181232
pub fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
12191233
unsafe { llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs) }
12201234
}

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+1
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,7 @@ pub enum MetadataType {
442442
MD_mem_parallel_loop_access = 10,
443443
MD_nonnull = 11,
444444
MD_type = 19,
445+
MD_noundef = 29,
445446
}
446447

447448
/// LLVMRustAsmDialect

src/test/codegen/loads.rs

+83-4
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,87 @@
22

33
#![crate_type = "lib"]
44

5+
use std::mem::MaybeUninit;
6+
use std::num::NonZeroU16;
7+
58
pub struct Bytes {
6-
a: u8,
7-
b: u8,
8-
c: u8,
9-
d: u8,
9+
a: u8,
10+
b: u8,
11+
c: u8,
12+
d: u8,
13+
}
14+
15+
#[derive(Copy, Clone)]
16+
pub enum MyBool {
17+
True,
18+
False,
19+
}
20+
21+
// CHECK-LABEL: @load_ref
22+
#[no_mangle]
23+
pub fn load_ref<'a>(x: &&'a i32) -> &'a i32 {
24+
// Alignment of a reference itself is target dependent, so just match any alignment:
25+
// the main thing we care about here is !nonnull and !noundef.
26+
// CHECK: load i32*, i32** %x, align {{[0-9]+}}, !nonnull !{{[0-9]+}}, !noundef !{{[0-9]+}}
27+
*x
28+
}
29+
30+
// CHECK-LABEL: @load_box
31+
#[no_mangle]
32+
pub fn load_box<'a>(x: Box<Box<i32>>) -> Box<i32> {
33+
// Alignment of a box itself is target dependent, so just match any alignment:
34+
// the main thing we care about here is !nonnull and !noundef.
35+
// CHECK: load i32*, i32** %x, align {{[0-9]+}}, !nonnull !{{[0-9]+}}, !noundef !{{[0-9]+}}
36+
*x
37+
}
38+
39+
// CHECK-LABEL: @load_bool
40+
#[no_mangle]
41+
pub fn load_bool(x: &bool) -> bool {
42+
// CHECK: load i8, i8* %x, align 1, !range ![[BOOL_RANGE:[0-9]+]], !noundef !{{[0-9]+}}
43+
*x
44+
}
45+
46+
// CHECK-LABEL: @load_maybeuninit_bool
47+
#[no_mangle]
48+
pub fn load_maybeuninit_bool(x: &MaybeUninit<bool>) -> MaybeUninit<bool> {
49+
// CHECK: load i8, i8* %x, align 1{{$}}
50+
*x
51+
}
52+
53+
// CHECK-LABEL: @load_enum_bool
54+
#[no_mangle]
55+
pub fn load_enum_bool(x: &MyBool) -> MyBool {
56+
// CHECK: load i8, i8* %x, align 1, !range ![[BOOL_RANGE]], !noundef !{{[0-9]+}}
57+
*x
58+
}
59+
60+
// CHECK-LABEL: @load_maybeuninit_enum_bool
61+
#[no_mangle]
62+
pub fn load_maybeuninit_enum_bool(x: &MaybeUninit<MyBool>) -> MaybeUninit<MyBool> {
63+
// CHECK: load i8, i8* %x, align 1{{$}}
64+
*x
65+
}
66+
67+
// CHECK-LABEL: @load_int
68+
#[no_mangle]
69+
pub fn load_int(x: &u16) -> u16 {
70+
// CHECK: load i16, i16* %x, align 2{{$}}
71+
*x
72+
}
73+
74+
// CHECK-LABEL: @load_nonzero_int
75+
#[no_mangle]
76+
pub fn load_nonzero_int(x: &NonZeroU16) -> NonZeroU16 {
77+
// CHECK: load i16, i16* %x, align 2, !range ![[NONZEROU16_RANGE:[0-9]+]], !noundef !{{[0-9]+}}
78+
*x
79+
}
80+
81+
// CHECK-LABEL: @load_option_nonzero_int
82+
#[no_mangle]
83+
pub fn load_option_nonzero_int(x: &Option<NonZeroU16>) -> Option<NonZeroU16> {
84+
// CHECK: load i16, i16* %x, align 2{{$}}
85+
*x
1086
}
1187

1288
// CHECK-LABEL: @borrow
@@ -43,3 +119,6 @@ pub fn small_struct_alignment(x: Bytes) -> Bytes {
43119
// CHECK: ret i32 [[VAR]]
44120
x
45121
}
122+
123+
// CHECK: ![[BOOL_RANGE]] = !{i8 0, i8 2}
124+
// CHECK: ![[NONZEROU16_RANGE]] = !{i16 1, i16 0}

0 commit comments

Comments
 (0)