@@ -718,7 +718,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
718
718
// );
719
719
}
720
720
721
- Instruction :: ListCanonLower { element, realloc } => {
721
+ Instruction :: ListCanonLower { element, .. } => {
722
722
let list: & String = & operands[ 0 ] ;
723
723
match self . interface_gen . direction {
724
724
Direction :: Import => {
@@ -755,29 +755,20 @@ impl Bindgen for FunctionBindgen<'_, '_> {
755
755
results. push ( format ! ( "({list}).Length" ) ) ;
756
756
}
757
757
Direction :: Export => {
758
+ let ( _, ty) = list_element_info ( element) ;
758
759
let address = self . locals . tmp ( "address" ) ;
759
- let buffer = self . locals . tmp ( "buffer" ) ;
760
- let gc_handle = self . locals . tmp ( "gcHandle" ) ;
761
760
let size = self . interface_gen . csharp_gen . sizes . size ( element) . size_wasm32 ( ) ;
761
+ let byte_length = self . locals . tmp ( "byteLength" ) ;
762
762
uwrite ! (
763
763
self . src,
764
764
"
765
- byte[] {buffer} = new byte[({size}) * {list}.Length];
766
- Buffer.BlockCopy({list}.ToArray(), 0, {buffer}, 0, ({size}) * {list}.Length);
767
- var {gc_handle} = GCHandle.Alloc({buffer}, GCHandleType.Pinned);
768
- var {address} = {gc_handle}.AddrOfPinnedObject();
765
+ var {byte_length} = ({size}) * {list}.Length;
766
+ var {address} = NativeMemory.Alloc((nuint)({byte_length}));
767
+ {list}.AsSpan().CopyTo(new Span<{ty}>({address},{byte_length}));
769
768
"
770
769
) ;
771
770
772
- if realloc. is_none ( ) {
773
- self . needs_cleanup = true ;
774
- uwrite ! (
775
- self . src,
776
- "
777
- cleanups.Add(()=> {gc_handle}.Free());
778
- " ) ;
779
- }
780
- results. push ( format ! ( "((IntPtr)({address})).ToInt32()" ) ) ;
771
+ results. push ( format ! ( "(int)({address})" ) ) ;
781
772
results. push ( format ! ( "{list}.Length" ) ) ;
782
773
}
783
774
}
@@ -802,33 +793,45 @@ impl Bindgen for FunctionBindgen<'_, '_> {
802
793
803
794
Instruction :: StringLower { realloc } => {
804
795
let op = & operands[ 0 ] ;
805
- let interop_string = self . locals . tmp ( "interopString " ) ;
796
+ let str_ptr = self . locals . tmp ( "strPtr " ) ;
806
797
let utf8_bytes = self . locals . tmp ( "utf8Bytes" ) ;
807
798
let length = self . locals . tmp ( "length" ) ;
808
799
let gc_handle = self . locals . tmp ( "gcHandle" ) ;
809
- uwriteln ! (
810
- self . src,
811
- "
812
- var {utf8_bytes} = Encoding.UTF8.GetBytes({op});
813
- var {length} = {utf8_bytes}.Length;
814
- var {gc_handle} = GCHandle.Alloc({utf8_bytes}, GCHandleType.Pinned);
815
- var {interop_string} = {gc_handle}.AddrOfPinnedObject();
816
- "
817
- ) ;
818
800
819
801
if realloc. is_none ( ) {
820
- results. push ( format ! ( "{interop_string}.ToInt32()" ) ) ;
802
+ uwriteln ! (
803
+ self . src,
804
+ "
805
+ var {utf8_bytes} = Encoding.UTF8.GetBytes({op});
806
+ var {length} = {utf8_bytes}.Length;
807
+ var {gc_handle} = GCHandle.Alloc({utf8_bytes}, GCHandleType.Pinned);
808
+ var {str_ptr} = {gc_handle}.AddrOfPinnedObject();
809
+ "
810
+ ) ;
811
+
821
812
self . needs_cleanup = true ;
822
813
uwrite ! (
823
814
self . src,
824
815
"
825
816
cleanups.Add(()=> {gc_handle}.Free());
826
- " ) ;
817
+ "
818
+ ) ;
819
+ results. push ( format ! ( "{str_ptr}.ToInt32()" ) ) ;
827
820
} else {
828
- results. push ( format ! ( "{interop_string}.ToInt32()" ) ) ;
821
+ let string_span = self . locals . tmp ( "stringSpan" ) ;
822
+ uwriteln ! (
823
+ self . src,
824
+ "
825
+ var {string_span} = {op}.AsSpan();
826
+ var {length} = Encoding.UTF8.GetByteCount({string_span});
827
+ var {str_ptr} = NativeMemory.Alloc((nuint){length});
828
+ Encoding.UTF8.GetBytes({string_span}, new Span<byte>({str_ptr}, {length}));
829
+ "
830
+ ) ;
831
+ results. push ( format ! ( "(int){str_ptr}" ) ) ;
829
832
}
830
- results. push ( format ! ( "{length}" ) ) ;
831
833
834
+ results. push ( format ! ( "{length}" ) ) ;
832
835
if FunctionKind :: Freestanding == * self . kind || self . interface_gen . direction == Direction :: Export {
833
836
self . interface_gen . require_interop_using ( "System.Text" ) ;
834
837
self . interface_gen . require_interop_using ( "System.Runtime.InteropServices" ) ;
@@ -851,7 +854,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
851
854
) ) ;
852
855
}
853
856
854
- Instruction :: ListLower { element, .. } => {
857
+ Instruction :: ListLower { element, realloc } => {
855
858
let Block {
856
859
body,
857
860
results : block_results,
@@ -876,22 +879,38 @@ impl Bindgen for FunctionBindgen<'_, '_> {
876
879
) ;
877
880
let ret_area = self . locals . tmp ( "retArea" ) ;
878
881
879
- self . needs_cleanup = true ;
880
- uwrite ! (
881
- self . src,
882
- "
883
- void* {address};
884
- if (({size} * {list}.Count) < 1024) {{
885
- var {ret_area} = stackalloc {element_type}[({array_size}*{list}.Count)+1];
886
- {address} = (void*)(((int){ret_area}) + ({align} - 1) & -{align});
887
- }}
888
- else
889
- {{
890
- var {buffer_size} = {size} * (nuint){list}.Count;
891
- {address} = NativeMemory.AlignedAlloc({buffer_size}, {align});
892
- cleanups.Add(()=> NativeMemory.AlignedFree({address}));
893
- }}
882
+ match realloc {
883
+ None => {
884
+ self . needs_cleanup = true ;
885
+ uwrite ! ( self . src,
886
+ "
887
+ void* {address};
888
+ if (({size} * {list}.Count) < 1024) {{
889
+ var {ret_area} = stackalloc {element_type}[({array_size}*{list}.Count)+1];
890
+ {address} = (void*)(((int){ret_area}) + ({align} - 1) & -{align});
891
+ }}
892
+ else
893
+ {{
894
+ var {buffer_size} = {size} * (nuint){list}.Count;
895
+ {address} = NativeMemory.AlignedAlloc({buffer_size}, {align});
896
+ cleanups.Add(() => NativeMemory.AlignedFree({address}));
897
+ }}
898
+ "
899
+ ) ;
900
+ }
901
+ Some ( _) => {
902
+ //cabi_realloc_post_return will be called to clean up this allocation
903
+ uwrite ! ( self . src,
904
+ "
905
+ var {buffer_size} = {size} * (nuint){list}.Count;
906
+ void* {address} = NativeMemory.AlignedAlloc({buffer_size}, {align});
907
+ "
908
+ ) ;
909
+ }
910
+ }
894
911
912
+ uwrite ! ( self . src,
913
+ "
895
914
for (int {index} = 0; {index} < {list}.Count; ++{index}) {{
896
915
{ty} {block_element} = {list}[{index}];
897
916
int {base} = (int){address} + ({index} * {size});
@@ -1035,7 +1054,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
1035
1054
}
1036
1055
}
1037
1056
1038
- Instruction :: Return { amt : _ , func } => {
1057
+ Instruction :: Return { amt, .. } => {
1039
1058
if self . fixed_statments . len ( ) > 0 {
1040
1059
let fixed: String = self . fixed_statments . iter ( ) . map ( |f| format ! ( "{} = {}" , f. ptr_name, f. item_to_pin) ) . collect :: < Vec < _ > > ( ) . join ( ", " ) ;
1041
1060
self . src . insert_str ( 0 , & format ! ( "fixed (void* {fixed})
@@ -1055,7 +1074,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
1055
1074
}
1056
1075
1057
1076
if !matches ! ( ( self . interface_gen. direction, self . kind) , ( Direction :: Import , FunctionKind :: Constructor ( _) ) ) {
1058
- match func . results . len ( ) {
1077
+ match * amt {
1059
1078
0 => ( ) ,
1060
1079
1 => {
1061
1080
self . handle_result_import ( operands) ;
@@ -1075,19 +1094,72 @@ impl Bindgen for FunctionBindgen<'_, '_> {
1075
1094
Instruction :: Malloc { .. } => unimplemented ! ( ) ,
1076
1095
1077
1096
Instruction :: GuestDeallocate { .. } => {
1078
- uwriteln ! ( self . src, r#"Console.WriteLine("TODO: deallocate buffer for indirect parameters");"# ) ;
1097
+ // the original alloc here comes from cabi_realloc implementation (wasi-libc in .net)
1098
+ uwriteln ! ( self . src, r#"NativeMemory.Free((void*){});"# , operands[ 0 ] ) ;
1079
1099
}
1080
1100
1081
1101
Instruction :: GuestDeallocateString => {
1082
- uwriteln ! ( self . src, r#"Console.WriteLine("TODO: deallocate buffer for string") ;"# ) ;
1102
+ uwriteln ! ( self . src, r#"NativeMemory.Free((void*){}) ;"# , operands [ 0 ] ) ;
1083
1103
}
1084
1104
1085
- Instruction :: GuestDeallocateVariant { .. } => {
1086
- uwriteln ! ( self . src, r#"Console.WriteLine("TODO: deallocate buffer for variant");"# ) ;
1105
+ Instruction :: GuestDeallocateVariant { blocks } => {
1106
+ let cases = self
1107
+ . blocks
1108
+ . drain ( self . blocks . len ( ) - blocks..)
1109
+ . enumerate ( )
1110
+ . map ( |( i, Block { body, results, .. } ) | {
1111
+ assert ! ( results. is_empty( ) ) ;
1112
+
1113
+ format ! (
1114
+ "case {i}: {{
1115
+ {body}
1116
+ break;
1117
+ }}"
1118
+ )
1119
+ } )
1120
+ . collect :: < Vec < _ > > ( )
1121
+ . join ( "\n " ) ;
1122
+
1123
+ let op = & operands[ 0 ] ;
1124
+
1125
+ uwrite ! (
1126
+ self . src,
1127
+ "
1128
+ switch ({op}) {{
1129
+ {cases}
1130
+ }}
1131
+ "
1132
+ ) ;
1087
1133
}
1088
1134
1089
- Instruction :: GuestDeallocateList { .. } => {
1090
- uwriteln ! ( self . src, r#"Console.WriteLine("TODO: deallocate buffer for list");"# ) ;
1135
+ Instruction :: GuestDeallocateList { element : element_type } => {
1136
+ let Block {
1137
+ body,
1138
+ results : block_results,
1139
+ base,
1140
+ element : _,
1141
+ } = self . blocks . pop ( ) . unwrap ( ) ;
1142
+ assert ! ( block_results. is_empty( ) ) ;
1143
+
1144
+ let address = & operands[ 0 ] ;
1145
+ let length = & operands[ 1 ] ;
1146
+ let size = self . interface_gen . csharp_gen . sizes . size ( element_type) . size_wasm32 ( ) ;
1147
+
1148
+ if !body. trim ( ) . is_empty ( ) {
1149
+ let index = self . locals . tmp ( "index" ) ;
1150
+
1151
+ uwrite ! (
1152
+ self . src,
1153
+ "
1154
+ for (int {index} = 0; {index} < {length}; ++{index}) {{
1155
+ int {base} = (int){address} + ({index} * {size});
1156
+ {body}
1157
+ }}
1158
+ "
1159
+ ) ;
1160
+ }
1161
+
1162
+ uwriteln ! ( self . src, r#"NativeMemory.Free((void*){});"# , operands[ 0 ] ) ;
1091
1163
}
1092
1164
1093
1165
Instruction :: HandleLower {
0 commit comments