@@ -738,7 +738,7 @@ pub fn call(
738
738
bindgen : & mut impl Bindgen ,
739
739
async_ : bool ,
740
740
) {
741
- Generator :: new ( resolve, variant, lift_lower, bindgen , async_) . call ( func ) ;
741
+ Generator :: new ( resolve, bindgen ) . call ( func , variant, lift_lower, async_) ;
742
742
}
743
743
744
744
pub fn lower_to_memory < B : Bindgen > (
@@ -748,14 +748,12 @@ pub fn lower_to_memory<B: Bindgen>(
748
748
value : B :: Operand ,
749
749
ty : & Type ,
750
750
) {
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 ) ;
759
757
generator. stack . push ( value) ;
760
758
generator. write_to_memory ( ty, address, Default :: default ( ) ) ;
761
759
}
@@ -766,14 +764,7 @@ pub fn lift_from_memory<B: Bindgen>(
766
764
address : B :: Operand ,
767
765
ty : & Type ,
768
766
) -> 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) ;
777
768
generator. read_from_memory ( ty, address, Default :: default ( ) ) ;
778
769
generator. stack . pop ( ) . unwrap ( )
779
770
}
@@ -784,16 +775,10 @@ pub fn lift_from_memory<B: Bindgen>(
784
775
/// This is only intended to be used in guest generators for exported
785
776
/// functions and will primarily generate `GuestDeallocate*` instructions,
786
777
/// 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) ;
796
780
}
781
+
797
782
/// Returns whether the `Function` specified needs a post-return function to
798
783
/// be generated in guest code.
799
784
///
@@ -846,47 +831,54 @@ fn needs_post_return(resolve: &Resolve, ty: &Type) -> bool {
846
831
}
847
832
}
848
833
834
+ #[ derive( Copy , Clone ) ]
835
+ pub enum Realloc {
836
+ None ,
837
+ Export ( & ' static str ) ,
838
+ }
839
+
849
840
struct Generator < ' a , B : Bindgen > {
850
- variant : AbiVariant ,
851
- lift_lower : LiftLower ,
852
841
bindgen : & ' a mut B ,
853
- async_ : bool ,
854
842
resolve : & ' a Resolve ,
855
843
operands : Vec < B :: Operand > ,
856
844
results : Vec < B :: Operand > ,
857
845
stack : Vec < B :: Operand > ,
858
846
return_pointer : Option < B :: Operand > ,
847
+ realloc : Option < Realloc > ,
859
848
}
860
849
861
850
impl < ' 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 > {
869
852
Generator {
870
853
resolve,
871
- variant,
872
- lift_lower,
873
854
bindgen,
874
- async_,
875
855
operands : Vec :: new ( ) ,
876
856
results : Vec :: new ( ) ,
877
857
stack : Vec :: new ( ) ,
878
858
return_pointer : None ,
859
+ realloc : None ,
879
860
}
880
861
}
881
862
882
- fn call ( & mut self , func : & Function ) {
863
+ fn call ( & mut self , func : & Function , variant : AbiVariant , lift_lower : LiftLower , async_ : bool ) {
883
864
const MAX_FLAT_PARAMS : usize = 16 ;
884
865
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( ) ) ;
886
877
887
- match self . lift_lower {
878
+ match lift_lower {
888
879
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_) {
890
882
unimplemented ! ( "host-side code generation for async lift/lower not supported" ) ;
891
883
}
892
884
@@ -902,7 +894,7 @@ impl<'a, B: Bindgen> Generator<'a, B> {
902
894
self_. stack . push ( ptr) ;
903
895
} ;
904
896
905
- if self . async_ {
897
+ if async_ {
906
898
let ElementInfo { size, align } = self
907
899
. bindgen
908
900
. sizes ( )
@@ -926,7 +918,7 @@ impl<'a, B: Bindgen> Generator<'a, B> {
926
918
. bindgen
927
919
. sizes ( )
928
920
. record ( func. params . iter ( ) . map ( |t| & t. 1 ) ) ;
929
- let ptr = match self . variant {
921
+ let ptr = match variant {
930
922
// When a wasm module calls an import it will provide
931
923
// space that isn't explicitly deallocated.
932
924
AbiVariant :: GuestImport => self . bindgen . return_pointer ( size, align) ,
@@ -949,8 +941,9 @@ impl<'a, B: Bindgen> Generator<'a, B> {
949
941
lower_to_memory ( self , ptr) ;
950
942
}
951
943
}
944
+ self . realloc = None ;
952
945
953
- if self . async_ {
946
+ if async_ {
954
947
let ElementInfo { size, align } =
955
948
self . bindgen . sizes ( ) . record ( func. result . iter ( ) ) ;
956
949
let ptr = self . bindgen . return_pointer ( size, align) ;
@@ -964,7 +957,7 @@ impl<'a, B: Bindgen> Generator<'a, B> {
964
957
} else {
965
958
// If necessary we may need to prepare a return pointer for
966
959
// this ABI.
967
- if self . variant == AbiVariant :: GuestImport && sig. retptr {
960
+ if variant == AbiVariant :: GuestImport && sig. retptr {
968
961
let info = self . bindgen . sizes ( ) . params ( & func. result ) ;
969
962
let ptr = self . bindgen . return_pointer ( info. size , info. align ) ;
970
963
self . return_pointer = Some ( ptr. clone ( ) ) ;
@@ -978,22 +971,22 @@ impl<'a, B: Bindgen> Generator<'a, B> {
978
971
} ) ;
979
972
}
980
973
981
- if !( sig. retptr || self . async_ ) {
974
+ if !( sig. retptr || async_) {
982
975
// With no return pointer in use we can simply lift the
983
976
// result(s) of the function from the result of the core
984
977
// wasm function.
985
978
if let Some ( ty) = & func. result {
986
979
self . lift ( ty)
987
980
}
988
981
} else {
989
- let ptr = match self . variant {
982
+ let ptr = match variant {
990
983
// imports into guests means it's a wasm module
991
984
// calling an imported function. We supplied the
992
985
// return pointer as the last argument (saved in
993
986
// `self.return_pointer`) so we use that to read
994
987
// the result of the function from memory.
995
988
AbiVariant :: GuestImport => {
996
- assert ! ( sig. results. is_empty( ) || self . async_) ;
989
+ assert ! ( sig. results. is_empty( ) || async_) ;
997
990
self . return_pointer . take ( ) . unwrap ( )
998
991
}
999
992
@@ -1025,7 +1018,7 @@ impl<'a, B: Bindgen> Generator<'a, B> {
1025
1018
} ) ;
1026
1019
}
1027
1020
LiftLower :: LiftArgsLowerResults => {
1028
- if let ( AbiVariant :: GuestImport , true ) = ( self . variant , self . async_ ) {
1021
+ if let ( AbiVariant :: GuestImport , true ) = ( variant, async_) {
1029
1022
todo ! ( "implement host-side support for async lift/lower" ) ;
1030
1023
}
1031
1024
@@ -1065,10 +1058,10 @@ impl<'a, B: Bindgen> Generator<'a, B> {
1065
1058
// ... and that allows us to call the interface types function
1066
1059
self . emit ( & Instruction :: CallInterface {
1067
1060
func,
1068
- async_ : self . async_ ,
1061
+ async_ : async_,
1069
1062
} ) ;
1070
1063
1071
- let ( lower_to_memory, async_results) = if self . async_ {
1064
+ let ( lower_to_memory, async_results) = if async_ {
1072
1065
self . emit ( & Instruction :: AsyncPostCallInterface { func } ) ;
1073
1066
1074
1067
let mut results = Vec :: new ( ) ;
@@ -1083,8 +1076,8 @@ impl<'a, B: Bindgen> Generator<'a, B> {
1083
1076
// This was dynamically allocated by the caller (or async start
1084
1077
// function) so after it's been read by the guest we need to
1085
1078
// 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_ {
1088
1081
let ElementInfo { size, align } = self
1089
1082
. bindgen
1090
1083
. sizes ( )
@@ -1094,14 +1087,16 @@ impl<'a, B: Bindgen> Generator<'a, B> {
1094
1087
}
1095
1088
}
1096
1089
1090
+ self . realloc = Some ( realloc) ;
1091
+
1097
1092
if !lower_to_memory {
1098
1093
// With no return pointer in use we simply lower the
1099
1094
// result(s) and return that directly from the function.
1100
1095
if let Some ( ty) = & func. result {
1101
1096
self . lower ( ty) ;
1102
1097
}
1103
1098
} else {
1104
- match self . variant {
1099
+ match variant {
1105
1100
// When a function is imported to a guest this means
1106
1101
// it's a host providing the implementation of the
1107
1102
// import. The result is stored in the pointer
@@ -1159,9 +1154,12 @@ impl<'a, B: Bindgen> Generator<'a, B> {
1159
1154
amt : sig. results . len ( ) ,
1160
1155
} ) ;
1161
1156
}
1157
+ self . realloc = None ;
1162
1158
}
1163
1159
}
1164
1160
1161
+ assert ! ( self . realloc. is_none( ) ) ;
1162
+
1165
1163
assert ! (
1166
1164
self . stack. is_empty( ) ,
1167
1165
"stack has {} items remaining" ,
@@ -1170,7 +1168,7 @@ impl<'a, B: Bindgen> Generator<'a, B> {
1170
1168
}
1171
1169
1172
1170
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) ;
1174
1172
1175
1173
// Currently post-return is only used for lists and lists are always
1176
1174
// returned indirectly through memory due to their flat representation
@@ -1424,13 +1422,9 @@ impl<'a, B: Bindgen> Generator<'a, B> {
1424
1422
}
1425
1423
1426
1424
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) ,
1434
1428
}
1435
1429
}
1436
1430
0 commit comments