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