@@ -23,12 +23,16 @@ extern crate stable_mir;
23
23
24
24
use rustc_middle:: ty:: TyCtxt ;
25
25
use rustc_smir:: rustc_internal;
26
- use stable_mir:: { CrateItem , CrateItems , ItemKind } ;
27
26
use stable_mir:: crate_def:: CrateDef ;
28
27
use stable_mir:: mir:: alloc:: GlobalAlloc ;
29
- use stable_mir:: mir:: mono:: StaticDef ;
28
+ use stable_mir:: mir:: mono:: { Instance , StaticDef } ;
29
+ use stable_mir:: mir:: Body ;
30
+ use stable_mir:: ty:: { Allocation , ConstantKind } ;
31
+ use stable_mir:: { CrateItem , CrateItems , ItemKind } ;
30
32
use std:: ascii:: Char ;
31
33
use std:: assert_matches:: assert_matches;
34
+ use std:: cmp:: { max, min} ;
35
+ use std:: collections:: HashMap ;
32
36
use std:: io:: Write ;
33
37
use std:: ops:: ControlFlow ;
34
38
@@ -41,6 +45,7 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
41
45
check_foo ( * get_item ( & items, ( ItemKind :: Static , "FOO" ) ) . unwrap ( ) ) ;
42
46
check_bar ( * get_item ( & items, ( ItemKind :: Static , "BAR" ) ) . unwrap ( ) ) ;
43
47
check_len ( * get_item ( & items, ( ItemKind :: Static , "LEN" ) ) . unwrap ( ) ) ;
48
+ check_other_consts ( * get_item ( & items, ( ItemKind :: Fn , "other_consts" ) ) . unwrap ( ) ) ;
44
49
ControlFlow :: Continue ( ( ) )
45
50
}
46
51
@@ -80,6 +85,73 @@ fn check_bar(item: CrateItem) {
80
85
assert_eq ! ( std:: str :: from_utf8( & allocation. raw_bytes( ) . unwrap( ) ) , Ok ( "Bar" ) ) ;
81
86
}
82
87
88
+ /// Check the allocation data for constants used in `other_consts` function.
89
+ fn check_other_consts ( item : CrateItem ) {
90
+ // Instance body will force constant evaluation.
91
+ let body = Instance :: try_from ( item) . unwrap ( ) . body ( ) . unwrap ( ) ;
92
+ let assigns = collect_consts ( & body) ;
93
+ assert_eq ! ( assigns. len( ) , 9 ) ;
94
+ for ( name, alloc) in assigns {
95
+ match name. as_str ( ) {
96
+ "_max_u128" => {
97
+ assert_eq ! ( alloc. read_uint( ) , Ok ( u128 :: MAX ) , "Failed parsing allocation: {alloc:?}" )
98
+ }
99
+ "_min_i128" => {
100
+ assert_eq ! ( alloc. read_int( ) , Ok ( i128 :: MIN ) , "Failed parsing allocation: {alloc:?}" )
101
+ }
102
+ "_max_i8" => {
103
+ assert_eq ! (
104
+ alloc. read_int( ) . unwrap( ) as i8 ,
105
+ i8 :: MAX ,
106
+ "Failed parsing allocation: {alloc:?}"
107
+ )
108
+ }
109
+ "_char" => {
110
+ assert_eq ! (
111
+ char :: from_u32( alloc. read_uint( ) . unwrap( ) as u32 ) ,
112
+ Some ( 'x' ) ,
113
+ "Failed parsing allocation: {alloc:?}"
114
+ )
115
+ }
116
+ "_false" => {
117
+ assert_eq ! ( alloc. read_bool( ) , Ok ( false ) , "Failed parsing allocation: {alloc:?}" )
118
+ }
119
+ "_true" => {
120
+ assert_eq ! ( alloc. read_bool( ) , Ok ( true ) , "Failed parsing allocation: {alloc:?}" )
121
+ }
122
+ "_ptr" => {
123
+ assert_eq ! ( alloc. is_null( ) , Ok ( false ) , "Failed parsing allocation: {alloc:?}" )
124
+ }
125
+ "_null_ptr" => {
126
+ assert_eq ! ( alloc. is_null( ) , Ok ( true ) , "Failed parsing allocation: {alloc:?}" )
127
+ }
128
+ "_tuple" => {
129
+ // The order of fields is not guaranteed.
130
+ let first = alloc. read_partial_uint ( 0 ..4 ) . unwrap ( ) ;
131
+ let second = alloc. read_partial_uint ( 4 ..8 ) . unwrap ( ) ;
132
+ assert_eq ! ( max( first, second) as u32 , u32 :: MAX ) ;
133
+ assert_eq ! ( min( first, second) , 10 ) ;
134
+ }
135
+ _ => {
136
+ unreachable ! ( "{name} -- {alloc:?}" )
137
+ }
138
+ }
139
+ }
140
+ }
141
+
142
+ /// Collects all the constant assignments.
143
+ pub fn collect_consts ( body : & Body ) -> HashMap < String , & Allocation > {
144
+ body. var_debug_info
145
+ . iter ( )
146
+ . filter_map ( |info| {
147
+ info. constant ( ) . map ( |const_op| {
148
+ let ConstantKind :: Allocated ( alloc) = const_op. const_ . kind ( ) else { unreachable ! ( ) } ;
149
+ ( info. name . clone ( ) , alloc)
150
+ } )
151
+ } )
152
+ . collect :: < HashMap < _ , _ > > ( )
153
+ }
154
+
83
155
/// Check the allocation data for `LEN`.
84
156
///
85
157
/// ```no_run
@@ -97,9 +169,7 @@ fn get_item<'a>(
97
169
items : & ' a CrateItems ,
98
170
item : ( ItemKind , & str ) ,
99
171
) -> Option < & ' a stable_mir:: CrateItem > {
100
- items. iter ( ) . find ( |crate_item| {
101
- ( item. 0 == crate_item. kind ( ) ) && crate_item. name ( ) == item. 1
102
- } )
172
+ items. iter ( ) . find ( |crate_item| ( item. 0 == crate_item. kind ( ) ) && crate_item. name ( ) == item. 1 )
103
173
}
104
174
105
175
/// This test will generate and analyze a dummy crate using the stable mir.
@@ -126,10 +196,25 @@ fn generate_input(path: &str) -> std::io::Result<()> {
126
196
static LEN: usize = 2;
127
197
static FOO: [&str; 2] = ["hi", "there"];
128
198
static BAR: &str = "Bar";
199
+ const NULL: *const u8 = std::ptr::null();
200
+ const TUPLE: (u32, u32) = (10, u32::MAX);
201
+
202
+ fn other_consts() {{
203
+ let _max_u128 = u128::MAX;
204
+ let _min_i128 = i128::MIN;
205
+ let _max_i8 = i8::MAX;
206
+ let _char = 'x';
207
+ let _false = false;
208
+ let _true = true;
209
+ let _ptr = &BAR;
210
+ let _null_ptr: *const u8 = NULL;
211
+ let _tuple = TUPLE;
212
+ }}
129
213
130
214
pub fn main() {{
131
215
println!("{{FOO:?}}! {{BAR}}");
132
216
assert_eq!(FOO.len(), LEN);
217
+ other_consts();
133
218
}}"#
134
219
) ?;
135
220
Ok ( ( ) )
0 commit comments