2
2
//! looking at their MIR. Intrinsics/functions supported here are shared by CTFE
3
3
//! and miri.
4
4
5
- use syntax :: symbol:: Symbol ;
5
+ use syntax_pos :: symbol:: { sym , Symbol } ;
6
6
use syntax_pos:: Span ;
7
7
use rustc:: ty;
8
8
use rustc:: ty:: layout:: { LayoutOf , Primitive , Size } ;
@@ -22,7 +22,7 @@ mod caller_location;
22
22
mod type_name;
23
23
24
24
fn numeric_intrinsic < ' tcx , Tag > (
25
- name : & str ,
25
+ name : Symbol ,
26
26
bits : u128 ,
27
27
kind : Primitive ,
28
28
) -> InterpResult < ' tcx , Scalar < Tag > > {
@@ -32,11 +32,11 @@ fn numeric_intrinsic<'tcx, Tag>(
32
32
} ;
33
33
let extra = 128 - size. bits ( ) as u128 ;
34
34
let bits_out = match name {
35
- " ctpop" => bits. count_ones ( ) as u128 ,
36
- " ctlz" => bits. leading_zeros ( ) as u128 - extra,
37
- " cttz" => ( bits << extra) . trailing_zeros ( ) as u128 - extra,
38
- " bswap" => ( bits << extra) . swap_bytes ( ) ,
39
- " bitreverse" => ( bits << extra) . reverse_bits ( ) ,
35
+ sym :: ctpop => bits. count_ones ( ) as u128 ,
36
+ sym :: ctlz => bits. leading_zeros ( ) as u128 - extra,
37
+ sym :: cttz => ( bits << extra) . trailing_zeros ( ) as u128 - extra,
38
+ sym :: bswap => ( bits << extra) . swap_bytes ( ) ,
39
+ sym :: bitreverse => ( bits << extra) . reverse_bits ( ) ,
40
40
_ => bug ! ( "not a numeric intrinsic: {}" , name) ,
41
41
} ;
42
42
Ok ( Scalar :: from_uint ( bits_out, size) )
@@ -51,9 +51,9 @@ crate fn eval_nullary_intrinsic<'tcx>(
51
51
substs : SubstsRef < ' tcx > ,
52
52
) -> InterpResult < ' tcx , & ' tcx ty:: Const < ' tcx > > {
53
53
let tp_ty = substs. type_at ( 0 ) ;
54
- let name = & * tcx. item_name ( def_id) . as_str ( ) ;
54
+ let name = tcx. item_name ( def_id) ;
55
55
Ok ( match name {
56
- " type_name" => {
56
+ sym :: type_name => {
57
57
let alloc = type_name:: alloc_type_name ( tcx, tp_ty) ;
58
58
tcx. mk_const ( ty:: Const {
59
59
val : ty:: ConstKind :: Value ( ConstValue :: Slice {
@@ -64,20 +64,20 @@ crate fn eval_nullary_intrinsic<'tcx>(
64
64
ty : tcx. mk_static_str ( ) ,
65
65
} )
66
66
} ,
67
- " needs_drop" => ty:: Const :: from_bool ( tcx, tp_ty. needs_drop ( tcx, param_env) ) ,
68
- " size_of" |
69
- " min_align_of" |
70
- " pref_align_of" => {
67
+ sym :: needs_drop => ty:: Const :: from_bool ( tcx, tp_ty. needs_drop ( tcx, param_env) ) ,
68
+ sym :: size_of |
69
+ sym :: min_align_of |
70
+ sym :: pref_align_of => {
71
71
let layout = tcx. layout_of ( param_env. and ( tp_ty) ) . map_err ( |e| err_inval ! ( Layout ( e) ) ) ?;
72
72
let n = match name {
73
- " pref_align_of" => layout. align . pref . bytes ( ) ,
74
- " min_align_of" => layout. align . abi . bytes ( ) ,
75
- " size_of" => layout. size . bytes ( ) ,
73
+ sym :: pref_align_of => layout. align . pref . bytes ( ) ,
74
+ sym :: min_align_of => layout. align . abi . bytes ( ) ,
75
+ sym :: size_of => layout. size . bytes ( ) ,
76
76
_ => bug ! ( ) ,
77
77
} ;
78
78
ty:: Const :: from_usize ( tcx, n)
79
79
} ,
80
- " type_id" => ty:: Const :: from_bits (
80
+ sym :: type_id => ty:: Const :: from_bits (
81
81
tcx,
82
82
tcx. type_id_hash ( tp_ty) . into ( ) ,
83
83
param_env. and ( tcx. types . u64 ) ,
@@ -96,30 +96,32 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
96
96
ret : Option < ( PlaceTy < ' tcx , M :: PointerTag > , mir:: BasicBlock ) > ,
97
97
) -> InterpResult < ' tcx , bool > {
98
98
let substs = instance. substs ;
99
- let intrinsic_name = & * self . tcx . item_name ( instance. def_id ( ) ) . as_str ( ) ;
99
+ let intrinsic_name = self . tcx . item_name ( instance. def_id ( ) ) ;
100
100
101
101
// We currently do not handle any intrinsics that are *allowed* to diverge,
102
102
// but `transmute` could lack a return place in case of UB.
103
103
let ( dest, ret) = match ret {
104
104
Some ( p) => p,
105
105
None => match intrinsic_name {
106
- " transmute" => throw_ub ! ( Unreachable ) ,
106
+ sym :: transmute => throw_ub ! ( Unreachable ) ,
107
107
_ => return Ok ( false ) ,
108
108
}
109
109
} ;
110
110
111
+ // Keep the patterns in this match ordered the same as the list in
112
+ // `src/librustc/ty/constness.rs`
111
113
match intrinsic_name {
112
- " caller_location" => {
114
+ sym :: caller_location => {
113
115
let location = self . alloc_caller_location_for_span ( span) ;
114
116
self . write_scalar ( location. ptr , dest) ?;
115
117
}
116
118
117
- " min_align_of" |
118
- " pref_align_of" |
119
- " needs_drop" |
120
- " size_of" |
121
- " type_id" |
122
- " type_name" => {
119
+ sym :: min_align_of |
120
+ sym :: pref_align_of |
121
+ sym :: needs_drop |
122
+ sym :: size_of |
123
+ sym :: type_id |
124
+ sym :: type_name => {
123
125
let gid = GlobalId {
124
126
instance,
125
127
promoted : None ,
@@ -129,13 +131,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
129
131
self . copy_op ( val, dest) ?;
130
132
}
131
133
132
- | " ctpop"
133
- | " cttz"
134
- | " cttz_nonzero"
135
- | " ctlz"
136
- | " ctlz_nonzero"
137
- | " bswap"
138
- | " bitreverse" => {
134
+ | sym :: ctpop
135
+ | sym :: cttz
136
+ | sym :: cttz_nonzero
137
+ | sym :: ctlz
138
+ | sym :: ctlz_nonzero
139
+ | sym :: bswap
140
+ | sym :: bitreverse => {
139
141
let ty = substs. type_at ( 0 ) ;
140
142
let layout_of = self . layout_of ( ty) ?;
141
143
let val = self . read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?;
@@ -144,31 +146,32 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
144
146
ty:: layout:: Abi :: Scalar ( ref scalar) => scalar. value ,
145
147
_ => throw_unsup ! ( TypeNotPrimitive ( ty) ) ,
146
148
} ;
147
- let out_val = if intrinsic_name. ends_with ( "_nonzero" ) {
148
- if bits == 0 {
149
- throw_ub_format ! ( "`{}` called on 0" , intrinsic_name) ;
150
- }
151
- numeric_intrinsic ( intrinsic_name. trim_end_matches ( "_nonzero" ) , bits, kind) ?
152
- } else {
153
- numeric_intrinsic ( intrinsic_name, bits, kind) ?
149
+ let ( nonzero, intrinsic_name) = match intrinsic_name {
150
+ sym:: cttz_nonzero => ( true , sym:: cttz) ,
151
+ sym:: ctlz_nonzero => ( true , sym:: ctlz) ,
152
+ other => ( false , other) ,
154
153
} ;
154
+ if nonzero && bits == 0 {
155
+ throw_ub_format ! ( "`{}_nonzero` called on 0" , intrinsic_name) ;
156
+ }
157
+ let out_val = numeric_intrinsic ( intrinsic_name, bits, kind) ?;
155
158
self . write_scalar ( out_val, dest) ?;
156
159
}
157
- | " wrapping_add"
158
- | " wrapping_sub"
159
- | " wrapping_mul"
160
- | " add_with_overflow"
161
- | " sub_with_overflow"
162
- | " mul_with_overflow" => {
160
+ | sym :: wrapping_add
161
+ | sym :: wrapping_sub
162
+ | sym :: wrapping_mul
163
+ | sym :: add_with_overflow
164
+ | sym :: sub_with_overflow
165
+ | sym :: mul_with_overflow => {
163
166
let lhs = self . read_immediate ( args[ 0 ] ) ?;
164
167
let rhs = self . read_immediate ( args[ 1 ] ) ?;
165
168
let ( bin_op, ignore_overflow) = match intrinsic_name {
166
- " wrapping_add" => ( BinOp :: Add , true ) ,
167
- " wrapping_sub" => ( BinOp :: Sub , true ) ,
168
- " wrapping_mul" => ( BinOp :: Mul , true ) ,
169
- " add_with_overflow" => ( BinOp :: Add , false ) ,
170
- " sub_with_overflow" => ( BinOp :: Sub , false ) ,
171
- " mul_with_overflow" => ( BinOp :: Mul , false ) ,
169
+ sym :: wrapping_add => ( BinOp :: Add , true ) ,
170
+ sym :: wrapping_sub => ( BinOp :: Sub , true ) ,
171
+ sym :: wrapping_mul => ( BinOp :: Mul , true ) ,
172
+ sym :: add_with_overflow => ( BinOp :: Add , false ) ,
173
+ sym :: sub_with_overflow => ( BinOp :: Sub , false ) ,
174
+ sym :: mul_with_overflow => ( BinOp :: Mul , false ) ,
172
175
_ => bug ! ( "Already checked for int ops" )
173
176
} ;
174
177
if ignore_overflow {
@@ -177,10 +180,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
177
180
self . binop_with_overflow ( bin_op, lhs, rhs, dest) ?;
178
181
}
179
182
}
180
- " saturating_add" | " saturating_sub" => {
183
+ sym :: saturating_add | sym :: saturating_sub => {
181
184
let l = self . read_immediate ( args[ 0 ] ) ?;
182
185
let r = self . read_immediate ( args[ 1 ] ) ?;
183
- let is_add = intrinsic_name == " saturating_add" ;
186
+ let is_add = intrinsic_name == sym :: saturating_add;
184
187
let ( val, overflowed, _ty) = self . overflowing_binary_op ( if is_add {
185
188
BinOp :: Add
186
189
} else {
@@ -220,12 +223,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
220
223
} ;
221
224
self . write_scalar ( val, dest) ?;
222
225
}
223
- " unchecked_shl" | " unchecked_shr" => {
226
+ sym :: unchecked_shl | sym :: unchecked_shr => {
224
227
let l = self . read_immediate ( args[ 0 ] ) ?;
225
228
let r = self . read_immediate ( args[ 1 ] ) ?;
226
229
let bin_op = match intrinsic_name {
227
- " unchecked_shl" => BinOp :: Shl ,
228
- " unchecked_shr" => BinOp :: Shr ,
230
+ sym :: unchecked_shl => BinOp :: Shl ,
231
+ sym :: unchecked_shr => BinOp :: Shr ,
229
232
_ => bug ! ( "Already checked for int ops" )
230
233
} ;
231
234
let ( val, overflowed, _ty) = self . overflowing_binary_op ( bin_op, l, r) ?;
@@ -236,7 +239,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
236
239
}
237
240
self . write_scalar ( val, dest) ?;
238
241
}
239
- " rotate_left" | " rotate_right" => {
242
+ sym :: rotate_left | sym :: rotate_right => {
240
243
// rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW))
241
244
// rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
242
245
let layout = self . layout_of ( substs. type_at ( 0 ) ) ?;
@@ -247,7 +250,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
247
250
let width_bits = layout. size . bits ( ) as u128 ;
248
251
let shift_bits = raw_shift_bits % width_bits;
249
252
let inv_shift_bits = ( width_bits - shift_bits) % width_bits;
250
- let result_bits = if intrinsic_name == " rotate_left" {
253
+ let result_bits = if intrinsic_name == sym :: rotate_left {
251
254
( val_bits << shift_bits) | ( val_bits >> inv_shift_bits)
252
255
} else {
253
256
( val_bits >> shift_bits) | ( val_bits << inv_shift_bits)
@@ -257,7 +260,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
257
260
self . write_scalar ( result, dest) ?;
258
261
}
259
262
260
- " ptr_offset_from" => {
263
+ sym :: ptr_offset_from => {
261
264
let isize_layout = self . layout_of ( self . tcx . types . isize ) ?;
262
265
let a = self . read_immediate ( args[ 0 ] ) ?. to_scalar ( ) ?;
263
266
let b = self . read_immediate ( args[ 1 ] ) ?. to_scalar ( ) ?;
@@ -303,10 +306,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
303
306
}
304
307
}
305
308
306
- " transmute" => {
309
+ sym :: transmute => {
307
310
self . copy_op_transmute ( args[ 0 ] , dest) ?;
308
311
}
309
- " simd_insert" => {
312
+ sym :: simd_insert => {
310
313
let index = u64:: from ( self . read_scalar ( args[ 1 ] ) ?. to_u32 ( ) ?) ;
311
314
let elem = args[ 2 ] ;
312
315
let input = args[ 0 ] ;
@@ -337,7 +340,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
337
340
self . copy_op ( value, place) ?;
338
341
}
339
342
}
340
- " simd_extract" => {
343
+ sym :: simd_extract => {
341
344
let index = u64:: from ( self . read_scalar ( args[ 1 ] ) ?. to_u32 ( ) ?) ;
342
345
let ( len, e_ty) = args[ 0 ] . layout . ty . simd_size_and_type ( self . tcx . tcx ) ;
343
346
assert ! (
0 commit comments