@@ -420,6 +420,7 @@ impl Go {
420420 false ,
421421 imported_type,
422422 ) ;
423+ generator. collect_lifters = true ;
423424
424425 let lift_result =
425426 abi:: lift_from_memory ( resolve, & mut generator, "src" . to_string ( ) , & ty) ;
@@ -432,6 +433,21 @@ impl Go {
432433 "value" . to_string ( ) ,
433434 & ty,
434435 ) ;
436+
437+ let lifter_count = generator. lifter_count ;
438+ let ( prefix, suffix) = if lifter_count > 0 {
439+ (
440+ format ! ( "lifters := make([]func(), 0, {lifter_count})\n " ) ,
441+ "\n return func() {
442+ for _, lifter := range lifters {
443+ lifter()
444+ }
445+ }" ,
446+ )
447+ } else {
448+ ( String :: new ( ) , "\n return func() {}" )
449+ } ;
450+
435451 let lower = mem:: take ( & mut generator. src ) ;
436452 data. extend ( InterfaceData :: from_generator_and_code (
437453 generator,
@@ -448,8 +464,12 @@ impl Go {
448464 ) ,
449465 format ! ( "wasm_{kind}_lift_{snake}" ) ,
450466 format ! (
451- "func wasm_{kind}_lower_{snake}(pinner *runtime.Pinner, value {payload}, dst unsafe.Pointer) {{
452- {lower}
467+ "func wasm_{kind}_lower_{snake}(
468+ pinner *runtime.Pinner,
469+ value {payload},
470+ dst unsafe.Pointer,
471+ ) func() {{
472+ {prefix}{lower}{suffix}
453473}}
454474"
455475 ) ,
@@ -1014,15 +1034,33 @@ impl Go {
10141034 . collect :: < Vec < _ > > ( )
10151035 . join ( ", " ) ;
10161036
1017- let lift = if let Some ( result ) = func. result {
1037+ let lift = if let Some ( ty ) = func. result {
10181038 let result = abi:: lift_from_memory (
10191039 resolve,
10201040 & mut generator,
10211041 IMPORT_RETURN_AREA . to_string ( ) ,
1022- & result ,
1042+ & ty ,
10231043 ) ;
10241044 let code = mem:: take ( & mut generator. src ) ;
1025- format ! ( "{code}\n return {result}" )
1045+ if let Type :: Id ( ty) = ty
1046+ && let TypeDefKind :: Tuple ( tuple) = & resolve. types [ ty] . kind
1047+ {
1048+ let count = tuple. types . len ( ) ;
1049+ let tuple = generator. locals . tmp ( "tuple" ) ;
1050+
1051+ let results = ( 0 ..count)
1052+ . map ( |index| format ! ( "{tuple}.F{index}" ) )
1053+ . collect :: < Vec < _ > > ( )
1054+ . join ( ", " ) ;
1055+
1056+ format ! (
1057+ "{code}
1058+ {tuple} := {result}
1059+ return {results}"
1060+ )
1061+ } else {
1062+ format ! ( "{code}\n return {result}" )
1063+ }
10261064 } else {
10271065 String :: new ( )
10281066 } ;
@@ -1403,6 +1441,8 @@ struct FunctionGenerator<'a> {
14031441 need_unsafe : bool ,
14041442 need_pinner : bool ,
14051443 need_math : bool ,
1444+ collect_lifters : bool ,
1445+ lifter_count : u32 ,
14061446 return_area_size : ArchitectureSize ,
14071447 return_area_align : Alignment ,
14081448 imports : BTreeSet < String > ,
@@ -1441,6 +1481,8 @@ impl<'a> FunctionGenerator<'a> {
14411481 need_unsafe : false ,
14421482 need_pinner : false ,
14431483 need_math : false ,
1484+ collect_lifters : false ,
1485+ lifter_count : 0 ,
14441486 return_area_size : ArchitectureSize :: default ( ) ,
14451487 return_area_align : Alignment :: default ( ) ,
14461488 imports : BTreeSet :: new ( ) ,
@@ -1744,13 +1786,18 @@ for index := 0; index < int({length}); index++ {{
17441786 && let TypeDefKind :: Tuple ( tuple) = & resolve. types [ ty] . kind
17451787 {
17461788 let count = tuple. types . len ( ) ;
1789+ let tuple = self . locals . tmp ( "tuple" ) ;
17471790
17481791 let results = ( 0 ..count)
1749- . map ( |index| format ! ( "({result}) .F{index}" ) )
1792+ . map ( |index| format ! ( "{tuple} .F{index}" ) )
17501793 . collect :: < Vec < _ > > ( )
17511794 . join ( ", " ) ;
17521795
1753- uwriteln ! ( self . src, "return {results}" ) ;
1796+ uwriteln ! (
1797+ self . src,
1798+ "{tuple} := {result}
1799+ return {results}"
1800+ ) ;
17541801 } else {
17551802 uwriteln ! ( self . src, "return {result}" ) ;
17561803 }
@@ -2275,7 +2322,25 @@ default:
22752322 | Instruction :: HandleLower {
22762323 handle : Handle :: Own ( _) ,
22772324 ..
2278- } => results. push ( format ! ( "({}).TakeHandle()" , operands[ 0 ] ) ) ,
2325+ } => {
2326+ let op = & operands[ 0 ] ;
2327+ if self . collect_lifters {
2328+ self . lifter_count += 1 ;
2329+ let resource = self . locals . tmp ( "resource" ) ;
2330+ let handle = self . locals . tmp ( "handle" ) ;
2331+ uwriteln ! (
2332+ self . src,
2333+ "{resource} := {op}
2334+ {handle} := {resource}.TakeHandle()
2335+ lifters = append(lifters, func() {{
2336+ {resource}.SetHandle({handle})
2337+ }})"
2338+ ) ;
2339+ results. push ( handle)
2340+ } else {
2341+ results. push ( format ! ( "({op}).TakeHandle()" ) )
2342+ }
2343+ }
22792344 Instruction :: HandleLower {
22802345 handle : Handle :: Borrow ( _) ,
22812346 ..
@@ -2469,6 +2534,10 @@ func (self *{camel}) TakeHandle() int32 {{
24692534 return self.handle.Take()
24702535}}
24712536
2537+ func (self *{camel}) SetHandle(handle int32) {{
2538+ self.handle.Set(handle)
2539+ }}
2540+
24722541func (self *{camel}) Handle() int32 {{
24732542 return self.handle.Use()
24742543}}
@@ -2525,6 +2594,12 @@ func (self *{camel}) TakeHandle() int32 {{
25252594 return self.handle
25262595}}
25272596
2597+ func (self *{camel}) SetHandle(handle int32) {{
2598+ if self.handle != handle {{
2599+ panic("invalid handle")
2600+ }}
2601+ }}
2602+
25282603func (self *{camel}) Drop() {{
25292604 handle := self.handle
25302605 if self.handle != 0 {{
@@ -3011,12 +3086,12 @@ fn func_declaration(resolve: &Resolve, func: &Function) -> (String, bool) {
30113086}
30123087
30133088fn maybe_gofmt < ' a > ( format : Format , code : & ' a [ u8 ] ) -> Cow < ' a , [ u8 ] > {
3014- return thread:: scope ( |s| {
3089+ thread:: scope ( |s| {
30153090 if let Format :: True = format
30163091 && let Ok ( ( reader, mut writer) ) = io:: pipe ( )
30173092 {
30183093 s. spawn ( move || {
3019- _ = writer. write_all ( & code) ;
3094+ _ = writer. write_all ( code) ;
30203095 } ) ;
30213096
30223097 if let Ok ( output) = Command :: new ( "gofmt" ) . stdin ( reader) . output ( )
@@ -3027,5 +3102,5 @@ fn maybe_gofmt<'a>(format: Format, code: &'a [u8]) -> Cow<'a, [u8]> {
30273102 }
30283103
30293104 Cow :: Borrowed ( code)
3030- } ) ;
3105+ } )
30313106}
0 commit comments