@@ -610,7 +610,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
610610 // \-------/
611611 //
612612 let virtual_drop = Instance {
613- def : ty:: InstanceKind :: Virtual ( drop_fn. def_id ( ) , 0 ) , // idx 0: the drop function
613+ def : ty:: InstanceKind :: Virtual (
614+ drop_fn. def_id ( ) ,
615+ ty:: COMMON_VTABLE_ENTRIES_DROPINPLACE ,
616+ ) ,
614617 args : drop_fn. args ,
615618 } ;
616619 debug ! ( "ty = {:?}" , ty) ;
@@ -652,7 +655,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
652655 //
653656 // SO THEN WE CAN USE THE ABOVE CODE.
654657 let virtual_drop = Instance {
655- def : ty:: InstanceKind :: Virtual ( drop_fn. def_id ( ) , 0 ) , // idx 0: the drop function
658+ def : ty:: InstanceKind :: Virtual (
659+ drop_fn. def_id ( ) ,
660+ ty:: COMMON_VTABLE_ENTRIES_DROPINPLACE ,
661+ ) ,
656662 args : drop_fn. args ,
657663 } ;
658664 debug ! ( "ty = {:?}" , ty) ;
@@ -707,6 +713,108 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
707713 )
708714 }
709715
716+ #[ tracing:: instrument( level = "trace" , skip( self , helper, bx) ) ]
717+ fn codegen_async_drop_dyn (
718+ & mut self ,
719+ helper : TerminatorCodegenHelper < ' tcx > ,
720+ bx : & mut Bx ,
721+ source_info : & mir:: SourceInfo ,
722+ dropee : mir:: Place < ' tcx > ,
723+ destination : mir:: Place < ' tcx > ,
724+ target : mir:: BasicBlock ,
725+ unwind : mir:: UnwindAction ,
726+ mergeable_succ : bool ,
727+ ) -> MergingSucc {
728+ let ty = dropee. ty ( self . mir , bx. tcx ( ) ) . ty ;
729+ let ty = self . monomorphize ( ty) ;
730+ let drop_fn = Instance :: resolve_async_drop_in_place_dyn ( bx. tcx ( ) , ty) . unwrap ( ) ;
731+ let place = self . codegen_place ( bx, dropee. as_ref ( ) ) ;
732+
733+ let ( args1, args2) ;
734+ let mut args = if let Some ( llextra) = place. val . llextra {
735+ args2 = [ place. val . llval , llextra] ;
736+ & args2[ ..]
737+ } else {
738+ args1 = [ place. val . llval ] ;
739+ & args1[ ..]
740+ } ;
741+
742+ let ( drop_fn, fn_abi, drop_instance) = match ty. kind ( ) {
743+ ty:: Dynamic ( _, _, ty:: Dyn ) => {
744+ let virtual_drop = Instance {
745+ def : ty:: InstanceKind :: Virtual (
746+ drop_fn. def_id ( ) ,
747+ ty:: COMMON_VTABLE_ENTRIES_ASYNCDROPINPLACE ,
748+ ) ,
749+ args : drop_fn. args ,
750+ } ;
751+ let fn_abi = bx. fn_abi_of_instance ( virtual_drop, ty:: List :: empty ( ) ) ;
752+ let vtable = args[ 1 ] ;
753+ // Truncate vtable off of args list
754+ args = & args[ ..1 ] ;
755+ (
756+ meth:: VirtualIndex :: from_index ( ty:: COMMON_VTABLE_ENTRIES_ASYNCDROPINPLACE )
757+ . get_optional_fn ( bx, vtable, ty, fn_abi) ,
758+ fn_abi,
759+ virtual_drop,
760+ )
761+ }
762+ ty:: Dynamic ( _, _, ty:: DynStar ) => {
763+ let virtual_drop = Instance {
764+ def : ty:: InstanceKind :: Virtual (
765+ drop_fn. def_id ( ) ,
766+ ty:: COMMON_VTABLE_ENTRIES_ASYNCDROPINPLACE ,
767+ ) ,
768+ args : drop_fn. args ,
769+ } ;
770+ let fn_abi = bx. fn_abi_of_instance ( virtual_drop, ty:: List :: empty ( ) ) ;
771+ let meta_ptr = place. project_field ( bx, 1 ) ;
772+ let meta = bx. load_operand ( meta_ptr) ;
773+ // Truncate vtable off of args list
774+ assert ! ( args. len( ) == 1 ) ;
775+ args = & args[ ..1 ] ;
776+ debug ! ( "args' = {:?}" , args) ;
777+ (
778+ meth:: VirtualIndex :: from_index ( ty:: COMMON_VTABLE_ENTRIES_ASYNCDROPINPLACE )
779+ . get_optional_fn ( bx, meta. immediate ( ) , ty, fn_abi) ,
780+ fn_abi,
781+ virtual_drop,
782+ )
783+ }
784+ _ => bug ! ( "Non-virtual call for async drop terminator (ty is not dyn or dyn*)" ) ,
785+ } ;
786+ // We generate a null check for the drop_fn. This saves a bunch of relocations being
787+ // generated for no-op drops.
788+ // FIXME: do we need it for dyn async drop?
789+ {
790+ let is_not_null = bx. append_sibling_block ( "is_not_null" ) ;
791+ let llty = bx. fn_ptr_backend_type ( fn_abi) ;
792+ let null = bx. const_null ( llty) ;
793+ let non_null =
794+ bx. icmp ( base:: bin_op_to_icmp_predicate ( mir:: BinOp :: Ne , false ) , drop_fn, null) ;
795+ bx. cond_br ( non_null, is_not_null, helper. llbb_with_cleanup ( self , target) ) ;
796+ bx. switch_to_block ( is_not_null) ;
797+ self . set_debug_loc ( bx, * source_info) ;
798+ }
799+ assert ! ( !fn_abi. ret. is_indirect( ) ) ;
800+ let mut llargs = Vec :: new ( ) ;
801+ let return_dest = self . make_return_dest ( bx, destination, & fn_abi. ret , & mut llargs) ;
802+ assert ! ( llargs. is_empty( ) ) ;
803+
804+ helper. do_call (
805+ self ,
806+ bx,
807+ fn_abi,
808+ drop_fn,
809+ args,
810+ Some ( ( return_dest, target) ) ,
811+ unwind,
812+ & [ ] ,
813+ Some ( drop_instance) ,
814+ false ,
815+ )
816+ }
817+
710818 fn codegen_assert_terminator (
711819 & mut self ,
712820 helper : TerminatorCodegenHelper < ' tcx > ,
@@ -907,6 +1015,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
9071015
9081016 let ( instance, mut llfn) = match * callee. layout . ty . kind ( ) {
9091017 ty:: FnDef ( def_id, generic_args) => {
1018+ if bx. tcx ( ) . is_lang_item ( def_id, LangItem :: AsyncDropInPlaceDyn ) {
1019+ let mir:: Operand :: Move ( dropee) = args[ 0 ] . node else {
1020+ bug ! ( ) ;
1021+ } ;
1022+ return self . codegen_async_drop_dyn (
1023+ helper,
1024+ bx,
1025+ & terminator. source_info ,
1026+ dropee,
1027+ destination,
1028+ target. unwrap ( ) ,
1029+ unwind,
1030+ mergeable_succ,
1031+ ) ;
1032+ }
9101033 let instance = ty:: Instance :: expect_resolve (
9111034 bx. tcx ( ) ,
9121035 bx. typing_env ( ) ,
0 commit comments