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