@@ -23,12 +23,16 @@ extern crate stable_mir;
2323
2424use rustc_middle:: ty:: TyCtxt ;
2525use rustc_smir:: rustc_internal;
26- use stable_mir:: { CrateItem , CrateItems , ItemKind } ;
2726use stable_mir:: crate_def:: CrateDef ;
2827use 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 } ;
3032use std:: ascii:: Char ;
3133use std:: assert_matches:: assert_matches;
34+ use std:: cmp:: { max, min} ;
35+ use std:: collections:: HashMap ;
3236use std:: io:: Write ;
3337use std:: ops:: ControlFlow ;
3438
@@ -41,6 +45,7 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
4145 check_foo ( * get_item ( & items, ( ItemKind :: Static , "FOO" ) ) . unwrap ( ) ) ;
4246 check_bar ( * get_item ( & items, ( ItemKind :: Static , "BAR" ) ) . unwrap ( ) ) ;
4347 check_len ( * get_item ( & items, ( ItemKind :: Static , "LEN" ) ) . unwrap ( ) ) ;
48+ check_other_consts ( * get_item ( & items, ( ItemKind :: Fn , "other_consts" ) ) . unwrap ( ) ) ;
4449 ControlFlow :: Continue ( ( ) )
4550}
4651
@@ -80,6 +85,73 @@ fn check_bar(item: CrateItem) {
8085 assert_eq ! ( std:: str :: from_utf8( & allocation. raw_bytes( ) . unwrap( ) ) , Ok ( "Bar" ) ) ;
8186}
8287
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+
83155/// Check the allocation data for `LEN`.
84156///
85157/// ```no_run
@@ -97,9 +169,7 @@ fn get_item<'a>(
97169 items : & ' a CrateItems ,
98170 item : ( ItemKind , & str ) ,
99171) -> 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 )
103173}
104174
105175/// 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<()> {
126196 static LEN: usize = 2;
127197 static FOO: [&str; 2] = ["hi", "there"];
128198 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+ }}
129213
130214 pub fn main() {{
131215 println!("{{FOO:?}}! {{BAR}}");
132216 assert_eq!(FOO.len(), LEN);
217+ other_consts();
133218 }}"#
134219 ) ?;
135220 Ok ( ( ) )
0 commit comments