@@ -6,7 +6,7 @@ use std::mem::{replace, take};
66use std:: path:: PathBuf ;
77use wit_bindgen_core:: {
88 Direction , Files , InterfaceGenerator , Source , Types , WorldGenerator ,
9- abi:: { self , Bindgen , WasmType } ,
9+ abi:: { self , Bindgen , Bitcast , WasmType } ,
1010 wit_parser:: * ,
1111} ;
1212
@@ -322,6 +322,9 @@ impl D {
322322 direction,
323323
324324 wasm_import_module,
325+
326+ return_pointer_area_size : Default :: default ( ) ,
327+ return_pointer_area_align : Default :: default ( ) ,
325328 }
326329 }
327330
@@ -598,6 +601,9 @@ impl WorldGenerator for D {
598601 }
599602 }
600603
604+ let ret_area_decl = r#gen. emit_ret_area_if_needed ( ) ;
605+
606+ r#gen. src . push_str ( & ret_area_decl) ;
601607 r#gen. src . push_str ( "}\n " ) ;
602608
603609 let mut interface_filepath = PathBuf :: from_iter ( fqn. split ( "." ) ) ;
@@ -618,10 +624,19 @@ impl WorldGenerator for D {
618624 ) -> Result < ( ) > {
619625 let mut r#gen = self . interface ( resolve, Some ( Direction :: Export ) , None , Some ( "$root" ) ) ;
620626 for ( _name, func) in funcs {
621- r#gen. export_func ( func) ;
627+ match func. kind {
628+ FunctionKind :: Freestanding | FunctionKind :: AsyncFreestanding => {
629+ r#gen. export_func ( func) ;
630+ }
631+ _ => { }
632+ }
622633 }
623634
635+ let ret_area_decl = r#gen. emit_ret_area_if_needed ( ) ;
636+
624637 self . function_exports_src = take ( & mut r#gen. src ) ;
638+ self . function_exports_src . push_str ( & ret_area_decl) ;
639+
625640 Ok ( ( ) )
626641 }
627642
@@ -720,6 +735,9 @@ struct DInterfaceGenerator<'a> {
720735 fqn : & ' a str ,
721736
722737 sizes : SizeAlign ,
738+
739+ return_pointer_area_size : ArchitectureSize ,
740+ return_pointer_area_align : Alignment ,
723741}
724742
725743impl < ' a > DInterfaceGenerator < ' a > {
@@ -1095,11 +1113,15 @@ impl<'a> DInterfaceGenerator<'a> {
10951113 fn export_func ( & mut self , func : & Function ) {
10961114 match & func. kind {
10971115 FunctionKind :: Freestanding => { }
1116+ FunctionKind :: Constructor ( _) => {
1117+ todo ! ( "Export FunctionKind::Constructor - {}\n " , func. name) ;
1118+ }
10981119 FunctionKind :: Method ( _) => { }
1120+ FunctionKind :: Static ( _) => {
1121+ todo ! ( "Export FunctionKind::Static - {}\n " , func. name) ;
1122+ }
10991123 kind => {
1100- self . src
1101- . push_str ( & format ! ( "// TODO: Export {kind:?} - {}\n " , func. name) ) ;
1102- return ;
1124+ todo ! ( "Export {kind:?} - {}\n " , func. name) ;
11031125 }
11041126 }
11051127
@@ -1205,14 +1227,37 @@ impl<'a> DInterfaceGenerator<'a> {
12051227 & mut f,
12061228 false ,
12071229 ) ;
1230+
12081231 let ret_area_decl = f. emit_ret_area_if_needed ( ) ;
12091232
1210- let FunctionBindgen { src, .. } = f;
1233+ let FunctionBindgen {
1234+ src,
1235+ return_pointer_area_size,
1236+ return_pointer_area_align,
1237+ ..
1238+ } = f;
1239+ self . return_pointer_area_size = self . return_pointer_area_size . max ( return_pointer_area_size) ;
1240+ self . return_pointer_area_align = self
1241+ . return_pointer_area_align
1242+ . max ( return_pointer_area_align) ;
1243+
12111244 self . src . push_str ( & ret_area_decl) ;
12121245 self . src . push_str ( & src. to_string ( ) ) ;
12131246
12141247 self . src . push_str ( "}\n " ) ;
12151248 }
1249+
1250+ fn emit_ret_area_if_needed ( & self ) -> String {
1251+ if !self . return_pointer_area_size . is_empty ( ) {
1252+ format ! (
1253+ "\n align({}) private void[{}] _exportsRetArea;\n " ,
1254+ self . return_pointer_area_align. format( "size_t.sizeof" ) ,
1255+ self . return_pointer_area_size. format( "size_t.sizeof" )
1256+ )
1257+ } else {
1258+ String :: new ( )
1259+ }
1260+ }
12161261}
12171262
12181263impl < ' a > InterfaceGenerator < ' a > for DInterfaceGenerator < ' a > {
@@ -1894,7 +1939,7 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
18941939
18951940 fn store ( & mut self , ty : & str , offset : ArchitectureSize , operands : & [ String ] ) {
18961941 self . push_str ( & format ! (
1897- "*( cast({ty}*)({} + {}) ) = cast({ty})({});\n " ,
1942+ "*cast({ty}*)({} + {}) = cast({ty})({});\n " ,
18981943 operands[ 1 ] ,
18991944 offset. format( "size_t.sizeof" ) ,
19001945 operands[ 0 ]
@@ -1915,22 +1960,58 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
19151960 /// The scratch space is reused but never accessed simultaneously.
19161961 fn emit_ret_area_if_needed ( & self ) -> String {
19171962 if !self . return_pointer_area_size . is_empty ( ) {
1918- format ! (
1919- "{}align({}) void[{}] _retArea = void;\n " ,
1920- if self . r#gen. direction == Some ( Direction :: Export ) {
1921- "static "
1922- } else {
1923- ""
1924- } ,
1925- self . return_pointer_area_align. format( "size_t.sizeof" ) ,
1926- self . return_pointer_area_size. format( "size_t.sizeof" )
1927- )
1963+ match self . r#gen . direction {
1964+ Some ( Direction :: Import ) => format ! (
1965+ "align({}) void[{}] _retArea = void;\n " ,
1966+ self . return_pointer_area_align. format( "size_t.sizeof" ) ,
1967+ self . return_pointer_area_size. format( "size_t.sizeof" )
1968+ ) ,
1969+ Some ( Direction :: Export ) => "alias _retArea = _exportsRetArea;\n " . to_string ( ) ,
1970+ None => {
1971+ unreachable ! ( ) ;
1972+ }
1973+ }
19281974 } else {
19291975 String :: new ( )
19301976 }
19311977 }
19321978}
19331979
1980+ fn perform_cast ( op : & str , cast : & Bitcast ) -> String {
1981+ match cast {
1982+ Bitcast :: I32ToF32 | Bitcast :: I64ToF32 => {
1983+ format ! ( "cast(uint)({op}).reinterpretCast!float" )
1984+ }
1985+ Bitcast :: F32ToI32 | Bitcast :: F32ToI64 => {
1986+ format ! ( "({op}).reinterpretCast!uint" )
1987+ }
1988+ Bitcast :: I64ToF64 => {
1989+ format ! ( "({op}).reinterpretCast!double" )
1990+ }
1991+ Bitcast :: F64ToI64 => {
1992+ format ! ( "({op}).reinterpretCast!ulong" )
1993+ }
1994+ Bitcast :: I32ToI64 | Bitcast :: LToI64 | Bitcast :: PToP64 => {
1995+ format ! ( "cast(ulong)({op})" )
1996+ }
1997+ Bitcast :: I64ToI32 | Bitcast :: PToI32 | Bitcast :: LToI32 => {
1998+ format ! ( "cast(uint)({op})" )
1999+ }
2000+ Bitcast :: P64ToI64 | Bitcast :: None | Bitcast :: I64ToP64 => op. to_string ( ) ,
2001+ Bitcast :: P64ToP | Bitcast :: I32ToP | Bitcast :: LToP => {
2002+ format ! ( "cast(void*)({op})" )
2003+ }
2004+ Bitcast :: PToL | Bitcast :: I32ToL | Bitcast :: I64ToL => {
2005+ format ! ( "cast(size_t)({op})" )
2006+ }
2007+ Bitcast :: Sequence ( sequence) => {
2008+ let [ first, second] = & * * sequence;
2009+ let inner = perform_cast ( op, first) ;
2010+ perform_cast ( & inner, second)
2011+ }
2012+ }
2013+ }
2014+
19342015impl < ' a , ' b > Bindgen for FunctionBindgen < ' a , ' b > {
19352016 type Operand = String ;
19362017
@@ -1942,7 +2023,7 @@ impl<'a, 'b> Bindgen for FunctionBindgen<'a, 'b> {
19422023 results : & mut Vec < Self :: Operand > ,
19432024 ) {
19442025 let mut top_as = |cvt : & str | {
1945- results. push ( format ! ( "( cast({cvt})({}) )" , operands. pop( ) . unwrap( ) ) ) ;
2026+ results. push ( format ! ( "cast({cvt})({})" , operands. pop( ) . unwrap( ) ) ) ;
19462027 } ;
19472028
19482029 match inst {
@@ -1955,6 +2036,12 @@ impl<'a, 'b> Bindgen for FunctionBindgen<'a, 'b> {
19552036 }
19562037
19572038 abi:: Instruction :: I32Const { val } => results. push ( val. to_string ( ) ) ,
2039+ abi:: Instruction :: Bitcasts { casts } => {
2040+ for ( cast, op) in casts. iter ( ) . zip ( operands) {
2041+ let op = perform_cast ( op, cast) ;
2042+ results. push ( op) ;
2043+ }
2044+ }
19582045 abi:: Instruction :: ConstZero { tys } => {
19592046 for ty in tys. iter ( ) {
19602047 results. push (
@@ -2027,7 +2114,7 @@ impl<'a, 'b> Bindgen for FunctionBindgen<'a, 'b> {
20272114 abi:: Instruction :: CharFromI32 => top_as ( "dchar" ) ,
20282115 abi:: Instruction :: F32FromCoreF32 => results. push ( operands. pop ( ) . unwrap ( ) ) ,
20292116 abi:: Instruction :: F64FromCoreF64 => results. push ( operands. pop ( ) . unwrap ( ) ) ,
2030- abi:: Instruction :: BoolFromI32 => results. push ( format ! ( "({} != 0) " , operands[ 0 ] ) ) ,
2117+ abi:: Instruction :: BoolFromI32 => results. push ( format ! ( "({}) != 0" , operands[ 0 ] ) ) ,
20312118
20322119 abi:: Instruction :: ListCanonLower { .. } | abi:: Instruction :: StringLower { .. } => {
20332120 results. push ( format ! ( "cast(void*)({}.ptr)" , operands[ 0 ] ) ) ;
@@ -2059,7 +2146,7 @@ impl<'a, 'b> Bindgen for FunctionBindgen<'a, 'b> {
20592146 "foreach ({block_element}_idx, const ref {block_element}; {list_src}) {{\n "
20602147 ) ) ;
20612148 self . push_str ( & format ! (
2062- "auto {base} = {list} + {block_element}_idx * {size_str};\n "
2149+ "auto {base} = {list} + {block_element}_idx * ( {size_str}) ;\n "
20632150 ) ) ;
20642151 self . push_str ( & body) ;
20652152 //self.push_str(&format!("_targetElem = {};", body.1[0]));
@@ -2681,10 +2768,13 @@ impl<'a, 'b> Bindgen for FunctionBindgen<'a, 'b> {
26812768 todo ! ( "instr: Malloc" )
26822769 }
26832770 abi:: Instruction :: GuestDeallocate { .. } => {
2684- todo ! ( "instr: GuestDeallocate" )
2771+ self . push_str ( & format ! ( "free({});" , operands [ 0 ] ) ) ;
26852772 }
26862773 abi:: Instruction :: GuestDeallocateString { .. } => {
2687- todo ! ( "instr: GuestDeallocateString" )
2774+ todo ! ( "instr: GuestDeallocateString" ) ;
2775+ //self.push_str(&format!("if (({}) > 0) {{\n", operands[1]));
2776+ //self.push_str(&format!("free({});", operands[0]));
2777+ //self.push_str("}\n");
26882778 }
26892779 abi:: Instruction :: GuestDeallocateList { .. } => {
26902780 todo ! ( "instr: GuestDeallocateList" )
0 commit comments