@@ -5,21 +5,22 @@ use rustc::hir;
55use rustc:: mir:: interpret:: ConstEvalErr ;
66use rustc:: mir;
77use rustc:: ty:: { self , TyCtxt , Instance } ;
8- use rustc:: ty:: layout:: { LayoutOf , Primitive , TyLayout } ;
8+ use rustc:: ty:: layout:: { LayoutOf , Primitive , TyLayout , Size } ;
99use rustc:: ty:: subst:: Subst ;
1010use rustc_data_structures:: indexed_vec:: { IndexVec , Idx } ;
1111
1212use syntax:: ast:: Mutability ;
1313use syntax:: source_map:: Span ;
1414use syntax:: source_map:: DUMMY_SP ;
15+ use syntax:: symbol:: Symbol ;
1516
1617use rustc:: mir:: interpret:: {
1718 EvalResult , EvalError , EvalErrorKind , GlobalId ,
1819 Scalar , AllocId , Allocation , ConstValue ,
1920} ;
2021use super :: {
2122 Place , PlaceExtra , PlaceTy , MemPlace , OpTy , Operand , Value ,
22- EvalContext , StackPopCleanup , Memory , MemoryKind
23+ EvalContext , StackPopCleanup , Memory , MemoryKind , MPlaceTy ,
2324} ;
2425
2526pub fn mk_borrowck_eval_cx < ' a , ' mir , ' tcx > (
@@ -237,23 +238,56 @@ impl<'mir, 'tcx> super::Machine<'mir, 'tcx> for CompileTimeEvaluator {
237238 if !ecx. tcx . is_const_fn ( instance. def_id ( ) ) {
238239 let def_id = instance. def_id ( ) ;
239240 // Some fn calls are actually BinOp intrinsics
240- let ( op, oflo) = if let Some ( op) = ecx. tcx . is_binop_lang_item ( def_id) {
241- op
241+ let _: ! = if let Some ( ( op, oflo) ) = ecx. tcx . is_binop_lang_item ( def_id) {
242+ let ( dest, bb) = destination. expect ( "128 lowerings can't diverge" ) ;
243+ let l = ecx. read_value ( args[ 0 ] ) ?;
244+ let r = ecx. read_value ( args[ 1 ] ) ?;
245+ if oflo {
246+ ecx. binop_with_overflow ( op, l, r, dest) ?;
247+ } else {
248+ ecx. binop_ignore_overflow ( op, l, r, dest) ?;
249+ }
250+ ecx. goto_block ( bb) ;
251+ return Ok ( true ) ;
252+ } else if Some ( def_id) == ecx. tcx . lang_items ( ) . panic_fn ( ) {
253+ assert ! ( args. len( ) == 1 ) ;
254+ // &(&'static str, &'static str, u32, u32)
255+ let ptr = ecx. read_value ( args[ 0 ] ) ?;
256+ let place = ecx. ref_to_mplace ( ptr) ?;
257+ let ( msg, file, line, col) = (
258+ place_field ( ecx, 0 , place) ?,
259+ place_field ( ecx, 1 , place) ?,
260+ place_field ( ecx, 2 , place) ?,
261+ place_field ( ecx, 3 , place) ?,
262+ ) ;
263+
264+ let msg = to_str ( ecx, msg) ?;
265+ let file = to_str ( ecx, file) ?;
266+ let line = to_u32 ( line) ?;
267+ let col = to_u32 ( col) ?;
268+ return Err ( EvalErrorKind :: Panic { msg, file, line, col } . into ( ) ) ;
269+ } else if Some ( def_id) == ecx. tcx . lang_items ( ) . begin_panic_fn ( ) {
270+ assert ! ( args. len( ) == 2 ) ;
271+ // &'static str, &(&'static str, u32, u32)
272+ let msg = ecx. read_value ( args[ 0 ] ) ?;
273+ let ptr = ecx. read_value ( args[ 1 ] ) ?;
274+ let place = ecx. ref_to_mplace ( ptr) ?;
275+ let ( file, line, col) = (
276+ place_field ( ecx, 0 , place) ?,
277+ place_field ( ecx, 1 , place) ?,
278+ place_field ( ecx, 2 , place) ?,
279+ ) ;
280+
281+ let msg = to_str ( ecx, msg. value ) ?;
282+ let file = to_str ( ecx, file) ?;
283+ let line = to_u32 ( line) ?;
284+ let col = to_u32 ( col) ?;
285+ return Err ( EvalErrorKind :: Panic { msg, file, line, col } . into ( ) ) ;
242286 } else {
243287 return Err (
244288 ConstEvalError :: NotConst ( format ! ( "calling non-const fn `{}`" , instance) ) . into ( ) ,
245289 ) ;
246290 } ;
247- let ( dest, bb) = destination. expect ( "128 lowerings can't diverge" ) ;
248- let l = ecx. read_value ( args[ 0 ] ) ?;
249- let r = ecx. read_value ( args[ 1 ] ) ?;
250- if oflo {
251- ecx. binop_with_overflow ( op, l, r, dest) ?;
252- } else {
253- ecx. binop_ignore_overflow ( op, l, r, dest) ?;
254- }
255- ecx. goto_block ( bb) ;
256- return Ok ( true ) ;
257291 }
258292 let mir = match ecx. load_mir ( instance. def ) {
259293 Ok ( mir) => mir,
@@ -412,6 +446,39 @@ impl<'mir, 'tcx> super::Machine<'mir, 'tcx> for CompileTimeEvaluator {
412446 }
413447}
414448
449+ fn place_field < ' a , ' tcx , ' mir > (
450+ ecx : & mut EvalContext < ' a , ' mir , ' tcx , CompileTimeEvaluator > ,
451+ i : u64 ,
452+ place : MPlaceTy < ' tcx > ,
453+ ) -> EvalResult < ' tcx , Value > {
454+ let place = ecx. mplace_field ( place, i) ?;
455+ Ok ( ecx. try_read_value_from_mplace ( place) ?. expect ( "bad panic arg layout" ) )
456+ }
457+
458+ fn to_str < ' a , ' tcx , ' mir > (
459+ ecx : & mut EvalContext < ' a , ' mir , ' tcx , CompileTimeEvaluator > ,
460+ val : Value ,
461+ ) -> EvalResult < ' tcx , Symbol > {
462+ if let Value :: ScalarPair ( ptr, len) = val {
463+ let len = len. not_undef ( ) ?. to_bits ( ecx. memory . pointer_size ( ) ) ?;
464+ let bytes = ecx. memory . read_bytes ( ptr. not_undef ( ) ?, Size :: from_bytes ( len as u64 ) ) ?;
465+ let str = :: std:: str:: from_utf8 ( bytes) . map_err ( |err| EvalErrorKind :: ValidationFailure ( err. to_string ( ) ) ) ?;
466+ Ok ( Symbol :: intern ( str) )
467+ } else {
468+ bug ! ( "panic arg is not a str" )
469+ }
470+ }
471+
472+ fn to_u32 < ' a , ' tcx , ' mir > (
473+ val : Value ,
474+ ) -> EvalResult < ' tcx , u32 > {
475+ if let Value :: Scalar ( n) = val {
476+ Ok ( n. not_undef ( ) ?. to_bits ( Size :: from_bits ( 32 ) ) ? as u32 )
477+ } else {
478+ bug ! ( "panic arg is not a str" )
479+ }
480+ }
481+
415482/// Project to a field of a (variant of a) const
416483pub fn const_field < ' a , ' tcx > (
417484 tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
0 commit comments