@@ -624,7 +624,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
624624 // \-------/
625625 //
626626 let virtual_drop = Instance {
627- def : ty:: InstanceKind :: Virtual ( drop_fn. def_id ( ) , 0 ) , // idx 0: the drop function
627+ def : ty:: InstanceKind :: Virtual (
628+ drop_fn. def_id ( ) ,
629+ ty:: COMMON_VTABLE_ENTRIES_DROPINPLACE ,
630+ ) ,
628631 args : drop_fn. args ,
629632 } ;
630633 debug ! ( "ty = {:?}" , ty) ;
@@ -678,6 +681,87 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
678681 )
679682 }
680683
684+ #[ tracing:: instrument( level = "trace" , skip( self , helper, bx) ) ]
685+ fn codegen_async_drop_dyn (
686+ & mut self ,
687+ helper : TerminatorCodegenHelper < ' tcx > ,
688+ bx : & mut Bx ,
689+ source_info : & mir:: SourceInfo ,
690+ dropee : mir:: Place < ' tcx > ,
691+ destination : mir:: Place < ' tcx > ,
692+ target : mir:: BasicBlock ,
693+ unwind : mir:: UnwindAction ,
694+ mergeable_succ : bool ,
695+ ) -> MergingSucc {
696+ let ty = dropee. ty ( self . mir , bx. tcx ( ) ) . ty ;
697+ let ty = self . monomorphize ( ty) ;
698+ let drop_fn = Instance :: resolve_async_drop_in_place_dyn ( bx. tcx ( ) , ty) . unwrap ( ) ;
699+ let place = self . codegen_place ( bx, dropee. as_ref ( ) ) ;
700+
701+ let ( args1, args2) ;
702+ let mut args = if let Some ( llextra) = place. val . llextra {
703+ args2 = [ place. val . llval , llextra] ;
704+ & args2[ ..]
705+ } else {
706+ args1 = [ place. val . llval ] ;
707+ & args1[ ..]
708+ } ;
709+
710+ let ( drop_fn, fn_abi, drop_instance) = match ty. kind ( ) {
711+ ty:: Dynamic ( _, _, ty:: Dyn ) => {
712+ let virtual_drop = Instance {
713+ def : ty:: InstanceKind :: Virtual (
714+ drop_fn. def_id ( ) ,
715+ ty:: COMMON_VTABLE_ENTRIES_ASYNCDROPINPLACE ,
716+ ) ,
717+ args : drop_fn. args ,
718+ } ;
719+ let fn_abi = bx. fn_abi_of_instance ( virtual_drop, ty:: List :: empty ( ) ) ;
720+ let vtable = args[ 1 ] ;
721+ // Truncate vtable off of args list
722+ args = & args[ ..1 ] ;
723+ (
724+ meth:: VirtualIndex :: from_index ( ty:: COMMON_VTABLE_ENTRIES_ASYNCDROPINPLACE )
725+ . get_optional_fn ( bx, vtable, ty, fn_abi) ,
726+ fn_abi,
727+ virtual_drop,
728+ )
729+ }
730+ _ => bug ! ( "Non-virtual call for async drop terminator (ty is not dyn or dyn*)" ) ,
731+ } ;
732+ // We generate a null check for the drop_fn. This saves a bunch of relocations being
733+ // generated for no-op drops.
734+ // FIXME: do we need it for dyn async drop?
735+ {
736+ let is_not_null = bx. append_sibling_block ( "is_not_null" ) ;
737+ let llty = bx. fn_ptr_backend_type ( fn_abi) ;
738+ let null = bx. const_null ( llty) ;
739+ let non_null =
740+ bx. icmp ( base:: bin_op_to_icmp_predicate ( mir:: BinOp :: Ne , false ) , drop_fn, null) ;
741+ bx. cond_br ( non_null, is_not_null, helper. llbb_with_cleanup ( self , target) ) ;
742+ bx. switch_to_block ( is_not_null) ;
743+ self . set_debug_loc ( bx, * source_info) ;
744+ }
745+ assert ! ( !fn_abi. ret. is_indirect( ) ) ;
746+ let mut llargs = Vec :: new ( ) ;
747+ let return_dest = self . make_return_dest ( bx, destination, & fn_abi. ret , & mut llargs) ;
748+ assert ! ( llargs. is_empty( ) ) ;
749+
750+ helper. do_call (
751+ self ,
752+ bx,
753+ fn_abi,
754+ drop_fn,
755+ args,
756+ Some ( ( return_dest, target) ) ,
757+ unwind,
758+ & [ ] ,
759+ Some ( drop_instance) ,
760+ CallKind :: Normal ,
761+ false ,
762+ )
763+ }
764+
681765 fn codegen_assert_terminator (
682766 & mut self ,
683767 helper : TerminatorCodegenHelper < ' tcx > ,
@@ -898,6 +982,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
898982
899983 let ( instance, mut llfn) = match * callee. layout . ty . kind ( ) {
900984 ty:: FnDef ( def_id, generic_args) => {
985+ if bx. tcx ( ) . is_lang_item ( def_id, LangItem :: AsyncDropInPlaceDyn ) {
986+ let mir:: Operand :: Move ( dropee) = args[ 0 ] . node else {
987+ bug ! ( ) ;
988+ } ;
989+ return self . codegen_async_drop_dyn (
990+ helper,
991+ bx,
992+ & terminator. source_info ,
993+ dropee,
994+ destination,
995+ target. unwrap ( ) ,
996+ unwind,
997+ mergeable_succ,
998+ ) ;
999+ }
9011000 let instance = ty:: Instance :: expect_resolve (
9021001 bx. tcx ( ) ,
9031002 bx. typing_env ( ) ,
0 commit comments