55use syntax:: symbol:: Symbol ;
66use rustc:: ty;
77use rustc:: ty:: layout:: { LayoutOf , Primitive , Size } ;
8+ use rustc:: ty:: subst:: SubstsRef ;
9+ use rustc:: hir:: def_id:: DefId ;
10+ use rustc:: ty:: TyCtxt ;
811use rustc:: mir:: BinOp ;
9- use rustc:: mir:: interpret:: { InterpResult , Scalar } ;
12+ use rustc:: mir:: interpret:: { InterpResult , Scalar , GlobalId , ConstValue } ;
1013
1114use super :: {
12- Machine , PlaceTy , OpTy , InterpCx , Immediate ,
15+ Machine , PlaceTy , OpTy , InterpCx ,
1316} ;
1417
1518mod type_name;
1619
17- pub use type_name:: * ;
18-
1920fn numeric_intrinsic < ' tcx , Tag > (
2021 name : & str ,
2122 bits : u128 ,
@@ -37,6 +38,50 @@ fn numeric_intrinsic<'tcx, Tag>(
3738 Ok ( Scalar :: from_uint ( bits_out, size) )
3839}
3940
41+ /// The logic for all nullary intrinsics is implemented here. These intrinsics don't get evaluated
42+ /// inside an `InterpCx` and instead have their value computed directly from rustc internal info.
43+ crate fn eval_nullary_intrinsic < ' tcx > (
44+ tcx : TyCtxt < ' tcx > ,
45+ param_env : ty:: ParamEnv < ' tcx > ,
46+ def_id : DefId ,
47+ substs : SubstsRef < ' tcx > ,
48+ ) -> InterpResult < ' tcx , & ' tcx ty:: Const < ' tcx > > {
49+ let tp_ty = substs. type_at ( 0 ) ;
50+ let name = & * tcx. item_name ( def_id) . as_str ( ) ;
51+ Ok ( match name {
52+ "type_name" => {
53+ let alloc = type_name:: alloc_type_name ( tcx, tp_ty) ;
54+ tcx. mk_const ( ty:: Const {
55+ val : ConstValue :: Slice {
56+ data : alloc,
57+ start : 0 ,
58+ end : alloc. len ( ) ,
59+ } ,
60+ ty : tcx. mk_static_str ( ) ,
61+ } )
62+ } ,
63+ "needs_drop" => ty:: Const :: from_bool ( tcx, tp_ty. needs_drop ( tcx, param_env) ) ,
64+ "size_of" |
65+ "min_align_of" |
66+ "pref_align_of" => {
67+ let layout = tcx. layout_of ( param_env. and ( tp_ty) ) . map_err ( |e| err_inval ! ( Layout ( e) ) ) ?;
68+ let n = match name {
69+ "pref_align_of" => layout. align . pref . bytes ( ) ,
70+ "min_align_of" => layout. align . abi . bytes ( ) ,
71+ "size_of" => layout. size . bytes ( ) ,
72+ _ => bug ! ( ) ,
73+ } ;
74+ ty:: Const :: from_usize ( tcx, n)
75+ } ,
76+ "type_id" => ty:: Const :: from_bits (
77+ tcx,
78+ tcx. type_id_hash ( tp_ty) . into ( ) ,
79+ param_env. and ( tcx. types . u64 ) ,
80+ ) ,
81+ other => bug ! ( "`{}` is not a zero arg intrinsic" , other) ,
82+ } )
83+ }
84+
4085impl < ' mir , ' tcx , M : Machine < ' mir , ' tcx > > InterpCx < ' mir , ' tcx , M > {
4186 /// Returns `true` if emulation happened.
4287 pub fn emulate_intrinsic (
@@ -49,41 +94,19 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
4994
5095 let intrinsic_name = & self . tcx . item_name ( instance. def_id ( ) ) . as_str ( ) [ ..] ;
5196 match intrinsic_name {
52- "min_align_of" => {
53- let elem_ty = substs. type_at ( 0 ) ;
54- let elem_align = self . layout_of ( elem_ty) ?. align . abi . bytes ( ) ;
55- let align_val = Scalar :: from_uint ( elem_align, dest. layout . size ) ;
56- self . write_scalar ( align_val, dest) ?;
57- }
58-
59- "needs_drop" => {
60- let ty = substs. type_at ( 0 ) ;
61- let ty_needs_drop = ty. needs_drop ( self . tcx . tcx , self . param_env ) ;
62- let val = Scalar :: from_bool ( ty_needs_drop) ;
63- self . write_scalar ( val, dest) ?;
64- }
65-
66- "size_of" => {
67- let ty = substs. type_at ( 0 ) ;
68- let size = self . layout_of ( ty) ?. size . bytes ( ) as u128 ;
69- let size_val = Scalar :: from_uint ( size, dest. layout . size ) ;
70- self . write_scalar ( size_val, dest) ?;
71- }
72-
73- "type_id" => {
74- let ty = substs. type_at ( 0 ) ;
75- let type_id = self . tcx . type_id_hash ( ty) as u128 ;
76- let id_val = Scalar :: from_uint ( type_id, dest. layout . size ) ;
77- self . write_scalar ( id_val, dest) ?;
78- }
79-
97+ "min_align_of" |
98+ "pref_align_of" |
99+ "needs_drop" |
100+ "size_of" |
101+ "type_id" |
80102 "type_name" => {
81- let alloc = alloc_type_name ( self . tcx . tcx , substs. type_at ( 0 ) ) ;
82- let name_id = self . tcx . alloc_map . lock ( ) . create_memory_alloc ( alloc) ;
83- let id_ptr = self . memory . tag_static_base_pointer ( name_id. into ( ) ) ;
84- let alloc_len = alloc. size . bytes ( ) ;
85- let name_val = Immediate :: new_slice ( Scalar :: Ptr ( id_ptr) , alloc_len, self ) ;
86- self . write_immediate ( name_val, dest) ?;
103+ let gid = GlobalId {
104+ instance,
105+ promoted : None ,
106+ } ;
107+ let val = self . tcx . const_eval ( self . param_env . and ( gid) ) ?;
108+ let val = self . eval_const_to_op ( val, None ) ?;
109+ self . copy_op ( val, dest) ?;
87110 }
88111
89112 | "ctpop"
0 commit comments