@@ -499,6 +499,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
499
499
& mut self ,
500
500
helper : TerminatorCodegenHelper < ' tcx > ,
501
501
bx : & mut Bx ,
502
+ source_info : & mir:: SourceInfo ,
502
503
location : mir:: Place < ' tcx > ,
503
504
target : mir:: BasicBlock ,
504
505
unwind : mir:: UnwindAction ,
@@ -522,90 +523,109 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
522
523
args1 = [ place. val . llval ] ;
523
524
& args1[ ..]
524
525
} ;
525
- let ( drop_fn, fn_abi, drop_instance) =
526
- match ty. kind ( ) {
527
- // FIXME(eddyb) perhaps move some of this logic into
528
- // `Instance::resolve_drop_in_place`?
529
- ty:: Dynamic ( _, _, ty:: Dyn ) => {
530
- // IN THIS ARM, WE HAVE:
531
- // ty = *mut (dyn Trait)
532
- // which is: exists<T> ( *mut T, Vtable<T: Trait> )
533
- // args[0] args[1]
534
- //
535
- // args = ( Data, Vtable )
536
- // |
537
- // v
538
- // /-------\
539
- // | ... |
540
- // \-------/
541
- //
542
- let virtual_drop = Instance {
543
- def : ty:: InstanceDef :: Virtual ( drop_fn. def_id ( ) , 0 ) , // idx 0: the drop function
544
- args : drop_fn. args ,
545
- } ;
546
- debug ! ( "ty = {:?}" , ty) ;
547
- debug ! ( "drop_fn = {:?}" , drop_fn) ;
548
- debug ! ( "args = {:?}" , args) ;
549
- let fn_abi = bx. fn_abi_of_instance ( virtual_drop, ty:: List :: empty ( ) ) ;
550
- let vtable = args[ 1 ] ;
551
- // Truncate vtable off of args list
552
- args = & args[ ..1 ] ;
553
- (
554
- meth:: VirtualIndex :: from_index ( ty:: COMMON_VTABLE_ENTRIES_DROPINPLACE )
555
- . get_fn ( bx, vtable, ty, fn_abi) ,
556
- fn_abi,
557
- virtual_drop,
558
- )
559
- }
560
- ty:: Dynamic ( _, _, ty:: DynStar ) => {
561
- // IN THIS ARM, WE HAVE:
562
- // ty = *mut (dyn* Trait)
563
- // which is: *mut exists<T: sizeof(T) == sizeof(usize)> (T, Vtable<T: Trait>)
564
- //
565
- // args = [ * ]
566
- // |
567
- // v
568
- // ( Data, Vtable )
569
- // |
570
- // v
571
- // /-------\
572
- // | ... |
573
- // \-------/
574
- //
575
- //
576
- // WE CAN CONVERT THIS INTO THE ABOVE LOGIC BY DOING
577
- //
578
- // data = &(*args[0]).0 // gives a pointer to Data above (really the same pointer)
579
- // vtable = (*args[0]).1 // loads the vtable out
580
- // (data, vtable) // an equivalent Rust `*mut dyn Trait`
581
- //
582
- // SO THEN WE CAN USE THE ABOVE CODE.
583
- let virtual_drop = Instance {
584
- def : ty:: InstanceDef :: Virtual ( drop_fn. def_id ( ) , 0 ) , // idx 0: the drop function
585
- args : drop_fn. args ,
586
- } ;
587
- debug ! ( "ty = {:?}" , ty) ;
588
- debug ! ( "drop_fn = {:?}" , drop_fn) ;
589
- debug ! ( "args = {:?}" , args) ;
590
- let fn_abi = bx. fn_abi_of_instance ( virtual_drop, ty:: List :: empty ( ) ) ;
591
- let meta_ptr = place. project_field ( bx, 1 ) ;
592
- let meta = bx. load_operand ( meta_ptr) ;
593
- // Truncate vtable off of args list
594
- args = & args[ ..1 ] ;
595
- debug ! ( "args' = {:?}" , args) ;
596
- (
597
- meth:: VirtualIndex :: from_index ( ty:: COMMON_VTABLE_ENTRIES_DROPINPLACE )
598
- . get_fn ( bx, meta. immediate ( ) , ty, fn_abi) ,
599
- fn_abi,
600
- virtual_drop,
601
- )
602
- }
603
- _ => (
604
- bx. get_fn_addr ( drop_fn) ,
605
- bx. fn_abi_of_instance ( drop_fn, ty:: List :: empty ( ) ) ,
606
- drop_fn,
607
- ) ,
608
- } ;
526
+ let ( maybe_null, drop_fn, fn_abi, drop_instance) = match ty. kind ( ) {
527
+ // FIXME(eddyb) perhaps move some of this logic into
528
+ // `Instance::resolve_drop_in_place`?
529
+ ty:: Dynamic ( _, _, ty:: Dyn ) => {
530
+ // IN THIS ARM, WE HAVE:
531
+ // ty = *mut (dyn Trait)
532
+ // which is: exists<T> ( *mut T, Vtable<T: Trait> )
533
+ // args[0] args[1]
534
+ //
535
+ // args = ( Data, Vtable )
536
+ // |
537
+ // v
538
+ // /-------\
539
+ // | ... |
540
+ // \-------/
541
+ //
542
+ let virtual_drop = Instance {
543
+ def : ty:: InstanceDef :: Virtual ( drop_fn. def_id ( ) , 0 ) , // idx 0: the drop function
544
+ args : drop_fn. args ,
545
+ } ;
546
+ debug ! ( "ty = {:?}" , ty) ;
547
+ debug ! ( "drop_fn = {:?}" , drop_fn) ;
548
+ debug ! ( "args = {:?}" , args) ;
549
+ let fn_abi = bx. fn_abi_of_instance ( virtual_drop, ty:: List :: empty ( ) ) ;
550
+ let vtable = args[ 1 ] ;
551
+ // Truncate vtable off of args list
552
+ args = & args[ ..1 ] ;
553
+ (
554
+ true ,
555
+ meth:: VirtualIndex :: from_index ( ty:: COMMON_VTABLE_ENTRIES_DROPINPLACE )
556
+ . get_optional_fn ( bx, vtable, ty, fn_abi) ,
557
+ fn_abi,
558
+ virtual_drop,
559
+ )
560
+ }
561
+ ty:: Dynamic ( _, _, ty:: DynStar ) => {
562
+ // IN THIS ARM, WE HAVE:
563
+ // ty = *mut (dyn* Trait)
564
+ // which is: *mut exists<T: sizeof(T) == sizeof(usize)> (T, Vtable<T: Trait>)
565
+ //
566
+ // args = [ * ]
567
+ // |
568
+ // v
569
+ // ( Data, Vtable )
570
+ // |
571
+ // v
572
+ // /-------\
573
+ // | ... |
574
+ // \-------/
575
+ //
576
+ //
577
+ // WE CAN CONVERT THIS INTO THE ABOVE LOGIC BY DOING
578
+ //
579
+ // data = &(*args[0]).0 // gives a pointer to Data above (really the same pointer)
580
+ // vtable = (*args[0]).1 // loads the vtable out
581
+ // (data, vtable) // an equivalent Rust `*mut dyn Trait`
582
+ //
583
+ // SO THEN WE CAN USE THE ABOVE CODE.
584
+ let virtual_drop = Instance {
585
+ def : ty:: InstanceDef :: Virtual ( drop_fn. def_id ( ) , 0 ) , // idx 0: the drop function
586
+ args : drop_fn. args ,
587
+ } ;
588
+ debug ! ( "ty = {:?}" , ty) ;
589
+ debug ! ( "drop_fn = {:?}" , drop_fn) ;
590
+ debug ! ( "args = {:?}" , args) ;
591
+ let fn_abi = bx. fn_abi_of_instance ( virtual_drop, ty:: List :: empty ( ) ) ;
592
+ let meta_ptr = place. project_field ( bx, 1 ) ;
593
+ let meta = bx. load_operand ( meta_ptr) ;
594
+ // Truncate vtable off of args list
595
+ args = & args[ ..1 ] ;
596
+ debug ! ( "args' = {:?}" , args) ;
597
+ (
598
+ true ,
599
+ meth:: VirtualIndex :: from_index ( ty:: COMMON_VTABLE_ENTRIES_DROPINPLACE )
600
+ . get_optional_fn ( bx, meta. immediate ( ) , ty, fn_abi) ,
601
+ fn_abi,
602
+ virtual_drop,
603
+ )
604
+ }
605
+ _ => (
606
+ false ,
607
+ bx. get_fn_addr ( drop_fn) ,
608
+ bx. fn_abi_of_instance ( drop_fn, ty:: List :: empty ( ) ) ,
609
+ drop_fn,
610
+ ) ,
611
+ } ;
612
+
613
+ // We generate a null check for the drop_fn. This saves a bunch of relocations being
614
+ // generated for no-op drops.
615
+ if maybe_null {
616
+ let is_not_null = bx. append_sibling_block ( "is_not_null" ) ;
617
+ let llty = bx. fn_ptr_backend_type ( fn_abi) ;
618
+ let null = bx. const_null ( llty) ;
619
+ let non_null = bx. icmp (
620
+ base:: bin_op_to_icmp_predicate ( mir:: BinOp :: Ne . to_hir_binop ( ) , false ) ,
621
+ drop_fn,
622
+ null,
623
+ ) ;
624
+ bx. cond_br ( non_null, is_not_null, self . llbb ( target) ) ;
625
+ bx. switch_to_block ( is_not_null) ;
626
+ self . set_debug_loc ( bx, * source_info) ;
627
+ }
628
+
609
629
helper. do_call (
610
630
self ,
611
631
bx,
@@ -616,7 +636,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
616
636
unwind,
617
637
& [ ] ,
618
638
Some ( drop_instance) ,
619
- mergeable_succ,
639
+ !maybe_null && mergeable_succ,
620
640
)
621
641
}
622
642
@@ -1345,9 +1365,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1345
1365
MergingSucc :: False
1346
1366
}
1347
1367
1348
- mir:: TerminatorKind :: Drop { place, target, unwind, replace : _ } => {
1349
- self . codegen_drop_terminator ( helper, bx, place, target, unwind, mergeable_succ ( ) )
1350
- }
1368
+ mir:: TerminatorKind :: Drop { place, target, unwind, replace : _ } => self
1369
+ . codegen_drop_terminator (
1370
+ helper,
1371
+ bx,
1372
+ & terminator. source_info ,
1373
+ place,
1374
+ target,
1375
+ unwind,
1376
+ mergeable_succ ( ) ,
1377
+ ) ,
1351
1378
1352
1379
mir:: TerminatorKind :: Assert { ref cond, expected, ref msg, target, unwind } => self
1353
1380
. codegen_assert_terminator (
0 commit comments