@@ -9,8 +9,10 @@ use rustc::ty::layout::{LayoutOf, Primitive, Size};
99use rustc:: ty:: subst:: SubstsRef ;
1010use rustc:: hir:: def_id:: DefId ;
1111use rustc:: ty:: TyCtxt ;
12- use rustc:: mir:: BinOp ;
13- use rustc:: mir:: interpret:: { InterpResult , Scalar , GlobalId , ConstValue } ;
12+ use rustc:: mir:: {
13+ self , BinOp ,
14+ interpret:: { InterpResult , Scalar , GlobalId , ConstValue }
15+ } ;
1416
1517use super :: {
1618 Machine , PlaceTy , OpTy , InterpCx , ImmTy ,
@@ -91,16 +93,20 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
9193 span : Span ,
9294 instance : ty:: Instance < ' tcx > ,
9395 args : & [ OpTy < ' tcx , M :: PointerTag > ] ,
94- dest : Option < PlaceTy < ' tcx , M :: PointerTag > > ,
96+ ret : Option < ( PlaceTy < ' tcx , M :: PointerTag > , mir :: BasicBlock ) > ,
9597 ) -> InterpResult < ' tcx , bool > {
9698 let substs = instance. substs ;
99+ let intrinsic_name = & * self . tcx . item_name ( instance. def_id ( ) ) . as_str ( ) ;
97100
98- // We currently do not handle any diverging intrinsics.
99- let dest = match dest {
100- Some ( dest) => dest,
101- None => return Ok ( false )
101+ // We currently do not handle any intrinsics that are *allowed* to diverge,
102+ // but `transmute` could lack a return place in case of UB.
103+ let ( dest, ret) = match ret {
104+ Some ( p) => p,
105+ None => match intrinsic_name {
106+ "transmute" => throw_ub ! ( Unreachable ) ,
107+ _ => return Ok ( false ) ,
108+ }
102109 } ;
103- let intrinsic_name = & * self . tcx . item_name ( instance. def_id ( ) ) . as_str ( ) ;
104110
105111 match intrinsic_name {
106112 "caller_location" => {
@@ -268,34 +274,39 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
268274 // exception from the exception.)
269275 // This is the dual to the special exception for offset-by-0
270276 // in the inbounds pointer offset operation (see the Miri code, `src/operator.rs`).
271- if a. is_bits ( ) && b. is_bits ( ) {
277+ //
278+ // Control flow is weird because we cannot early-return (to reach the
279+ // `go_to_block` at the end).
280+ let done = if a. is_bits ( ) && b. is_bits ( ) {
272281 let a = a. to_machine_usize ( self ) ?;
273282 let b = b. to_machine_usize ( self ) ?;
274283 if a == b && a != 0 {
275284 self . write_scalar ( Scalar :: from_int ( 0 , isize_layout. size ) , dest) ?;
276- return Ok ( true ) ;
277- }
278- }
285+ true
286+ } else { false }
287+ } else { false } ;
279288
280- // General case: we need two pointers.
281- let a = self . force_ptr ( a) ?;
282- let b = self . force_ptr ( b) ?;
283- if a. alloc_id != b. alloc_id {
284- throw_ub_format ! (
285- "ptr_offset_from cannot compute offset of pointers into different \
286- allocations.",
287- ) ;
289+ if !done {
290+ // General case: we need two pointers.
291+ let a = self . force_ptr ( a) ?;
292+ let b = self . force_ptr ( b) ?;
293+ if a. alloc_id != b. alloc_id {
294+ throw_ub_format ! (
295+ "ptr_offset_from cannot compute offset of pointers into different \
296+ allocations.",
297+ ) ;
298+ }
299+ let usize_layout = self . layout_of ( self . tcx . types . usize ) ?;
300+ let a_offset = ImmTy :: from_uint ( a. offset . bytes ( ) , usize_layout) ;
301+ let b_offset = ImmTy :: from_uint ( b. offset . bytes ( ) , usize_layout) ;
302+ let ( val, _overflowed, _ty) = self . overflowing_binary_op (
303+ BinOp :: Sub , a_offset, b_offset,
304+ ) ?;
305+ let pointee_layout = self . layout_of ( substs. type_at ( 0 ) ) ?;
306+ let val = ImmTy :: from_scalar ( val, isize_layout) ;
307+ let size = ImmTy :: from_int ( pointee_layout. size . bytes ( ) , isize_layout) ;
308+ self . exact_div ( val, size, dest) ?;
288309 }
289- let usize_layout = self . layout_of ( self . tcx . types . usize ) ?;
290- let a_offset = ImmTy :: from_uint ( a. offset . bytes ( ) , usize_layout) ;
291- let b_offset = ImmTy :: from_uint ( b. offset . bytes ( ) , usize_layout) ;
292- let ( val, _overflowed, _ty) = self . overflowing_binary_op (
293- BinOp :: Sub , a_offset, b_offset,
294- ) ?;
295- let pointee_layout = self . layout_of ( substs. type_at ( 0 ) ) ?;
296- let val = ImmTy :: from_scalar ( val, isize_layout) ;
297- let size = ImmTy :: from_int ( pointee_layout. size . bytes ( ) , isize_layout) ;
298- self . exact_div ( val, size, dest) ?;
299310 }
300311
301312 "transmute" => {
@@ -350,6 +361,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
350361 _ => return Ok ( false ) ,
351362 }
352363
364+ self . dump_place ( * dest) ;
365+ self . go_to_block ( ret) ;
353366 Ok ( true )
354367 }
355368
@@ -360,7 +373,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
360373 & mut self ,
361374 instance : ty:: Instance < ' tcx > ,
362375 args : & [ OpTy < ' tcx , M :: PointerTag > ] ,
363- _dest : Option < PlaceTy < ' tcx , M :: PointerTag > > ,
376+ _ret : Option < ( PlaceTy < ' tcx , M :: PointerTag > , mir :: BasicBlock ) > ,
364377 ) -> InterpResult < ' tcx , bool > {
365378 let def_id = instance. def_id ( ) ;
366379 if Some ( def_id) == self . tcx . lang_items ( ) . panic_fn ( ) {
0 commit comments