@@ -1011,6 +1011,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
10111011 results : block_results,
10121012 element : block_element,
10131013 base,
1014+ ..
10141015 } = self . blocks . pop ( ) . unwrap ( ) ;
10151016 assert ! ( block_results. is_empty( ) ) ;
10161017
@@ -1414,6 +1415,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
14141415 results : block_results,
14151416 base,
14161417 element : _,
1418+ ..
14171419 } = self . blocks . pop ( ) . unwrap ( ) ;
14181420 assert ! ( block_results. is_empty( ) ) ;
14191421
@@ -1651,18 +1653,193 @@ impl Bindgen for FunctionBindgen<'_, '_> {
16511653 self . interface_gen . csharp_gen . needs_async_support = true ;
16521654 }
16531655
1656+ Instruction :: MapLower {
1657+ key,
1658+ value,
1659+ realloc,
1660+ } => {
1661+ let Block {
1662+ body,
1663+ results : block_results,
1664+ base,
1665+ map_key,
1666+ map_value,
1667+ ..
1668+ } = self . blocks . pop ( ) . unwrap ( ) ;
1669+ assert ! ( block_results. is_empty( ) ) ;
1670+
1671+ let map = & operands[ 0 ] ;
1672+ let entry = self
1673+ . interface_gen
1674+ . csharp_gen
1675+ . sizes
1676+ . record ( [ * key, * value] . iter ( ) . copied ( ) ) ;
1677+ let size = entry. size . size_wasm32 ( ) ;
1678+ let align = entry. align . align_wasm32 ( ) ;
1679+ let key_ty = self . interface_gen . type_name_with_qualifier ( key, true ) ;
1680+ let value_ty = self . interface_gen . type_name_with_qualifier ( value, true ) ;
1681+
1682+ let index = self . locals . tmp ( "index" ) ;
1683+ let address = self . locals . tmp ( "address" ) ;
1684+ let buffer_size = self . locals . tmp ( "bufferSize" ) ;
1685+ let entry_var = self . locals . tmp ( "entry" ) ;
1686+
1687+ let ( array_size, element_type) =
1688+ crate :: world_generator:: dotnet_aligned_array ( size, align) ;
1689+ let ret_area = self . locals . tmp ( "retArea" ) ;
1690+
1691+ let array_size = if align > 1 {
1692+ format ! ( "{array_size} * {map}.Count + 1" )
1693+ } else {
1694+ format ! ( "{array_size} * {map}.Count" )
1695+ } ;
1696+
1697+ match realloc {
1698+ None => {
1699+ self . needs_cleanup = true ;
1700+ self . interface_gen . csharp_gen . needs_align_stack_ptr = true ;
1701+ uwrite ! (
1702+ self . src,
1703+ "
1704+ void* {address};
1705+ if (({size} * {map}.Count) < 1024) {{
1706+ var {ret_area} = stackalloc {element_type}[{array_size}];
1707+ {address} = MemoryHelper.AlignStackPtr({ret_area}, {align});
1708+ }}
1709+ else
1710+ {{
1711+ var {buffer_size} = {size} * (nuint){map}.Count;
1712+ {address} = global::System.Runtime.InteropServices.NativeMemory.AlignedAlloc({buffer_size}, {align});
1713+ cleanups.Add(() => global::System.Runtime.InteropServices.NativeMemory.AlignedFree({address}));
1714+ }}
1715+ "
1716+ ) ;
1717+ }
1718+ Some ( _) => {
1719+ uwrite ! (
1720+ self . src,
1721+ "
1722+ var {buffer_size} = {size} * (nuint){map}.Count;
1723+ void* {address} = global::System.Runtime.InteropServices.NativeMemory.AlignedAlloc({buffer_size}, {align});
1724+ "
1725+ ) ;
1726+ }
1727+ }
1728+
1729+ uwrite ! (
1730+ self . src,
1731+ "
1732+ int {index} = 0;
1733+ foreach (var {entry_var} in {map}) {{
1734+ {key_ty} {map_key} = {entry_var}.Key;
1735+ {value_ty} {map_value} = {entry_var}.Value;
1736+ int {base} = (int){address} + ({index} * {size});
1737+ {body}
1738+ ++{index};
1739+ }}
1740+ "
1741+ ) ;
1742+
1743+ results. push ( format ! ( "(int){address}" ) ) ;
1744+ results. push ( format ! ( "{map}.Count" ) ) ;
1745+ }
1746+
1747+ Instruction :: MapLift { key, value, .. } => {
1748+ let Block {
1749+ body,
1750+ results : block_results,
1751+ base,
1752+ ..
1753+ } = self . blocks . pop ( ) . unwrap ( ) ;
1754+ let address = & operands[ 0 ] ;
1755+ let length = & operands[ 1 ] ;
1756+ let map = self . locals . tmp ( "map" ) ;
1757+ let key_ty = self . interface_gen . type_name_with_qualifier ( key, true ) ;
1758+ let value_ty = self . interface_gen . type_name_with_qualifier ( value, true ) ;
1759+ let entry = self
1760+ . interface_gen
1761+ . csharp_gen
1762+ . sizes
1763+ . record ( [ * key, * value] . iter ( ) . copied ( ) ) ;
1764+ let size = entry. size . size_wasm32 ( ) ;
1765+ let index = self . locals . tmp ( "index" ) ;
1766+
1767+ let body_key = & block_results[ 0 ] ;
1768+ let body_value = & block_results[ 1 ] ;
1769+
1770+ uwrite ! (
1771+ self . src,
1772+ "
1773+ var {map} = new global::System.Collections.Generic.Dictionary<{key_ty}, {value_ty}>((int){length});
1774+ for (int {index} = 0; {index} < {length}; ++{index}) {{
1775+ nint {base} = {address} + ({index} * {size});
1776+ {body}
1777+ {map}[{body_key}] = {body_value};
1778+ }}
1779+
1780+ if ({length} > 0) {{
1781+ global::System.Runtime.InteropServices.NativeMemory.Free((void*){address});
1782+ }}
1783+ "
1784+ ) ;
1785+
1786+ results. push ( map) ;
1787+ }
1788+
1789+ Instruction :: IterMapKey { .. } => {
1790+ results. push ( self . block_storage . last ( ) . unwrap ( ) . map_key . clone ( ) )
1791+ }
1792+
1793+ Instruction :: IterMapValue { .. } => {
1794+ results. push ( self . block_storage . last ( ) . unwrap ( ) . map_value . clone ( ) )
1795+ }
1796+
1797+ Instruction :: GuestDeallocateMap { key, value } => {
1798+ let Block {
1799+ body,
1800+ results : block_results,
1801+ base,
1802+ ..
1803+ } = self . blocks . pop ( ) . unwrap ( ) ;
1804+ assert ! ( block_results. is_empty( ) ) ;
1805+
1806+ let address = & operands[ 0 ] ;
1807+ let length = & operands[ 1 ] ;
1808+ let entry = self
1809+ . interface_gen
1810+ . csharp_gen
1811+ . sizes
1812+ . record ( [ * key, * value] . iter ( ) . copied ( ) ) ;
1813+ let size = entry. size . size_wasm32 ( ) ;
1814+
1815+ if !body. trim ( ) . is_empty ( ) {
1816+ let index = self . locals . tmp ( "index" ) ;
1817+
1818+ uwrite ! (
1819+ self . src,
1820+ "
1821+ for (int {index} = 0; {index} < {length}; ++{index}) {{
1822+ int {base} = (int){address} + ({index} * {size});
1823+ {body}
1824+ }}
1825+ "
1826+ ) ;
1827+ }
1828+
1829+ uwriteln ! (
1830+ self . src,
1831+ r#"global::System.Runtime.InteropServices.NativeMemory.Free((void*){});"# ,
1832+ operands[ 0 ]
1833+ ) ;
1834+ }
1835+
16541836 Instruction :: ErrorContextLower { .. }
16551837 | Instruction :: ErrorContextLift { .. }
16561838 | Instruction :: DropHandle { .. }
16571839 | Instruction :: FixedLengthListLift { .. }
16581840 | Instruction :: FixedLengthListLower { .. }
16591841 | Instruction :: FixedLengthListLowerToMemory { .. }
1660- | Instruction :: FixedLengthListLiftFromMemory { .. }
1661- | Instruction :: MapLower { .. }
1662- | Instruction :: MapLift { .. }
1663- | Instruction :: IterMapKey { .. }
1664- | Instruction :: IterMapValue { .. }
1665- | Instruction :: GuestDeallocateMap { .. } => {
1842+ | Instruction :: FixedLengthListLiftFromMemory { .. } => {
16661843 dbg ! ( inst) ;
16671844 todo ! ( )
16681845 }
@@ -1738,6 +1915,8 @@ impl Bindgen for FunctionBindgen<'_, '_> {
17381915 body : mem:: take ( & mut self . src ) ,
17391916 element : self . locals . tmp ( "element" ) ,
17401917 base : self . locals . tmp ( "basePtr" ) ,
1918+ map_key : self . locals . tmp ( "mapKey" ) ,
1919+ map_value : self . locals . tmp ( "mapValue" ) ,
17411920 } ) ;
17421921
17431922 self . is_block = true ;
@@ -1748,13 +1927,17 @@ impl Bindgen for FunctionBindgen<'_, '_> {
17481927 body,
17491928 element,
17501929 base,
1930+ map_key,
1931+ map_value,
17511932 } = self . block_storage . pop ( ) . unwrap ( ) ;
17521933
17531934 self . blocks . push ( Block {
17541935 body : mem:: replace ( & mut self . src , body) ,
17551936 results : mem:: take ( operands) ,
17561937 element,
17571938 base,
1939+ map_key,
1940+ map_value,
17581941 } ) ;
17591942 self . is_block = false ;
17601943 }
@@ -1827,6 +2010,8 @@ struct Block {
18272010 results : Vec < String > ,
18282011 element : String ,
18292012 base : String ,
2013+ map_key : String ,
2014+ map_value : String ,
18302015}
18312016
18322017struct Fixed {
@@ -1838,6 +2023,8 @@ struct BlockStorage {
18382023 body : String ,
18392024 element : String ,
18402025 base : String ,
2026+ map_key : String ,
2027+ map_value : String ,
18412028}
18422029
18432030#[ derive( Clone ) ]
0 commit comments