@@ -519,6 +519,8 @@ impl WorldGenerator for CSharp {
519519 if self . needs_export_return_area {
520520 let mut ret_area_str = String :: new ( ) ;
521521
522+ let ( array_size, element_type) =
523+ dotnet_aligned_array ( self . return_area_size , self . return_area_align ) ;
522524 uwrite ! (
523525 ret_area_str,
524526 "
@@ -528,23 +530,22 @@ impl WorldGenerator for CSharp {
528530 [StructLayout(LayoutKind.Sequential, Pack = {1})]
529531 internal struct ReturnArea
530532 {{
531- private byte buffer;
533+ private {2} buffer;
532534
533- internal unsafe int AddressOfReturnArea()
535+ internal unsafe nint AddressOfReturnArea()
534536 {{
535- fixed(byte* ptr = &buffer)
536- {{
537- return (int)ptr;
538- }}
537+ return (nint)Unsafe.AsPointer(ref buffer);
539538 }}
540539 }}
541540
542541 [ThreadStatic]
542+ [FixedAddressValueType]
543543 internal static ReturnArea returnArea = default;
544544 }}
545545 " ,
546- self . return_area_size ,
546+ array_size ,
547547 self . return_area_align,
548+ element_type
548549 ) ;
549550
550551 src. push_str ( & ret_area_str) ;
@@ -984,8 +985,6 @@ impl InterfaceGenerator<'_> {
984985 ) ;
985986
986987 let src = bindgen. src ;
987- let import_return_pointer_area_size = bindgen. import_return_pointer_area_size ;
988- let import_return_pointer_area_align = bindgen. import_return_pointer_area_align ;
989988
990989 let params = func
991990 . params
@@ -1022,28 +1021,6 @@ impl InterfaceGenerator<'_> {
10221021 "#
10231022 ) ;
10241023
1025- if import_return_pointer_area_size > 0 {
1026- uwrite ! (
1027- target,
1028- r#"
1029- [InlineArray({import_return_pointer_area_size})]
1030- [StructLayout(LayoutKind.Sequential, Pack = {import_return_pointer_area_align})]
1031- internal struct ImportReturnArea
1032- {{
1033- private byte buffer;
1034-
1035- internal unsafe int AddressOfReturnArea()
1036- {{
1037- fixed(byte* ptr = &buffer)
1038- {{
1039- return (int)ptr;
1040- }}
1041- }}
1042- }}
1043- "# ,
1044- )
1045- }
1046-
10471024 uwrite ! (
10481025 target,
10491026 r#"
@@ -1862,6 +1839,7 @@ struct FunctionBindgen<'a, 'b> {
18621839 cleanup : Vec < Cleanup > ,
18631840 import_return_pointer_area_size : usize ,
18641841 import_return_pointer_area_align : usize ,
1842+ fixed : usize , // Number of `fixed` blocks that need to be closed.
18651843 resource_drops : Vec < ( String , String ) > ,
18661844}
18671845
@@ -1892,6 +1870,7 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
18921870 cleanup : Vec :: new ( ) ,
18931871 import_return_pointer_area_size : 0 ,
18941872 import_return_pointer_area_align : 0 ,
1873+ fixed : 0 ,
18951874 resource_drops : Vec :: new ( ) ,
18961875 }
18971876 }
@@ -2468,7 +2447,6 @@ impl Bindgen for FunctionBindgen<'_, '_> {
24682447
24692448 let list = & operands[ 0 ] ;
24702449 let size = self . gen . gen . sizes . size ( element) ;
2471- let _align = self . gen . gen . sizes . align ( element) ;
24722450 let ty = self . gen . type_name_with_qualifier ( element, true ) ;
24732451 let index = self . locals . tmp ( "index" ) ;
24742452
@@ -2513,7 +2491,6 @@ impl Bindgen for FunctionBindgen<'_, '_> {
25132491 let array = self . locals . tmp ( "array" ) ;
25142492 let ty = self . gen . type_name_with_qualifier ( element, true ) ;
25152493 let size = self . gen . gen . sizes . size ( element) ;
2516- let _align = self . gen . gen . sizes . align ( element) ;
25172494 let index = self . locals . tmp ( "index" ) ;
25182495
25192496 let result = match & block_results[ ..] {
@@ -2526,7 +2503,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
25262503 "
25272504 var {array} = new List<{ty}>({length});
25282505 for (int {index} = 0; {index} < {length}; ++{index}) {{
2529- int {base} = {address} + ({index} * {size});
2506+ nint {base} = {address} + ({index} * {size});
25302507 {body}
25312508 {array}.Add({result});
25322509 }}
@@ -2651,6 +2628,11 @@ impl Bindgen for FunctionBindgen<'_, '_> {
26512628 uwriteln ! ( self . src, "return ({results});" )
26522629 }
26532630 }
2631+
2632+ // Close all the fixed blocks.
2633+ for _ in 0 ..self . fixed {
2634+ uwriteln ! ( self . src, "}}" ) ;
2635+ }
26542636 }
26552637 }
26562638
@@ -2780,19 +2762,30 @@ impl Bindgen for FunctionBindgen<'_, '_> {
27802762 // their return area to be live until the post-return call.
27812763 match self . gen . direction {
27822764 Direction :: Import => {
2783- let ret_area = self . locals . tmp ( "retArea" ) ;
2784- let name = self . func_name . to_upper_camel_case ( ) ;
27852765 self . import_return_pointer_area_size =
27862766 self . import_return_pointer_area_size . max ( size) ;
27872767 self . import_return_pointer_area_align =
27882768 self . import_return_pointer_area_align . max ( align) ;
2769+ let ( array_size, element_type) = dotnet_aligned_array (
2770+ self . import_return_pointer_area_size ,
2771+ self . import_return_pointer_area_align ,
2772+ ) ;
2773+ let ret_area = self . locals . tmp ( "retArea" ) ;
2774+ let ret_area_byte0 = self . locals . tmp ( "retAreaByte0" ) ;
27892775 uwrite ! (
27902776 self . src,
27912777 "
2792- var {ret_area} = new {name}WasmInterop.ImportReturnArea();
2793- var {ptr} = {ret_area}.AddressOfReturnArea();
2794- "
2778+ var {2} = new {0}[{1}];
2779+ fixed ({0}* {3} = &{2}[0])
2780+ {{
2781+ var {ptr} = (nint){3};
2782+ " ,
2783+ element_type,
2784+ array_size,
2785+ ret_area,
2786+ ret_area_byte0
27952787 ) ;
2788+ self . fixed = self . fixed + 1 ;
27962789
27972790 return format ! ( "{ptr}" ) ;
27982791 }
@@ -2857,6 +2850,26 @@ impl Bindgen for FunctionBindgen<'_, '_> {
28572850 }
28582851}
28592852
2853+ // We cant use "StructLayout.Pack" as dotnet will use the minimum of the type and the "Pack" field,
2854+ // so for byte it would always use 1 regardless of the "Pack".
2855+ fn dotnet_aligned_array ( array_size : usize , required_alignment : usize ) -> ( usize , String ) {
2856+ match required_alignment {
2857+ 1 => {
2858+ return ( array_size, "byte" . to_owned ( ) ) ;
2859+ }
2860+ 2 => {
2861+ return ( ( array_size + 1 ) / 2 , "ushort" . to_owned ( ) ) ;
2862+ }
2863+ 4 => {
2864+ return ( ( array_size + 3 ) / 4 , "uint" . to_owned ( ) ) ;
2865+ }
2866+ 8 => {
2867+ return ( ( array_size + 7 ) / 8 , "ulong" . to_owned ( ) ) ;
2868+ }
2869+ _ => todo ! ( "unsupported return_area_align {}" , required_alignment) ,
2870+ }
2871+ }
2872+
28602873fn perform_cast ( op : & String , cast : & Bitcast ) -> String {
28612874 match cast {
28622875 Bitcast :: I32ToF32 => format ! ( "BitConverter.Int32BitsToSingle({op})" ) ,
@@ -2900,7 +2913,7 @@ fn wasm_type(ty: WasmType) -> &'static str {
29002913 WasmType :: I64 => "long" ,
29012914 WasmType :: F32 => "float" ,
29022915 WasmType :: F64 => "double" ,
2903- WasmType :: Pointer => "int " ,
2916+ WasmType :: Pointer => "nint " ,
29042917 WasmType :: PointerOrI64 => "long" ,
29052918 WasmType :: Length => "int" ,
29062919 }
0 commit comments