@@ -528,23 +528,20 @@ impl Generator for RustWasm {
528
528
fn export ( & mut self , iface : & Interface , func : & Function ) {
529
529
let iface_name = iface. name . to_snake_case ( ) ;
530
530
531
- self . src . push_str ( "#[export_name = \" " ) ;
532
- match & iface. module {
531
+ let name_mangled = iface. mangle_funcname ( func) ;
532
+ let name_snake = func. name . to_snake_case ( ) ;
533
+ let name = match & iface. module {
533
534
Some ( module) => {
534
- self . src . push_str ( module) ;
535
- self . src . push_str ( "#" ) ;
536
- self . src . push_str ( & iface. mangle_funcname ( func) ) ;
535
+ format ! ( "{module}#{}" , name_mangled)
537
536
}
538
- None => {
539
- self . src . push_str ( & self . opts . symbol_namespace ) ;
540
- self . src . push_str ( & iface. mangle_funcname ( func) ) ;
541
- }
542
- }
543
- self . src . push_str ( "\" ]\n " ) ;
537
+ None => format ! ( "{}{}" , self . opts. symbol_namespace, name_mangled) ,
538
+ } ;
539
+
540
+ self . src . push_str ( & format ! ( "#[export_name = \" {name}\" ]\n " ) ) ;
544
541
self . src . push_str ( "unsafe extern \" C\" fn __wit_bindgen_" ) ;
545
542
self . src . push_str ( & iface_name) ;
546
543
self . src . push_str ( "_" ) ;
547
- self . src . push_str ( & func . name . to_snake_case ( ) ) ;
544
+ self . src . push_str ( & name_snake ) ;
548
545
self . src . push_str ( "(" ) ;
549
546
let sig = iface. wasm_signature ( AbiVariant :: GuestExport , func) ;
550
547
let mut params = Vec :: new ( ) ;
@@ -594,6 +591,37 @@ impl Generator for RustWasm {
594
591
self . src . push_str ( & String :: from ( src) ) ;
595
592
self . src . push_str ( "}\n " ) ;
596
593
594
+ if iface. guest_export_needs_post_return ( func) {
595
+ self . src . push_str ( & format ! (
596
+ "#[export_name = \" {}cabi_post_{}\" ]\n " ,
597
+ self . opts. symbol_namespace, func. name,
598
+ ) ) ;
599
+ self . src . push_str ( & format ! (
600
+ "unsafe extern \" C\" fn __wit_bindgen_{iface_name}_{name_snake}_post_return("
601
+ ) ) ;
602
+ let mut params = Vec :: new ( ) ;
603
+ for ( i, result) in sig. results . iter ( ) . enumerate ( ) {
604
+ let name = format ! ( "arg{}" , i) ;
605
+ self . src . push_str ( & name) ;
606
+ self . src . push_str ( ": " ) ;
607
+ self . wasm_type ( * result) ;
608
+ self . src . push_str ( ", " ) ;
609
+ params. push ( name) ;
610
+ }
611
+ self . src . push_str ( ") {\n " ) ;
612
+
613
+ let mut f = FunctionBindgen :: new ( self , params) ;
614
+ iface. post_return ( func, & mut f) ;
615
+ let FunctionBindgen {
616
+ needs_cleanup_list,
617
+ src,
618
+ ..
619
+ } = f;
620
+ assert ! ( !needs_cleanup_list) ;
621
+ self . src . push_str ( & String :: from ( src) ) ;
622
+ self . src . push_str ( "}\n " ) ;
623
+ }
624
+
597
625
let prev = mem:: take ( & mut self . src ) ;
598
626
self . in_trait = true ;
599
627
let mut sig = FnSig :: default ( ) ;
@@ -1290,10 +1318,7 @@ impl Bindgen for FunctionBindgen<'_> {
1290
1318
results. push ( len) ;
1291
1319
}
1292
1320
1293
- Instruction :: ListCanonLift { free, .. } => {
1294
- // This only happens when we're receiving a list from the
1295
- // outside world, so `free` should always be `Some`.
1296
- assert ! ( free. is_some( ) ) ;
1321
+ Instruction :: ListCanonLift { .. } => {
1297
1322
let tmp = self . tmp ( ) ;
1298
1323
let len = format ! ( "len{}" , tmp) ;
1299
1324
self . push_str ( & format ! ( "let {} = {} as usize;\n " , len, operands[ 1 ] ) ) ;
@@ -1324,10 +1349,7 @@ impl Bindgen for FunctionBindgen<'_> {
1324
1349
results. push ( len) ;
1325
1350
}
1326
1351
1327
- Instruction :: StringLift { free, .. } => {
1328
- // This only happens when we're receiving a string from the
1329
- // outside world, so `free` should always be `Some`.
1330
- assert ! ( free. is_some( ) ) ;
1352
+ Instruction :: StringLift => {
1331
1353
let tmp = self . tmp ( ) ;
1332
1354
let len = format ! ( "len{}" , tmp) ;
1333
1355
self . push_str ( & format ! ( "let {} = {} as usize;\n " , len, operands[ 1 ] ) ) ;
@@ -1383,10 +1405,7 @@ impl Bindgen for FunctionBindgen<'_> {
1383
1405
}
1384
1406
}
1385
1407
1386
- Instruction :: ListLift { element, free, .. } => {
1387
- // This only happens when we're receiving a list from the
1388
- // outside world, so `free` should always be `Some`.
1389
- assert ! ( free. is_some( ) ) ;
1408
+ Instruction :: ListLift { element, .. } => {
1390
1409
let body = self . blocks . pop ( ) . unwrap ( ) ;
1391
1410
let tmp = self . tmp ( ) ;
1392
1411
let size = self . gen . sizes . size ( element) ;
@@ -1421,7 +1440,7 @@ impl Bindgen for FunctionBindgen<'_> {
1421
1440
self . push_str ( "}\n " ) ;
1422
1441
results. push ( result) ;
1423
1442
self . push_str ( & format ! (
1424
- "if {len} != 0 {{ \n std::alloc ::dealloc({base} as *mut _, std::alloc::Layout::from_size_align_unchecked(( {len} as usize) * {size}, {align})); \n }} \n " ,
1443
+ "wit_bindgen_guest_rust::rt ::dealloc({base}, ( {len} as usize) * {size}, {align}); \n " ,
1425
1444
) ) ;
1426
1445
}
1427
1446
@@ -1575,16 +1594,72 @@ impl Bindgen for FunctionBindgen<'_> {
1575
1594
}
1576
1595
1577
1596
Instruction :: Malloc { .. } => unimplemented ! ( ) ,
1578
- Instruction :: Free {
1579
- free : _,
1580
- size,
1581
- align,
1582
- } => {
1597
+
1598
+ Instruction :: GuestDeallocate { size, align } => {
1583
1599
self . push_str ( & format ! (
1584
- "wit_bindgen_guest_rust::rt::canonical_abi_free ({} as *mut u8 , {}, {});\n " ,
1600
+ "wit_bindgen_guest_rust::rt::dealloc ({}, {}, {});\n " ,
1585
1601
operands[ 0 ] , size, align
1586
1602
) ) ;
1587
1603
}
1604
+
1605
+ Instruction :: GuestDeallocateString => {
1606
+ self . push_str ( & format ! (
1607
+ "wit_bindgen_guest_rust::rt::dealloc({}, ({}) as usize, 1);\n " ,
1608
+ operands[ 0 ] , operands[ 1 ] ,
1609
+ ) ) ;
1610
+ }
1611
+
1612
+ Instruction :: GuestDeallocateVariant { blocks } => {
1613
+ let max = blocks - 1 ;
1614
+ let blocks = self
1615
+ . blocks
1616
+ . drain ( self . blocks . len ( ) - blocks..)
1617
+ . collect :: < Vec < _ > > ( ) ;
1618
+ let op0 = & operands[ 0 ] ;
1619
+ self . src . push_str ( & format ! ( "match {op0} {{\n " ) ) ;
1620
+ for ( i, block) in blocks. into_iter ( ) . enumerate ( ) {
1621
+ let pat = if i == max {
1622
+ String :: from ( "_" )
1623
+ } else {
1624
+ i. to_string ( )
1625
+ } ;
1626
+ self . src . push_str ( & format ! ( "{pat} => {block},\n " ) ) ;
1627
+ }
1628
+ self . src . push_str ( "}\n " ) ;
1629
+ }
1630
+
1631
+ Instruction :: GuestDeallocateList { element } => {
1632
+ let body = self . blocks . pop ( ) . unwrap ( ) ;
1633
+ let tmp = self . tmp ( ) ;
1634
+ let size = self . gen . sizes . size ( element) ;
1635
+ let align = self . gen . sizes . align ( element) ;
1636
+ let len = format ! ( "len{tmp}" ) ;
1637
+ let base = format ! ( "base{tmp}" ) ;
1638
+ self . push_str ( & format ! (
1639
+ "let {base} = {operand0};\n " ,
1640
+ operand0 = operands[ 0 ]
1641
+ ) ) ;
1642
+ self . push_str ( & format ! (
1643
+ "let {len} = {operand1};\n " ,
1644
+ operand1 = operands[ 1 ]
1645
+ ) ) ;
1646
+
1647
+ if body != "()" {
1648
+ self . push_str ( "for i in 0.." ) ;
1649
+ self . push_str ( & len) ;
1650
+ self . push_str ( " {\n " ) ;
1651
+ self . push_str ( "let base = " ) ;
1652
+ self . push_str ( & base) ;
1653
+ self . push_str ( " + i *" ) ;
1654
+ self . push_str ( & size. to_string ( ) ) ;
1655
+ self . push_str ( ";\n " ) ;
1656
+ self . push_str ( & body) ;
1657
+ self . push_str ( "\n }\n " ) ;
1658
+ }
1659
+ self . push_str ( & format ! (
1660
+ "wit_bindgen_guest_rust::rt::dealloc({base}, ({len} as usize) * {size}, {align});\n " ,
1661
+ ) ) ;
1662
+ }
1588
1663
}
1589
1664
}
1590
1665
}
0 commit comments