22//! looking at their MIR. Intrinsics/functions supported here are shared by CTFE
33//! and miri.
44
5- use syntax :: symbol:: Symbol ;
5+ use syntax_pos :: symbol:: { sym , Symbol } ;
66use syntax_pos:: Span ;
77use rustc:: ty;
88use rustc:: ty:: layout:: { LayoutOf , Primitive , Size } ;
@@ -22,7 +22,7 @@ mod caller_location;
2222mod type_name;
2323
2424fn numeric_intrinsic < ' tcx , Tag > (
25- name : & str ,
25+ name : Symbol ,
2626 bits : u128 ,
2727 kind : Primitive ,
2828) -> InterpResult < ' tcx , Scalar < Tag > > {
@@ -32,11 +32,11 @@ fn numeric_intrinsic<'tcx, Tag>(
3232 } ;
3333 let extra = 128 - size. bits ( ) as u128 ;
3434 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 ( ) ,
4040 _ => bug ! ( "not a numeric intrinsic: {}" , name) ,
4141 } ;
4242 Ok ( Scalar :: from_uint ( bits_out, size) )
@@ -51,9 +51,9 @@ crate fn eval_nullary_intrinsic<'tcx>(
5151 substs : SubstsRef < ' tcx > ,
5252) -> InterpResult < ' tcx , & ' tcx ty:: Const < ' tcx > > {
5353 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) ;
5555 Ok ( match name {
56- " type_name" => {
56+ sym :: type_name => {
5757 let alloc = type_name:: alloc_type_name ( tcx, tp_ty) ;
5858 tcx. mk_const ( ty:: Const {
5959 val : ty:: ConstKind :: Value ( ConstValue :: Slice {
@@ -64,20 +64,20 @@ crate fn eval_nullary_intrinsic<'tcx>(
6464 ty : tcx. mk_static_str ( ) ,
6565 } )
6666 } ,
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 => {
7171 let layout = tcx. layout_of ( param_env. and ( tp_ty) ) . map_err ( |e| err_inval ! ( Layout ( e) ) ) ?;
7272 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 ( ) ,
7676 _ => bug ! ( ) ,
7777 } ;
7878 ty:: Const :: from_usize ( tcx, n)
7979 } ,
80- " type_id" => ty:: Const :: from_bits (
80+ sym :: type_id => ty:: Const :: from_bits (
8181 tcx,
8282 tcx. type_id_hash ( tp_ty) . into ( ) ,
8383 param_env. and ( tcx. types . u64 ) ,
@@ -96,30 +96,32 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
9696 ret : Option < ( PlaceTy < ' tcx , M :: PointerTag > , mir:: BasicBlock ) > ,
9797 ) -> InterpResult < ' tcx , bool > {
9898 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 ( ) ) ;
100100
101101 // We currently do not handle any intrinsics that are *allowed* to diverge,
102102 // but `transmute` could lack a return place in case of UB.
103103 let ( dest, ret) = match ret {
104104 Some ( p) => p,
105105 None => match intrinsic_name {
106- " transmute" => throw_ub ! ( Unreachable ) ,
106+ sym :: transmute => throw_ub ! ( Unreachable ) ,
107107 _ => return Ok ( false ) ,
108108 }
109109 } ;
110110
111+ // Keep the patterns in this match ordered the same as the list in
112+ // `src/librustc/ty/constness.rs`
111113 match intrinsic_name {
112- " caller_location" => {
114+ sym :: caller_location => {
113115 let location = self . alloc_caller_location_for_span ( span) ;
114116 self . write_scalar ( location. ptr , dest) ?;
115117 }
116118
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 => {
123125 let gid = GlobalId {
124126 instance,
125127 promoted : None ,
@@ -129,13 +131,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
129131 self . copy_op ( val, dest) ?;
130132 }
131133
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 => {
139141 let ty = substs. type_at ( 0 ) ;
140142 let layout_of = self . layout_of ( ty) ?;
141143 let val = self . read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?;
@@ -144,31 +146,32 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
144146 ty:: layout:: Abi :: Scalar ( ref scalar) => scalar. value ,
145147 _ => throw_unsup ! ( TypeNotPrimitive ( ty) ) ,
146148 } ;
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) ,
154153 } ;
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) ?;
155158 self . write_scalar ( out_val, dest) ?;
156159 }
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 => {
163166 let lhs = self . read_immediate ( args[ 0 ] ) ?;
164167 let rhs = self . read_immediate ( args[ 1 ] ) ?;
165168 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 ) ,
172175 _ => bug ! ( "Already checked for int ops" )
173176 } ;
174177 if ignore_overflow {
@@ -177,10 +180,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
177180 self . binop_with_overflow ( bin_op, lhs, rhs, dest) ?;
178181 }
179182 }
180- " saturating_add" | " saturating_sub" => {
183+ sym :: saturating_add | sym :: saturating_sub => {
181184 let l = self . read_immediate ( args[ 0 ] ) ?;
182185 let r = self . read_immediate ( args[ 1 ] ) ?;
183- let is_add = intrinsic_name == " saturating_add" ;
186+ let is_add = intrinsic_name == sym :: saturating_add;
184187 let ( val, overflowed, _ty) = self . overflowing_binary_op ( if is_add {
185188 BinOp :: Add
186189 } else {
@@ -220,12 +223,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
220223 } ;
221224 self . write_scalar ( val, dest) ?;
222225 }
223- " unchecked_shl" | " unchecked_shr" => {
226+ sym :: unchecked_shl | sym :: unchecked_shr => {
224227 let l = self . read_immediate ( args[ 0 ] ) ?;
225228 let r = self . read_immediate ( args[ 1 ] ) ?;
226229 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 ,
229232 _ => bug ! ( "Already checked for int ops" )
230233 } ;
231234 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> {
236239 }
237240 self . write_scalar ( val, dest) ?;
238241 }
239- " rotate_left" | " rotate_right" => {
242+ sym :: rotate_left | sym :: rotate_right => {
240243 // rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW))
241244 // rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
242245 let layout = self . layout_of ( substs. type_at ( 0 ) ) ?;
@@ -247,7 +250,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
247250 let width_bits = layout. size . bits ( ) as u128 ;
248251 let shift_bits = raw_shift_bits % width_bits;
249252 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 {
251254 ( val_bits << shift_bits) | ( val_bits >> inv_shift_bits)
252255 } else {
253256 ( val_bits >> shift_bits) | ( val_bits << inv_shift_bits)
@@ -257,7 +260,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
257260 self . write_scalar ( result, dest) ?;
258261 }
259262
260- " ptr_offset_from" => {
263+ sym :: ptr_offset_from => {
261264 let isize_layout = self . layout_of ( self . tcx . types . isize ) ?;
262265 let a = self . read_immediate ( args[ 0 ] ) ?. to_scalar ( ) ?;
263266 let b = self . read_immediate ( args[ 1 ] ) ?. to_scalar ( ) ?;
@@ -303,10 +306,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
303306 }
304307 }
305308
306- " transmute" => {
309+ sym :: transmute => {
307310 self . copy_op_transmute ( args[ 0 ] , dest) ?;
308311 }
309- " simd_insert" => {
312+ sym :: simd_insert => {
310313 let index = u64:: from ( self . read_scalar ( args[ 1 ] ) ?. to_u32 ( ) ?) ;
311314 let elem = args[ 2 ] ;
312315 let input = args[ 0 ] ;
@@ -337,7 +340,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
337340 self . copy_op ( value, place) ?;
338341 }
339342 }
340- " simd_extract" => {
343+ sym :: simd_extract => {
341344 let index = u64:: from ( self . read_scalar ( args[ 1 ] ) ?. to_u32 ( ) ?) ;
342345 let ( len, e_ty) = args[ 0 ] . layout . ty . simd_size_and_type ( self . tcx . tcx ) ;
343346 assert ! (
0 commit comments