@@ -9,8 +9,10 @@ use rustc::ty::layout::{LayoutOf, Primitive, Size};
9
9
use rustc:: ty:: subst:: SubstsRef ;
10
10
use rustc:: hir:: def_id:: DefId ;
11
11
use 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
+ } ;
14
16
15
17
use super :: {
16
18
Machine , PlaceTy , OpTy , InterpCx , ImmTy ,
@@ -91,16 +93,20 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
91
93
span : Span ,
92
94
instance : ty:: Instance < ' tcx > ,
93
95
args : & [ OpTy < ' tcx , M :: PointerTag > ] ,
94
- dest : Option < PlaceTy < ' tcx , M :: PointerTag > > ,
96
+ ret : Option < ( PlaceTy < ' tcx , M :: PointerTag > , mir :: BasicBlock ) > ,
95
97
) -> InterpResult < ' tcx , bool > {
96
98
let substs = instance. substs ;
99
+ let intrinsic_name = & * self . tcx . item_name ( instance. def_id ( ) ) . as_str ( ) ;
97
100
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
+ }
102
109
} ;
103
- let intrinsic_name = & * self . tcx . item_name ( instance. def_id ( ) ) . as_str ( ) ;
104
110
105
111
match intrinsic_name {
106
112
"caller_location" => {
@@ -268,34 +274,39 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
268
274
// exception from the exception.)
269
275
// This is the dual to the special exception for offset-by-0
270
276
// 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 ( ) {
272
281
let a = a. to_machine_usize ( self ) ?;
273
282
let b = b. to_machine_usize ( self ) ?;
274
283
if a == b && a != 0 {
275
284
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 } ;
279
288
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) ?;
288
309
}
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) ?;
299
310
}
300
311
301
312
"transmute" => {
@@ -350,6 +361,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
350
361
_ => return Ok ( false ) ,
351
362
}
352
363
364
+ self . dump_place ( * dest) ;
365
+ self . go_to_block ( ret) ;
353
366
Ok ( true )
354
367
}
355
368
@@ -360,7 +373,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
360
373
& mut self ,
361
374
instance : ty:: Instance < ' tcx > ,
362
375
args : & [ OpTy < ' tcx , M :: PointerTag > ] ,
363
- _dest : Option < PlaceTy < ' tcx , M :: PointerTag > > ,
376
+ _ret : Option < ( PlaceTy < ' tcx , M :: PointerTag > , mir :: BasicBlock ) > ,
364
377
) -> InterpResult < ' tcx , bool > {
365
378
let def_id = instance. def_id ( ) ;
366
379
if Some ( def_id) == self . tcx . lang_items ( ) . panic_fn ( ) {
0 commit comments