@@ -472,6 +472,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
472
472
& mut self ,
473
473
helper : TerminatorCodegenHelper < ' tcx > ,
474
474
bx : & mut Bx ,
475
+ source_info : & mir:: SourceInfo ,
475
476
location : mir:: Place < ' tcx > ,
476
477
target : mir:: BasicBlock ,
477
478
unwind : mir:: UnwindAction ,
@@ -495,84 +496,104 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
495
496
args1 = [ place. llval ] ;
496
497
& args1[ ..]
497
498
} ;
498
- let ( drop_fn, fn_abi) =
499
- match ty. kind ( ) {
500
- // FIXME(eddyb) perhaps move some of this logic into
501
- // `Instance::resolve_drop_in_place`?
502
- ty:: Dynamic ( _, _, ty:: Dyn ) => {
503
- // IN THIS ARM, WE HAVE:
504
- // ty = *mut (dyn Trait)
505
- // which is: exists<T> ( *mut T, Vtable<T: Trait> )
506
- // args[0] args[1]
507
- //
508
- // args = ( Data, Vtable )
509
- // |
510
- // v
511
- // /-------\
512
- // | ... |
513
- // \-------/
514
- //
515
- let virtual_drop = Instance {
516
- def : ty:: InstanceDef :: Virtual ( drop_fn. def_id ( ) , 0 ) ,
517
- args : drop_fn. args ,
518
- } ;
519
- debug ! ( "ty = {:?}" , ty) ;
520
- debug ! ( "drop_fn = {:?}" , drop_fn) ;
521
- debug ! ( "args = {:?}" , args) ;
522
- let fn_abi = bx. fn_abi_of_instance ( virtual_drop, ty:: List :: empty ( ) ) ;
523
- let vtable = args[ 1 ] ;
524
- // Truncate vtable off of args list
525
- args = & args[ ..1 ] ;
526
- (
527
- meth:: VirtualIndex :: from_index ( ty:: COMMON_VTABLE_ENTRIES_DROPINPLACE )
528
- . get_fn ( bx, vtable, ty, fn_abi) ,
529
- fn_abi,
530
- )
531
- }
532
- ty:: Dynamic ( _, _, ty:: DynStar ) => {
533
- // IN THIS ARM, WE HAVE:
534
- // ty = *mut (dyn* Trait)
535
- // which is: *mut exists<T: sizeof(T) == sizeof(usize)> (T, Vtable<T: Trait>)
536
- //
537
- // args = [ * ]
538
- // |
539
- // v
540
- // ( Data, Vtable )
541
- // |
542
- // v
543
- // /-------\
544
- // | ... |
545
- // \-------/
546
- //
547
- //
548
- // WE CAN CONVERT THIS INTO THE ABOVE LOGIC BY DOING
549
- //
550
- // data = &(*args[0]).0 // gives a pointer to Data above (really the same pointer)
551
- // vtable = (*args[0]).1 // loads the vtable out
552
- // (data, vtable) // an equivalent Rust `*mut dyn Trait`
553
- //
554
- // SO THEN WE CAN USE THE ABOVE CODE.
555
- let virtual_drop = Instance {
556
- def : ty:: InstanceDef :: Virtual ( drop_fn. def_id ( ) , 0 ) ,
557
- args : drop_fn. args ,
558
- } ;
559
- debug ! ( "ty = {:?}" , ty) ;
560
- debug ! ( "drop_fn = {:?}" , drop_fn) ;
561
- debug ! ( "args = {:?}" , args) ;
562
- let fn_abi = bx. fn_abi_of_instance ( virtual_drop, ty:: List :: empty ( ) ) ;
563
- let meta_ptr = place. project_field ( bx, 1 ) ;
564
- let meta = bx. load_operand ( meta_ptr) ;
565
- // Truncate vtable off of args list
566
- args = & args[ ..1 ] ;
567
- debug ! ( "args' = {:?}" , args) ;
568
- (
569
- meth:: VirtualIndex :: from_index ( ty:: COMMON_VTABLE_ENTRIES_DROPINPLACE )
570
- . get_fn ( bx, meta. immediate ( ) , ty, fn_abi) ,
571
- fn_abi,
572
- )
573
- }
574
- _ => ( bx. get_fn_addr ( drop_fn) , bx. fn_abi_of_instance ( drop_fn, ty:: List :: empty ( ) ) ) ,
575
- } ;
499
+ let ( maybe_null, drop_fn, fn_abi) = match ty. kind ( ) {
500
+ // FIXME(eddyb) perhaps move some of this logic into
501
+ // `Instance::resolve_drop_in_place`?
502
+ ty:: Dynamic ( _, _, ty:: Dyn ) => {
503
+ // IN THIS ARM, WE HAVE:
504
+ // ty = *mut (dyn Trait)
505
+ // which is: exists<T> ( *mut T, Vtable<T: Trait> )
506
+ // args[0] args[1]
507
+ //
508
+ // args = ( Data, Vtable )
509
+ // |
510
+ // v
511
+ // /-------\
512
+ // | ... |
513
+ // \-------/
514
+ //
515
+ let virtual_drop = Instance {
516
+ def : ty:: InstanceDef :: Virtual ( drop_fn. def_id ( ) , 0 ) ,
517
+ args : drop_fn. args ,
518
+ } ;
519
+ debug ! ( "ty = {:?}" , ty) ;
520
+ debug ! ( "drop_fn = {:?}" , drop_fn) ;
521
+ debug ! ( "args = {:?}" , args) ;
522
+ let fn_abi = bx. fn_abi_of_instance ( virtual_drop, ty:: List :: empty ( ) ) ;
523
+ let vtable = args[ 1 ] ;
524
+ // Truncate vtable off of args list
525
+ args = & args[ ..1 ] ;
526
+ (
527
+ true ,
528
+ meth:: VirtualIndex :: from_index ( ty:: COMMON_VTABLE_ENTRIES_DROPINPLACE )
529
+ . get_optional_fn ( bx, vtable, ty, fn_abi) ,
530
+ fn_abi,
531
+ )
532
+ }
533
+ ty:: Dynamic ( _, _, ty:: DynStar ) => {
534
+ // IN THIS ARM, WE HAVE:
535
+ // ty = *mut (dyn* Trait)
536
+ // which is: *mut exists<T: sizeof(T) == sizeof(usize)> (T, Vtable<T: Trait>)
537
+ //
538
+ // args = [ * ]
539
+ // |
540
+ // v
541
+ // ( Data, Vtable )
542
+ // |
543
+ // v
544
+ // /-------\
545
+ // | ... |
546
+ // \-------/
547
+ //
548
+ //
549
+ // WE CAN CONVERT THIS INTO THE ABOVE LOGIC BY DOING
550
+ //
551
+ // data = &(*args[0]).0 // gives a pointer to Data above (really the same pointer)
552
+ // vtable = (*args[0]).1 // loads the vtable out
553
+ // (data, vtable) // an equivalent Rust `*mut dyn Trait`
554
+ //
555
+ // SO THEN WE CAN USE THE ABOVE CODE.
556
+ let virtual_drop = Instance {
557
+ def : ty:: InstanceDef :: Virtual ( drop_fn. def_id ( ) , 0 ) ,
558
+ args : drop_fn. args ,
559
+ } ;
560
+ debug ! ( "ty = {:?}" , ty) ;
561
+ debug ! ( "drop_fn = {:?}" , drop_fn) ;
562
+ debug ! ( "args = {:?}" , args) ;
563
+ let fn_abi = bx. fn_abi_of_instance ( virtual_drop, ty:: List :: empty ( ) ) ;
564
+ let meta_ptr = place. project_field ( bx, 1 ) ;
565
+ let meta = bx. load_operand ( meta_ptr) ;
566
+ // Truncate vtable off of args list
567
+ args = & args[ ..1 ] ;
568
+ debug ! ( "args' = {:?}" , args) ;
569
+ (
570
+ true ,
571
+ meth:: VirtualIndex :: from_index ( ty:: COMMON_VTABLE_ENTRIES_DROPINPLACE )
572
+ . get_optional_fn ( bx, meta. immediate ( ) , ty, fn_abi) ,
573
+ fn_abi,
574
+ )
575
+ }
576
+ _ => {
577
+ ( false , bx. get_fn_addr ( drop_fn) , bx. fn_abi_of_instance ( drop_fn, ty:: List :: empty ( ) ) )
578
+ }
579
+ } ;
580
+
581
+ // We generate a null check for the drop_fn. This saves a bunch of relocations being
582
+ // generated for no-op drops.
583
+ if maybe_null {
584
+ let is_not_null = bx. append_sibling_block ( "is_not_null" ) ;
585
+ let llty = bx. fn_ptr_backend_type ( fn_abi) ;
586
+ let null = bx. const_null ( llty) ;
587
+ let non_null = bx. icmp (
588
+ base:: bin_op_to_icmp_predicate ( mir:: BinOp :: Ne . to_hir_binop ( ) , false ) ,
589
+ drop_fn,
590
+ null,
591
+ ) ;
592
+ bx. cond_br ( non_null, is_not_null, self . llbb ( target) ) ;
593
+ bx. switch_to_block ( is_not_null) ;
594
+ self . set_debug_loc ( bx, * source_info) ;
595
+ }
596
+
576
597
helper. do_call (
577
598
self ,
578
599
bx,
@@ -582,7 +603,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
582
603
Some ( ( ReturnDest :: Nothing , target) ) ,
583
604
unwind,
584
605
& [ ] ,
585
- mergeable_succ,
606
+ !maybe_null && mergeable_succ,
586
607
)
587
608
}
588
609
@@ -1305,9 +1326,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1305
1326
MergingSucc :: False
1306
1327
}
1307
1328
1308
- mir:: TerminatorKind :: Drop { place, target, unwind, replace : _ } => {
1309
- self . codegen_drop_terminator ( helper, bx, place, target, unwind, mergeable_succ ( ) )
1310
- }
1329
+ mir:: TerminatorKind :: Drop { place, target, unwind, replace : _ } => self
1330
+ . codegen_drop_terminator (
1331
+ helper,
1332
+ bx,
1333
+ & terminator. source_info ,
1334
+ place,
1335
+ target,
1336
+ unwind,
1337
+ mergeable_succ ( ) ,
1338
+ ) ,
1311
1339
1312
1340
mir:: TerminatorKind :: Assert { ref cond, expected, ref msg, target, unwind } => self
1313
1341
. codegen_assert_terminator (
0 commit comments