5
5
use syntax:: symbol:: Symbol ;
6
6
use rustc:: ty;
7
7
use rustc:: ty:: layout:: { LayoutOf , Primitive , Size } ;
8
+ use rustc:: ty:: subst:: SubstsRef ;
9
+ use rustc:: hir:: def_id:: DefId ;
10
+ use rustc:: ty:: TyCtxt ;
8
11
use rustc:: mir:: BinOp ;
9
- use rustc:: mir:: interpret:: { InterpResult , Scalar } ;
12
+ use rustc:: mir:: interpret:: { InterpResult , Scalar , GlobalId , ConstValue } ;
10
13
11
14
use super :: {
12
- Machine , PlaceTy , OpTy , InterpCx , Immediate ,
15
+ Machine , PlaceTy , OpTy , InterpCx ,
13
16
} ;
14
17
15
18
mod type_name;
16
19
17
- pub use type_name:: * ;
18
-
19
20
fn numeric_intrinsic < ' tcx , Tag > (
20
21
name : & str ,
21
22
bits : u128 ,
@@ -37,6 +38,50 @@ fn numeric_intrinsic<'tcx, Tag>(
37
38
Ok ( Scalar :: from_uint ( bits_out, size) )
38
39
}
39
40
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
+
40
85
impl < ' mir , ' tcx , M : Machine < ' mir , ' tcx > > InterpCx < ' mir , ' tcx , M > {
41
86
/// Returns `true` if emulation happened.
42
87
pub fn emulate_intrinsic (
@@ -49,41 +94,19 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
49
94
50
95
let intrinsic_name = & self . tcx . item_name ( instance. def_id ( ) ) . as_str ( ) [ ..] ;
51
96
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" |
80
102
"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) ?;
87
110
}
88
111
89
112
| "ctpop"
0 commit comments