@@ -738,7 +738,7 @@ pub fn call(
738738 bindgen : & mut impl Bindgen ,
739739 async_ : bool ,
740740) {
741- Generator :: new ( resolve, variant, lift_lower, bindgen , async_) . call ( func ) ;
741+ Generator :: new ( resolve, bindgen ) . call ( func , variant, lift_lower, async_) ;
742742}
743743
744744pub fn lower_to_memory < B : Bindgen > (
@@ -748,14 +748,12 @@ pub fn lower_to_memory<B: Bindgen>(
748748 value : B :: Operand ,
749749 ty : & Type ,
750750) {
751- // TODO: refactor so we don't need to pass in a bunch of unused dummy parameters:
752- let mut generator = Generator :: new (
753- resolve,
754- AbiVariant :: GuestImport ,
755- LiftLower :: LowerArgsLiftResults ,
756- bindgen,
757- true ,
758- ) ;
751+ let mut generator = Generator :: new ( resolve, bindgen) ;
752+ // TODO: make this configurable? Right this this function is only called for
753+ // future/stream callbacks so it's appropriate to skip realloc here as it's
754+ // all "lower for wasm import", but this might get reused for something else
755+ // in the future.
756+ generator. realloc = Some ( Realloc :: None ) ;
759757 generator. stack . push ( value) ;
760758 generator. write_to_memory ( ty, address, Default :: default ( ) ) ;
761759}
@@ -766,14 +764,7 @@ pub fn lift_from_memory<B: Bindgen>(
766764 address : B :: Operand ,
767765 ty : & Type ,
768766) -> B :: Operand {
769- // TODO: refactor so we don't need to pass in a bunch of unused dummy parameters:
770- let mut generator = Generator :: new (
771- resolve,
772- AbiVariant :: GuestImport ,
773- LiftLower :: LowerArgsLiftResults ,
774- bindgen,
775- true ,
776- ) ;
767+ let mut generator = Generator :: new ( resolve, bindgen) ;
777768 generator. read_from_memory ( ty, address, Default :: default ( ) ) ;
778769 generator. stack . pop ( ) . unwrap ( )
779770}
@@ -784,16 +775,10 @@ pub fn lift_from_memory<B: Bindgen>(
784775/// This is only intended to be used in guest generators for exported
785776/// functions and will primarily generate `GuestDeallocate*` instructions,
786777/// plus others used as input to those instructions.
787- pub fn post_return ( resolve : & Resolve , func : & Function , bindgen : & mut impl Bindgen , async_ : bool ) {
788- Generator :: new (
789- resolve,
790- AbiVariant :: GuestExport ,
791- LiftLower :: LiftArgsLowerResults ,
792- bindgen,
793- async_,
794- )
795- . post_return ( func) ;
778+ pub fn post_return ( resolve : & Resolve , func : & Function , bindgen : & mut impl Bindgen ) {
779+ Generator :: new ( resolve, bindgen) . post_return ( func) ;
796780}
781+
797782/// Returns whether the `Function` specified needs a post-return function to
798783/// be generated in guest code.
799784///
@@ -846,47 +831,54 @@ fn needs_post_return(resolve: &Resolve, ty: &Type) -> bool {
846831 }
847832}
848833
834+ #[ derive( Copy , Clone ) ]
835+ pub enum Realloc {
836+ None ,
837+ Export ( & ' static str ) ,
838+ }
839+
849840struct Generator < ' a , B : Bindgen > {
850- variant : AbiVariant ,
851- lift_lower : LiftLower ,
852841 bindgen : & ' a mut B ,
853- async_ : bool ,
854842 resolve : & ' a Resolve ,
855843 operands : Vec < B :: Operand > ,
856844 results : Vec < B :: Operand > ,
857845 stack : Vec < B :: Operand > ,
858846 return_pointer : Option < B :: Operand > ,
847+ realloc : Option < Realloc > ,
859848}
860849
861850impl < ' a , B : Bindgen > Generator < ' a , B > {
862- fn new (
863- resolve : & ' a Resolve ,
864- variant : AbiVariant ,
865- lift_lower : LiftLower ,
866- bindgen : & ' a mut B ,
867- async_ : bool ,
868- ) -> Generator < ' a , B > {
851+ fn new ( resolve : & ' a Resolve , bindgen : & ' a mut B ) -> Generator < ' a , B > {
869852 Generator {
870853 resolve,
871- variant,
872- lift_lower,
873854 bindgen,
874- async_,
875855 operands : Vec :: new ( ) ,
876856 results : Vec :: new ( ) ,
877857 stack : Vec :: new ( ) ,
878858 return_pointer : None ,
859+ realloc : None ,
879860 }
880861 }
881862
882- fn call ( & mut self , func : & Function ) {
863+ fn call ( & mut self , func : & Function , variant : AbiVariant , lift_lower : LiftLower , async_ : bool ) {
883864 const MAX_FLAT_PARAMS : usize = 16 ;
884865
885- let sig = self . resolve . wasm_signature ( self . variant , func) ;
866+ let sig = self . resolve . wasm_signature ( variant, func) ;
867+
868+ // Lowering parameters calling a wasm import _or_ returning a result
869+ // from an async-lifted wasm export means we don't need to pass
870+ // ownership, but we pass ownership in all other cases.
871+ let realloc = match ( variant, lift_lower, async_) {
872+ ( AbiVariant :: GuestImport , LiftLower :: LowerArgsLiftResults , _)
873+ | ( AbiVariant :: GuestExport , LiftLower :: LiftArgsLowerResults , true ) => Realloc :: None ,
874+ _ => Realloc :: Export ( "cabi_realloc" ) ,
875+ } ;
876+ assert ! ( self . realloc. is_none( ) ) ;
886877
887- match self . lift_lower {
878+ match lift_lower {
888879 LiftLower :: LowerArgsLiftResults => {
889- if let ( AbiVariant :: GuestExport , true ) = ( self . variant , self . async_ ) {
880+ self . realloc = Some ( realloc) ;
881+ if let ( AbiVariant :: GuestExport , true ) = ( variant, async_) {
890882 unimplemented ! ( "host-side code generation for async lift/lower not supported" ) ;
891883 }
892884
@@ -902,7 +894,7 @@ impl<'a, B: Bindgen> Generator<'a, B> {
902894 self_. stack . push ( ptr) ;
903895 } ;
904896
905- if self . async_ {
897+ if async_ {
906898 let ElementInfo { size, align } = self
907899 . bindgen
908900 . sizes ( )
@@ -926,7 +918,7 @@ impl<'a, B: Bindgen> Generator<'a, B> {
926918 . bindgen
927919 . sizes ( )
928920 . record ( func. params . iter ( ) . map ( |t| & t. 1 ) ) ;
929- let ptr = match self . variant {
921+ let ptr = match variant {
930922 // When a wasm module calls an import it will provide
931923 // space that isn't explicitly deallocated.
932924 AbiVariant :: GuestImport => self . bindgen . return_pointer ( size, align) ,
@@ -949,8 +941,9 @@ impl<'a, B: Bindgen> Generator<'a, B> {
949941 lower_to_memory ( self , ptr) ;
950942 }
951943 }
944+ self . realloc = None ;
952945
953- if self . async_ {
946+ if async_ {
954947 let ElementInfo { size, align } =
955948 self . bindgen . sizes ( ) . record ( func. result . iter ( ) ) ;
956949 let ptr = self . bindgen . return_pointer ( size, align) ;
@@ -964,7 +957,7 @@ impl<'a, B: Bindgen> Generator<'a, B> {
964957 } else {
965958 // If necessary we may need to prepare a return pointer for
966959 // this ABI.
967- if self . variant == AbiVariant :: GuestImport && sig. retptr {
960+ if variant == AbiVariant :: GuestImport && sig. retptr {
968961 let info = self . bindgen . sizes ( ) . params ( & func. result ) ;
969962 let ptr = self . bindgen . return_pointer ( info. size , info. align ) ;
970963 self . return_pointer = Some ( ptr. clone ( ) ) ;
@@ -978,22 +971,22 @@ impl<'a, B: Bindgen> Generator<'a, B> {
978971 } ) ;
979972 }
980973
981- if !( sig. retptr || self . async_ ) {
974+ if !( sig. retptr || async_) {
982975 // With no return pointer in use we can simply lift the
983976 // result(s) of the function from the result of the core
984977 // wasm function.
985978 if let Some ( ty) = & func. result {
986979 self . lift ( ty)
987980 }
988981 } else {
989- let ptr = match self . variant {
982+ let ptr = match variant {
990983 // imports into guests means it's a wasm module
991984 // calling an imported function. We supplied the
992985 // return pointer as the last argument (saved in
993986 // `self.return_pointer`) so we use that to read
994987 // the result of the function from memory.
995988 AbiVariant :: GuestImport => {
996- assert ! ( sig. results. is_empty( ) || self . async_) ;
989+ assert ! ( sig. results. is_empty( ) || async_) ;
997990 self . return_pointer . take ( ) . unwrap ( )
998991 }
999992
@@ -1025,7 +1018,7 @@ impl<'a, B: Bindgen> Generator<'a, B> {
10251018 } ) ;
10261019 }
10271020 LiftLower :: LiftArgsLowerResults => {
1028- if let ( AbiVariant :: GuestImport , true ) = ( self . variant , self . async_ ) {
1021+ if let ( AbiVariant :: GuestImport , true ) = ( variant, async_) {
10291022 todo ! ( "implement host-side support for async lift/lower" ) ;
10301023 }
10311024
@@ -1065,10 +1058,10 @@ impl<'a, B: Bindgen> Generator<'a, B> {
10651058 // ... and that allows us to call the interface types function
10661059 self . emit ( & Instruction :: CallInterface {
10671060 func,
1068- async_ : self . async_ ,
1061+ async_ : async_,
10691062 } ) ;
10701063
1071- let ( lower_to_memory, async_results) = if self . async_ {
1064+ let ( lower_to_memory, async_results) = if async_ {
10721065 self . emit ( & Instruction :: AsyncPostCallInterface { func } ) ;
10731066
10741067 let mut results = Vec :: new ( ) ;
@@ -1083,8 +1076,8 @@ impl<'a, B: Bindgen> Generator<'a, B> {
10831076 // This was dynamically allocated by the caller (or async start
10841077 // function) so after it's been read by the guest we need to
10851078 // deallocate it.
1086- if let AbiVariant :: GuestExport = self . variant {
1087- if sig. indirect_params && !self . async_ {
1079+ if let AbiVariant :: GuestExport = variant {
1080+ if sig. indirect_params && !async_ {
10881081 let ElementInfo { size, align } = self
10891082 . bindgen
10901083 . sizes ( )
@@ -1094,14 +1087,16 @@ impl<'a, B: Bindgen> Generator<'a, B> {
10941087 }
10951088 }
10961089
1090+ self . realloc = Some ( realloc) ;
1091+
10971092 if !lower_to_memory {
10981093 // With no return pointer in use we simply lower the
10991094 // result(s) and return that directly from the function.
11001095 if let Some ( ty) = & func. result {
11011096 self . lower ( ty) ;
11021097 }
11031098 } else {
1104- match self . variant {
1099+ match variant {
11051100 // When a function is imported to a guest this means
11061101 // it's a host providing the implementation of the
11071102 // import. The result is stored in the pointer
@@ -1159,9 +1154,12 @@ impl<'a, B: Bindgen> Generator<'a, B> {
11591154 amt : sig. results . len ( ) ,
11601155 } ) ;
11611156 }
1157+ self . realloc = None ;
11621158 }
11631159 }
11641160
1161+ assert ! ( self . realloc. is_none( ) ) ;
1162+
11651163 assert ! (
11661164 self . stack. is_empty( ) ,
11671165 "stack has {} items remaining" ,
@@ -1170,7 +1168,7 @@ impl<'a, B: Bindgen> Generator<'a, B> {
11701168 }
11711169
11721170 fn post_return ( & mut self , func : & Function ) {
1173- let sig = self . resolve . wasm_signature ( self . variant , func) ;
1171+ let sig = self . resolve . wasm_signature ( AbiVariant :: GuestExport , func) ;
11741172
11751173 // Currently post-return is only used for lists and lists are always
11761174 // returned indirectly through memory due to their flat representation
@@ -1424,13 +1422,9 @@ impl<'a, B: Bindgen> Generator<'a, B> {
14241422 }
14251423
14261424 fn list_realloc ( & self ) -> Option < & ' static str > {
1427- // Lowering parameters calling a wasm import _or_ returning a result
1428- // from an async-lifted wasm export means we don't need to pass
1429- // ownership, but we pass ownership in all other cases.
1430- match ( self . variant , self . lift_lower , self . async_ ) {
1431- ( AbiVariant :: GuestImport , LiftLower :: LowerArgsLiftResults , _)
1432- | ( AbiVariant :: GuestExport , LiftLower :: LiftArgsLowerResults , true ) => None ,
1433- _ => Some ( "cabi_realloc" ) ,
1425+ match self . realloc . expect ( "realloc should be configured" ) {
1426+ Realloc :: None => None ,
1427+ Realloc :: Export ( s) => Some ( s) ,
14341428 }
14351429 }
14361430
0 commit comments