@@ -125,11 +125,111 @@ impl<'tcx, 'ctx> Analyzer<'tcx, 'ctx> {
125125 clauses
126126 }
127127
128+ fn const_bytes_ty (
129+ & self ,
130+ ty : mir_ty:: Ty < ' tcx > ,
131+ alloc : mir:: interpret:: ConstAllocation ,
132+ range : std:: ops:: Range < usize > ,
133+ ) -> PlaceType {
134+ let alloc = alloc. inner ( ) ;
135+ let bytes = alloc. inspect_with_uninit_and_ptr_outside_interpreter ( range) ;
136+ match ty. kind ( ) {
137+ mir_ty:: TyKind :: Str => {
138+ let content = std:: str:: from_utf8 ( bytes) . unwrap ( ) ;
139+ PlaceType :: with_ty_and_term (
140+ rty:: Type :: string ( ) ,
141+ chc:: Term :: string ( content. to_owned ( ) ) ,
142+ )
143+ }
144+ mir_ty:: TyKind :: Bool => {
145+ PlaceType :: with_ty_and_term ( rty:: Type :: bool ( ) , chc:: Term :: bool ( bytes[ 0 ] != 0 ) )
146+ }
147+ mir_ty:: Int ( _) => {
148+ // TODO: see target endianess
149+ let val = match bytes. len ( ) {
150+ 1 => i8:: from_ne_bytes ( bytes. try_into ( ) . unwrap ( ) ) as i64 ,
151+ 2 => i16:: from_ne_bytes ( bytes. try_into ( ) . unwrap ( ) ) as i64 ,
152+ 4 => i32:: from_ne_bytes ( bytes. try_into ( ) . unwrap ( ) ) as i64 ,
153+ 8 => i64:: from_ne_bytes ( bytes. try_into ( ) . unwrap ( ) ) ,
154+ _ => unimplemented ! ( "const int bytes len: {}" , bytes. len( ) ) ,
155+ } ;
156+ PlaceType :: with_ty_and_term ( rty:: Type :: int ( ) , chc:: Term :: int ( val) )
157+ }
158+ _ => unimplemented ! ( "const bytes ty: {:?}" , ty) ,
159+ }
160+ }
161+
162+ fn const_value_ty ( & self , val : & mir:: ConstValue < ' tcx > , ty : & mir_ty:: Ty < ' tcx > ) -> PlaceType {
163+ use mir:: { interpret:: Scalar , ConstValue , Mutability } ;
164+ match ( ty. kind ( ) , val) {
165+ ( mir_ty:: TyKind :: Int ( _) , ConstValue :: Scalar ( Scalar :: Int ( val) ) ) => {
166+ let val = val. try_to_int ( val. size ( ) ) . unwrap ( ) ;
167+ PlaceType :: with_ty_and_term (
168+ rty:: Type :: int ( ) ,
169+ chc:: Term :: int ( val. try_into ( ) . unwrap ( ) ) ,
170+ )
171+ }
172+ ( mir_ty:: TyKind :: Bool , ConstValue :: Scalar ( Scalar :: Int ( val) ) ) => {
173+ PlaceType :: with_ty_and_term (
174+ rty:: Type :: bool ( ) ,
175+ chc:: Term :: bool ( val. try_to_bool ( ) . unwrap ( ) ) ,
176+ )
177+ }
178+ (
179+ mir_ty:: TyKind :: Ref ( _, elem, Mutability :: Not ) ,
180+ ConstValue :: Scalar ( Scalar :: Ptr ( ptr, _) ) ,
181+ ) => {
182+ // Pointer::into_parts is OK for CtfeProvenance
183+ // in later version of rustc it has prov_and_relative_offset that ensures this
184+ let ( prov, offset) = ptr. into_parts ( ) ;
185+ let global_alloc = self . tcx . global_alloc ( prov. alloc_id ( ) ) ;
186+ match global_alloc {
187+ mir:: interpret:: GlobalAlloc :: Memory ( alloc) => {
188+ let layout = self
189+ . tcx
190+ . layout_of ( mir_ty:: ParamEnv :: reveal_all ( ) . and ( * elem) )
191+ . unwrap ( ) ;
192+ let size = layout. size ;
193+ let range =
194+ offset. bytes ( ) as usize ..( offset. bytes ( ) + size. bytes ( ) ) as usize ;
195+ self . const_bytes_ty ( * elem, alloc, range) . immut ( )
196+ }
197+ _ => unimplemented ! ( "const ptr alloc: {:?}" , global_alloc) ,
198+ }
199+ }
200+ ( mir_ty:: TyKind :: Ref ( _, elem, Mutability :: Not ) , ConstValue :: Slice { data, meta } ) => {
201+ let end = ( * meta) . try_into ( ) . unwrap ( ) ;
202+ self . const_bytes_ty ( * elem, * data, 0 ..end) . immut ( )
203+ }
204+ _ => unimplemented ! ( "const: {:?}, ty: {:?}" , val, ty) ,
205+ }
206+ }
207+
208+ fn const_ty ( & self , const_ : & mir:: Const < ' tcx > ) -> PlaceType {
209+ match const_ {
210+ mir:: Const :: Val ( val, ty) => self . const_value_ty ( val, ty) ,
211+ mir:: Const :: Unevaluated ( unevaluated, ty) => {
212+ // since all constants are immutable in current setup,
213+ // it should be okay to evaluate them here on-the-fly
214+ let param_env = self . tcx . param_env ( self . local_def_id ) ;
215+ let val = self
216+ . tcx
217+ . const_eval_resolve ( param_env, * unevaluated, None )
218+ . unwrap ( ) ;
219+ self . const_value_ty ( & val, ty)
220+ }
221+ _ => unimplemented ! ( "const: {:?}" , const_) ,
222+ }
223+ }
224+
128225 fn operand_type ( & self , mut operand : Operand < ' tcx > ) -> PlaceType {
129226 if let Operand :: Copy ( p) | Operand :: Move ( p) = & mut operand {
130227 * p = self . elaborate_place ( p) ;
131228 }
132- let ty = self . env . operand_type ( operand. clone ( ) ) ;
229+ let ty = match & operand {
230+ Operand :: Copy ( place) | Operand :: Move ( place) => self . env . place_type ( * place) ,
231+ Operand :: Constant ( operand) => self . const_ty ( & operand. const_ ) ,
232+ } ;
133233 tracing:: debug!( operand = ?operand, ty = %ty. display( ) , "operand_type" ) ;
134234 ty
135235 }
0 commit comments