diff --git a/eng/native/configureplatform.cmake b/eng/native/configureplatform.cmake
index 2ccced093f6b38..a9ddb0d18aec41 100644
--- a/eng/native/configureplatform.cmake
+++ b/eng/native/configureplatform.cmake
@@ -221,10 +221,10 @@ if(CLR_CMAKE_HOST_OS STREQUAL emscripten)
set(CLR_CMAKE_HOST_BROWSER 1)
endif(CLR_CMAKE_HOST_OS STREQUAL emscripten)
-if(CLR_CMAKE_TARGET_OS STREQUAL wasi)
+if(CLR_CMAKE_HOST_OS STREQUAL wasi)
set(CLR_CMAKE_HOST_WASI 1)
set(CLR_CMAKE_HOST_UNIX 1)
-endif(CLR_CMAKE_TARGET_OS STREQUAL wasi)
+endif(CLR_CMAKE_HOST_OS STREQUAL wasi)
#--------------------------------------------
# This repo builds two set of binaries
diff --git a/src/coreclr/build-runtime.cmd b/src/coreclr/build-runtime.cmd
index 4374e13face5ae..77788bbf6c21ff 100644
--- a/src/coreclr/build-runtime.cmd
+++ b/src/coreclr/build-runtime.cmd
@@ -281,6 +281,9 @@ if "%__TargetOS%"=="android" (
if "%__TargetOS%"=="browser" (
set __CrossTarget=1
)
+if "%__TargetOS%"=="wasi" (
+ set __CrossTarget=1
+)
if %__CrossTarget% EQU 0 (
call "%__RepoRootDir%\eng\native\version\copy_version_files.cmd"
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/ILCompiler.ReadyToRun.Tests.csproj b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/ILCompiler.ReadyToRun.Tests.csproj
index 1c77956d8bbe6b..13811c03632ff8 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/ILCompiler.ReadyToRun.Tests.csproj
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/ILCompiler.ReadyToRun.Tests.csproj
@@ -37,6 +37,14 @@
+
+
+
+
+
+
ThunkShapes()
+ {
+ // (description, isStatic, expected signature key)
+ TheoryData data = new()
+ {
+ { "void(int)", true, "vip" },
+ { "int(int)", false, "iTip" },
+ { "long(double)", true, "ldp" },
+ { "int(float, double, long)", false, "iTfdlp" },
+ { "void()", false, "vTp" },
+ // Struct returns: the shape both encoders previously disagreed on.
+ { "S8()", true, "S8p" },
+ { "S8(int)", false, "S8Tip" },
+ { "S16(long, int)", true, "S16lip" },
+ { "S12(S12, int)", false, "S12TS12ip" },
+ { "void(S8)", false, "vTS8p" },
+ };
+
+ return data;
+ }
+
+ ///
+ /// The R2R-to-interpreter thunks are written by the WasmAppBuilder generator but called by code
+ /// crossgen2 emits, so the two have to agree on the wasm signature behind every key. This checks
+ /// arity and types: a missing hidden return buffer — which is what returning the struct by value
+ /// produces, since the compiler then inserts its own pointer ahead of the stack pointer — or a
+ /// wrong scalar width shows up here. It cannot see two same-typed parameters swapped;
+ /// covers the order.
+ ///
+ [Theory]
+ [MemberData(nameof(ThunkShapes))]
+ public void GeneratedThunkMatchesLoweredWasmSignature(string description, bool isStatic, string expectedKey)
+ {
+ _output.WriteLine($"{description} => {expectedKey}");
+
+ ReadyToRunCompilerContext context = CreateWasmContext();
+ WasmSignature lowered = WasmLowering.GetSignature(MakeThunkSignature(context, description, isStatic), WasmLowering.LoweringFlags.None);
+
+ Assert.Equal(expectedKey, lowered.SignatureString);
+ Assert.Equal(lowered.FuncType.Params.Types.ToArray(), GetThunkWasmParameters(lowered.SignatureString));
+ }
+
+ ///
+ /// A generic context argument is an ordinary pointer slot that follows the return buffer, so it
+ /// encodes exactly like a leading int parameter and must lay out the same way.
+ ///
+ [Fact]
+ public void GenericContextArgumentFollowsTheReturnBuffer()
+ {
+ ReadyToRunCompilerContext context = CreateWasmContext();
+ MethodSignature signature = new(
+ MethodSignatureFlags.None,
+ genericParameterCount: 0,
+ returnType: MakeBlobOfSize(context, 8),
+ parameters: Array.Empty());
+
+ WasmSignature lowered = WasmLowering.GetSignature(signature, WasmLowering.LoweringFlags.HasGenericContextArg);
+
+ Assert.Equal("S8Tip", lowered.SignatureString);
+ Assert.Equal(lowered.FuncType.Params.Types.ToArray(), GetThunkWasmParameters(lowered.SignatureString));
+ }
+
+ public static TheoryData ThunkParameterOrder()
+ {
+ // Transcribed from WasmR2RToInterpreterThunkNode.EmitCode, which stores 'this' from the
+ // local after the stack pointer and then reads the buffer from
+ // retBufLocalIndex = 1 + (hasThis ? 1 : 0). A generic context is an ordinary slot that
+ // follows the buffer, so it is spelled like any other argument here.
+ return new TheoryData
+ {
+ { Array.Empty(), true, new[] { "retBuf" } },
+ { new[] { "i" }, true, new[] { "retBuf", "arg0" } },
+ { new[] { "T" }, true, new[] { "arg0", "retBuf" } },
+ { new[] { "T", "i" }, true, new[] { "arg0", "retBuf", "arg1" } },
+ { new[] { "T", "i", "S8" }, true, new[] { "arg0", "retBuf", "arg1", "arg2" } },
+ { new[] { "T", "i" }, false, new[] { "arg0", "arg1" } },
+ { new[] { "i", "l" }, false, new[] { "arg0", "arg1" } },
+ };
+ }
+
+ ///
+ /// The transposition that shipped broken, and the reason it needs its own test: for an instance
+ /// method the hidden return buffer follows this, and both are i32, so getting the
+ /// order wrong leaves the wasm type sequence unchanged. Comparing lowered parameter types cannot
+ /// see it — only the positions can.
+ ///
+ [Theory]
+ [MemberData(nameof(ThunkParameterOrder))]
+ public void ThunkParametersFollowCrossgen2Order(string[] args, bool isStructReturn, string[] expectedNames)
+ {
+ Assert.Equal(
+ expectedNames,
+ PortableEntryPointThunkSignature.GetDeclaredParameters(args, isStructReturn).Select(static p => p.Name));
+ }
+
+ ///
+ /// Builds the signature named by in .
+ ///
+ private static MethodSignature MakeThunkSignature(ReadyToRunCompilerContext context, string description, bool isStatic)
+ {
+ TypeDesc Int32() => context.GetWellKnownType(WellKnownType.Int32);
+
+ (TypeDesc Return, TypeDesc[] Parameters) shape = description switch
+ {
+ "void(int)" => (context.GetWellKnownType(WellKnownType.Void), new[] { Int32() }),
+ "int(int)" => (Int32(), new[] { Int32() }),
+ "long(double)" => (context.GetWellKnownType(WellKnownType.Int64), new[] { context.GetWellKnownType(WellKnownType.Double) }),
+ "int(float, double, long)" => (Int32(), new[]
+ {
+ context.GetWellKnownType(WellKnownType.Single),
+ context.GetWellKnownType(WellKnownType.Double),
+ context.GetWellKnownType(WellKnownType.Int64),
+ }),
+ "void()" => (context.GetWellKnownType(WellKnownType.Void), Array.Empty()),
+ "S8()" => (MakeBlobOfSize(context, 8), Array.Empty()),
+ "S8(int)" => (MakeBlobOfSize(context, 8), new[] { Int32() }),
+ "S16(long, int)" => (MakeBlobOfSize(context, 16), new[] { context.GetWellKnownType(WellKnownType.Int64), Int32() }),
+ "S12(S12, int)" => (MakeBlobOfSize(context, 12), new TypeDesc[] { MakeBlobOfSize(context, 12), Int32() }),
+ "void(S8)" => (context.GetWellKnownType(WellKnownType.Void), new TypeDesc[] { MakeBlobOfSize(context, 8) }),
+ _ => throw new ArgumentOutOfRangeException(nameof(description), description, null),
+ };
+
+ return new MethodSignature(
+ isStatic ? MethodSignatureFlags.Static : MethodSignatureFlags.None,
+ genericParameterCount: 0,
+ returnType: shape.Return,
+ parameters: shape.Parameters);
+ }
+
+ ///
+ /// A multi-field struct of the given size. It needs more than one field: a single-field struct
+ /// is lowered to the field's own type and would never reach the S<N> encoding.
+ ///
+ private static DefType MakeBlobOfSize(ReadyToRunCompilerContext context, int size)
+ {
+ TypeDesc int32 = context.GetWellKnownType(WellKnownType.Int32);
+ TypeDesc int64 = context.GetWellKnownType(WellKnownType.Int64);
+
+ DefType result = size switch
+ {
+ 8 => MakeValueTuple(context, int32, int32),
+ 12 => MakeValueTuple(context, int32, int32, int32),
+ 16 => MakeValueTuple(context, int64, int64),
+ _ => throw new ArgumentOutOfRangeException(nameof(size), size, null),
+ };
+
+ Assert.Equal(size, result.InstanceFieldSize.AsInt);
+ return result;
+ }
+
+ ///
+ /// The wasm parameters of the thunk the generator emits for .
+ /// The stack pointer comes from the WASM_CALLABLE_FUNC macro and the portable entrypoint is
+ /// appended after the declared arguments, so neither is part of the generator's own list.
+ ///
+ private static List GetThunkWasmParameters(string signatureKey)
+ {
+ List tokens = SignatureMapper.ParseSignatureTokens(signatureKey);
+ string returnToken = tokens[0];
+
+ Assert.Equal("p", tokens[tokens.Count - 1]);
+ tokens.RemoveAt(tokens.Count - 1);
+ List args = tokens.GetRange(1, tokens.Count - 1);
+
+ List parameters = new() { WasmValueType.I32 }; // callersStackPointer
+ foreach (PortableEntryPointThunkSignature.Parameter parameter in
+ PortableEntryPointThunkSignature.GetDeclaredParameters(args, PortableEntryPointThunkSignature.IsStructToken(returnToken)))
+ {
+ parameters.Add(NativeTypeToWasmType(parameter.NativeType));
+ }
+
+ parameters.Add(WasmValueType.I32); // portable entrypoint
+ return parameters;
+ }
+
+ ///
+ /// Maps a C type the generator emits onto the wasm type clang gives it on wasm32. Reading the
+ /// generator's own type strings, rather than re-deriving them from the signature, is what makes
+ /// this a check of the emitted thunk instead of a restatement of the encoding rules.
+ ///
+ private static WasmValueType NativeTypeToWasmType(string nativeType) => nativeType switch
+ {
+ "int32_t" or "int8_t*" or "PCODE" => WasmValueType.I32,
+ "int64_t" => WasmValueType.I64,
+ "float" => WasmValueType.F32,
+ "double" => WasmValueType.F64,
+ _ => throw new ArgumentOutOfRangeException(nameof(nativeType), nativeType, null),
+ };
+
private static DefType MakeValueTuple(ReadyToRunCompilerContext context, params TypeDesc[] fields) =>
((MetadataType)context.SystemModule.GetType(
"System"u8, System.Text.Encoding.UTF8.GetBytes($"ValueTuple`{fields.Length}")))
diff --git a/src/coreclr/vm/CMakeLists.txt b/src/coreclr/vm/CMakeLists.txt
index bcc0a0d6e791cc..aa6b9d10ffaff7 100644
--- a/src/coreclr/vm/CMakeLists.txt
+++ b/src/coreclr/vm/CMakeLists.txt
@@ -973,6 +973,11 @@ elseif(CLR_CMAKE_TARGET_ARCH_WASM)
else()
set(WASM_THUNK_SUBDIR browser)
endif()
+ # Unlike the other generated call helpers, the portable entrypoint thunks are not regenerated
+ # per app, so they belong in the shipped static library rather than in cee_wks_gen.
+ list(APPEND VM_SOURCES_WKS_ARCH
+ ${ARCH_SOURCES_DIR}/${WASM_THUNK_SUBDIR}/callhelpers-portable-entrypoints.cpp
+ )
set(VM_SOURCES_WKS_GEN
${ARCH_SOURCES_DIR}/${WASM_THUNK_SUBDIR}/callhelpers-interp-to-managed.cpp
${ARCH_SOURCES_DIR}/${WASM_THUNK_SUBDIR}/callhelpers-reverse.cpp
diff --git a/src/coreclr/vm/wasm/browser/callhelpers-interp-to-managed.cpp b/src/coreclr/vm/wasm/browser/callhelpers-interp-to-managed.cpp
index dc7af3ffa4ea3a..a82b48a6c00b7e 100644
--- a/src/coreclr/vm/wasm/browser/callhelpers-interp-to-managed.cpp
+++ b/src/coreclr/vm/wasm/browser/callhelpers-interp-to-managed.cpp
@@ -17,9 +17,83 @@
#define ARG_I64(i) (*(int64_t*)ARG_ADDR(i))
#define ARG_F32(i) (*(float*)ARG_ADDR(i))
#define ARG_F64(i) (*(double*)ARG_ADDR(i))
+typedef struct { char d[1]; } wasm_ret_S1;
+typedef struct { char d[8]; } wasm_ret_S8;
+typedef struct { char d[12]; } wasm_ret_S12;
+typedef struct { char d[16]; } wasm_ret_S16;
namespace
{
+ NOINLINE static void CallFunc_This_S12_I32_RetS12_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int8_t*, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int8_t*, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), pRet, ARG_IND(1), ARG_I32(3), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_S12_I32_RetS12_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int8_t*, int32_t, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int8_t*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), pRet, ARG_I32(1), ARG_IND(2), ARG_I32(4), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_I32_I32_RetS12_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int8_t*, int32_t, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int8_t*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), pRet, ARG_I32(1), ARG_I32(2), ARG_I32(3), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_I32_RetS12_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int8_t*, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int8_t*, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), pRet, ARG_I32(1), ARG_I32(2), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_RetS16_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int8_t*, PCODE) = *(void (**)(int*, int32_t, int8_t*, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), pRet, pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_L2_I32_RetS16_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int8_t*, int64_t, int64_t, int32_t, PCODE) = *(void (**)(int*, int8_t*, int64_t, int64_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, pRet, ARG_I64(0), ARG_I64(1), ARG_I32(2), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_RetS1_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int8_t*, PCODE) = *(void (**)(int*, int32_t, int8_t*, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), pRet, pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_I32_I32_RetS8_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int8_t*, int32_t, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int8_t*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), pRet, ARG_I32(1), ARG_I32(2), ARG_I32(3), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_RetS8_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int8_t*, int32_t, PCODE) = *(void (**)(int*, int32_t, int8_t*, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), pRet, ARG_I32(1), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_RetS8_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int8_t*, PCODE) = *(void (**)(int*, int32_t, int8_t*, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), pRet, pPortableEntryPoint);
+ }
+
NOINLINE static void CallFunc_F64_F64_F64_RetF64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
{
alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
@@ -166,6 +240,97 @@ namespace
*((int32_t*)pRet) = (*fptr)(ARG_IND(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5));
}
+ NOINLINE static void CallFunc_S8_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_IND(0), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_S12_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), ARG_I32(3), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_S12_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_S8_S8_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), ARG_IND(2), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_S8_I32_S8_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), ARG_I32(2), ARG_IND(3), ARG_I32(4), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_S8_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_S8_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), ARG_I32(2), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_S8_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_S12_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_IND(2), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_S8_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_IND(2), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), pPortableEntryPoint);
+ }
+
NOINLINE static void CallFunc_This_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
{
alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
@@ -180,6 +345,13 @@ namespace
*((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), pPortableEntryPoint);
}
+ NOINLINE static void CallFunc_F64_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, double, PCODE) = *(int32_t (**)(int*, double, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_F64(0), pPortableEntryPoint);
+ }
+
static void CallFunc_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet)
{
int32_t (*fptr)(int32_t) = (int32_t (*)(int32_t))pcode;
@@ -198,6 +370,13 @@ namespace
*((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_IND(1), ARG_I32(2), ARG_I32(3), ARG_I32(4));
}
+ NOINLINE static void CallFunc_I32_S8_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), pPortableEntryPoint);
+ }
+
static void CallFunc_I32_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet)
{
int32_t (*fptr)(int32_t, int32_t) = (int32_t (*)(int32_t, int32_t))pcode;
@@ -258,6 +437,20 @@ namespace
*((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5), ARG_I32(6), ARG_I32(7), ARG_I32(8), ARG_I32(9), ARG_I32(10), ARG_I32(11), ARG_I32(12), ARG_I32(13));
}
+ NOINLINE static void CallFunc_I32_I32_I32_I32_I32_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5), ARG_I32(6), ARG_I32(7), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_I32_I32_I32_I32_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5), ARG_I32(6), pPortableEntryPoint);
+ }
+
NOINLINE static void CallFunc_I32_I32_I32_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
{
alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
@@ -379,6 +572,13 @@ namespace
*((int64_t*)pRet) = (*fptr)();
}
+ NOINLINE static void CallFunc_F64_RetI64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int64_t (*fptr)(int*, double, PCODE) = *(int64_t (**)(int*, double, PCODE))(pPortableEntryPoint);
+ *((int64_t*)pRet) = (*fptr)(&framePointer, ARG_F64(0), pPortableEntryPoint);
+ }
+
static void CallFunc_I32_RetI64(PCODE pcode, int8_t* pArgs, int8_t* pRet)
{
int64_t (*fptr)(int32_t) = (int64_t (*)(int32_t))pcode;
@@ -510,6 +710,90 @@ namespace
(*fptr)(ARG_IND(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5), ARG_I32(6), ARG_I32(7), ARG_I32(8), ARG_I32(9), ARG_I32(10), ARG_I32(11));
}
+ NOINLINE static void CallFunc_This_S12_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_S32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_S8_S8_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), ARG_IND(2), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_S8_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), ARG_I32(2), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_S8_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_S8_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_IND(2), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_I32_S8_S8_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_IND(3), ARG_IND(4), ARG_I32(5), ARG_I32(6), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_I32_I32_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_I32_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), pPortableEntryPoint);
+ }
+
NOINLINE static void CallFunc_This_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
{
alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
@@ -627,6 +911,13 @@ namespace
(*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I64(4));
}
+ NOINLINE static void CallFunc_I32_I32_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), pPortableEntryPoint);
+ }
+
NOINLINE static void CallFunc_I32_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
{
alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
@@ -663,6 +954,16 @@ namespace
}
const StringToWasmSigThunk g_wasmThunks[] = {
+ { "MS12TS12ip", (void*)&CallFunc_This_S12_I32_RetS12_PE },
+ { "MS12TiS12ip", (void*)&CallFunc_This_I32_S12_I32_RetS12_PE },
+ { "MS12Tiiip", (void*)&CallFunc_This_I32_I32_I32_RetS12_PE },
+ { "MS12Tiip", (void*)&CallFunc_This_I32_I32_RetS12_PE },
+ { "MS16Tp", (void*)&CallFunc_This_RetS16_PE },
+ { "MS16l2ip", (void*)&CallFunc_L2_I32_RetS16_PE },
+ { "MS1Tp", (void*)&CallFunc_This_RetS1_PE },
+ { "MS8Tiiip", (void*)&CallFunc_This_I32_I32_I32_RetS8_PE },
+ { "MS8Tip", (void*)&CallFunc_This_I32_RetS8_PE },
+ { "MS8Tp", (void*)&CallFunc_This_RetS8_PE },
{ "Mddddp", (void*)&CallFunc_F64_F64_F64_RetF64_PE },
{ "Mdddp", (void*)&CallFunc_F64_F64_RetF64_PE },
{ "Mddip", (void*)&CallFunc_F64_I32_RetF64_PE },
@@ -686,11 +987,26 @@ const StringToWasmSigThunk g_wasmThunks[] = {
{ "MiS8iii", (void*)&CallFunc_S8_I32_I32_I32_RetI32 },
{ "MiS8iiii", (void*)&CallFunc_S8_I32_I32_I32_I32_RetI32 },
{ "MiS8iiiii", (void*)&CallFunc_S8_I32_I32_I32_I32_I32_RetI32 },
+ { "MiS8p", (void*)&CallFunc_S8_RetI32_PE },
+ { "MiTS12ip", (void*)&CallFunc_This_S12_I32_RetI32_PE },
+ { "MiTS12p", (void*)&CallFunc_This_S12_RetI32_PE },
+ { "MiTS8S8p", (void*)&CallFunc_This_S8_S8_RetI32_PE },
+ { "MiTS8iS8ip", (void*)&CallFunc_This_S8_I32_S8_I32_RetI32_PE },
+ { "MiTS8iiip", (void*)&CallFunc_This_S8_I32_I32_I32_RetI32_PE },
+ { "MiTS8ip", (void*)&CallFunc_This_S8_I32_RetI32_PE },
+ { "MiTS8p", (void*)&CallFunc_This_S8_RetI32_PE },
+ { "MiTiS12p", (void*)&CallFunc_This_I32_S12_RetI32_PE },
+ { "MiTiS8p", (void*)&CallFunc_This_I32_S8_RetI32_PE },
+ { "MiTiiiip", (void*)&CallFunc_This_I32_I32_I32_I32_RetI32_PE },
+ { "MiTiiip", (void*)&CallFunc_This_I32_I32_I32_RetI32_PE },
+ { "MiTiip", (void*)&CallFunc_This_I32_I32_RetI32_PE },
{ "MiTip", (void*)&CallFunc_This_I32_RetI32_PE },
{ "MiTp", (void*)&CallFunc_This_RetI32_PE },
+ { "Midp", (void*)&CallFunc_F64_RetI32_PE },
{ "Mii", (void*)&CallFunc_I32_RetI32 },
{ "MiiS8i", (void*)&CallFunc_I32_S8_I32_RetI32 },
{ "MiiS8iii", (void*)&CallFunc_I32_S8_I32_I32_I32_RetI32 },
+ { "MiiS8p", (void*)&CallFunc_I32_S8_RetI32_PE },
{ "Miii", (void*)&CallFunc_I32_I32_RetI32 },
{ "MiiiS8iiS8", (void*)&CallFunc_I32_I32_S8_I32_I32_S8_RetI32 },
{ "MiiiS8iiii", (void*)&CallFunc_I32_I32_S8_I32_I32_I32_I32_RetI32 },
@@ -701,6 +1017,8 @@ const StringToWasmSigThunk g_wasmThunks[] = {
{ "Miiiiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_RetI32 },
{ "Miiiiiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_I32_RetI32 },
{ "Miiiiiiiiiiiiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_RetI32 },
+ { "Miiiiiiiiip", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_I32_I32_RetI32_PE },
+ { "Miiiiiiiip", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_I32_RetI32_PE },
{ "Miiiiiiip", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_RetI32_PE },
{ "Miiiiiip", (void*)&CallFunc_I32_I32_I32_I32_I32_RetI32_PE },
{ "Miiiiip", (void*)&CallFunc_I32_I32_I32_I32_RetI32_PE },
@@ -720,6 +1038,7 @@ const StringToWasmSigThunk g_wasmThunks[] = {
{ "Milili", (void*)&CallFunc_I64_I32_I64_I32_RetI32 },
{ "Mip", (void*)&CallFunc_Void_RetI32_PE },
{ "Ml", (void*)&CallFunc_Void_RetI64 },
+ { "Mldp", (void*)&CallFunc_F64_RetI64_PE },
{ "Mli", (void*)&CallFunc_I32_RetI64 },
{ "Mliii", (void*)&CallFunc_I32_I32_I32_RetI64 },
{ "Mliiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_RetI64 },
@@ -741,6 +1060,18 @@ const StringToWasmSigThunk g_wasmThunks[] = {
{ "MvS8iiiii", (void*)&CallFunc_S8_I32_I32_I32_I32_I32_RetVoid },
{ "MvS8iiiiii", (void*)&CallFunc_S8_I32_I32_I32_I32_I32_I32_RetVoid },
{ "MvS8iiiiiiiiiii", (void*)&CallFunc_S8_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_RetVoid },
+ { "MvTS12p", (void*)&CallFunc_This_S12_RetVoid_PE },
+ { "MvTS32p", (void*)&CallFunc_This_S32_RetVoid_PE },
+ { "MvTS8S8p", (void*)&CallFunc_This_S8_S8_RetVoid_PE },
+ { "MvTS8ip", (void*)&CallFunc_This_S8_I32_RetVoid_PE },
+ { "MvTS8p", (void*)&CallFunc_This_S8_RetVoid_PE },
+ { "MvTiS8p", (void*)&CallFunc_This_I32_S8_RetVoid_PE },
+ { "MvTiiS8S8iip", (void*)&CallFunc_This_I32_I32_S8_S8_I32_I32_RetVoid_PE },
+ { "MvTiiiiip", (void*)&CallFunc_This_I32_I32_I32_I32_I32_RetVoid_PE },
+ { "MvTiiiip", (void*)&CallFunc_This_I32_I32_I32_I32_RetVoid_PE },
+ { "MvTiiip", (void*)&CallFunc_This_I32_I32_I32_RetVoid_PE },
+ { "MvTiip", (void*)&CallFunc_This_I32_I32_RetVoid_PE },
+ { "MvTip", (void*)&CallFunc_This_I32_RetVoid_PE },
{ "MvTp", (void*)&CallFunc_This_RetVoid_PE },
{ "Mvdddddddddii", (void*)&CallFunc_F64_F64_F64_F64_F64_F64_F64_F64_F64_I32_I32_RetVoid },
{ "Mvdi", (void*)&CallFunc_F64_I32_RetVoid },
@@ -760,6 +1091,7 @@ const StringToWasmSigThunk g_wasmThunks[] = {
{ "Mviiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_RetVoid },
{ "Mviiiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_RetVoid },
{ "Mviiiil", (void*)&CallFunc_I32_I32_I32_I32_I64_RetVoid },
+ { "Mviiiip", (void*)&CallFunc_I32_I32_I32_I32_RetVoid_PE },
{ "Mviiip", (void*)&CallFunc_I32_I32_I32_RetVoid_PE },
{ "Mviip", (void*)&CallFunc_I32_I32_RetVoid_PE },
{ "Mvip", (void*)&CallFunc_I32_RetVoid_PE },
diff --git a/src/coreclr/vm/wasm/browser/callhelpers-pinvoke.cpp b/src/coreclr/vm/wasm/browser/callhelpers-pinvoke.cpp
index 9dbd7f579c68e6..2248bb068804aa 100644
--- a/src/coreclr/vm/wasm/browser/callhelpers-pinvoke.cpp
+++ b/src/coreclr/vm/wasm/browser/callhelpers-pinvoke.cpp
@@ -11,7 +11,6 @@
#include
extern "C" {
- uint32_t CompressionNative_CompressBound (uint32_t);
uint32_t CompressionNative_Crc32 (uint32_t, void *, int32_t);
int32_t CompressionNative_Deflate (void *, int32_t);
int32_t CompressionNative_DeflateEnd (void *);
@@ -196,7 +195,6 @@ static const Entry s_libSystem_Globalization_Native [] = {
};
static const Entry s_libSystem_IO_Compression_Native [] = {
- DllImportEntry(CompressionNative_CompressBound) // System.IO.Compression
DllImportEntry(CompressionNative_Crc32) // System.IO.Compression
DllImportEntry(CompressionNative_Deflate) // System.IO.Compression, System.Net.WebSockets
DllImportEntry(CompressionNative_DeflateEnd) // System.IO.Compression, System.Net.WebSockets
@@ -236,7 +234,7 @@ static const Entry s_libSystem_Native [] = {
DllImportEntry(SystemNative_Free) // System.Private.CoreLib
DllImportEntry(SystemNative_FreeLibrary) // System.Private.CoreLib
DllImportEntry(SystemNative_GetCpuUtilization) // System.Private.CoreLib
- DllImportEntry(SystemNative_GetCryptographicallySecureRandomBytes) // System.Private.CoreLib, System.Security.Cryptography
+ DllImportEntry(SystemNative_GetCryptographicallySecureRandomBytes) // System.IO.Compression, System.Private.CoreLib, System.Security.Cryptography
DllImportEntry(SystemNative_GetCwd) // System.Private.CoreLib
DllImportEntry(SystemNative_GetDefaultSearchOrderPseudoHandle) // System.Private.CoreLib
DllImportEntry(SystemNative_GetErrNo) // System.Private.CoreLib
@@ -326,7 +324,7 @@ typedef struct PInvokeTable {
static PInvokeTable s_PInvokeTables[] = {
{"libSystem.Globalization.Native", s_libSystem_Globalization_Native, 34},
- {"libSystem.IO.Compression.Native", s_libSystem_IO_Compression_Native, 10},
+ {"libSystem.IO.Compression.Native", s_libSystem_IO_Compression_Native, 9},
{"libSystem.Native", s_libSystem_Native, 94},
{"libSystem.Native.Browser", s_libSystem_Native_Browser, 1},
{"libSystem.Runtime.InteropServices.JavaScript.Native", s_libSystem_Runtime_InteropServices_JavaScript_Native, 6}
diff --git a/src/coreclr/vm/wasm/browser/callhelpers-portable-entrypoints.cpp b/src/coreclr/vm/wasm/browser/callhelpers-portable-entrypoints.cpp
new file mode 100644
index 00000000000000..cbe20c0ef987a0
--- /dev/null
+++ b/src/coreclr/vm/wasm/browser/callhelpers-portable-entrypoints.cpp
@@ -0,0 +1,1461 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+//
+
+//
+// GENERATED FILE, DON'T EDIT
+// Generated by coreclr InterpToNativeGenerator
+//
+
+#include
+#include
+#include "callhelpers.hpp"
+
+void ExecuteInterpretedMethodWithArgs_PortableEntryPoint(PCODE portableEntrypoint, TransitionBlock* block, size_t argsSize, int8_t* retBuff);
+
+namespace
+{
+ FCDECL4(void, CallInterpreter_This_S12_I32_RetS12, int32_t, int8_t*, int8_t*, int32_t);
+ WASM_CALLABLE_FUNC_5(void, CallInterpreter_This_S12_I32_RetS12, int32_t arg0, int8_t* retBuf, int8_t* arg1, int32_t arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[4];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 12);
+ transitionBlock.args[3] = (int64_t)arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), retBuf);
+ return;
+ }
+
+ FCDECL5(void, CallInterpreter_This_I32_S12_I32_RetS12, int32_t, int8_t*, int32_t, int8_t*, int32_t);
+ WASM_CALLABLE_FUNC_6(void, CallInterpreter_This_I32_S12_I32_RetS12, int32_t arg0, int8_t* retBuf, int32_t arg1, int8_t* arg2, int32_t arg3, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[5];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ memcpy(&transitionBlock.args[2], arg2, 12);
+ transitionBlock.args[4] = (int64_t)arg3;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), retBuf);
+ return;
+ }
+
+ FCDECL5(void, CallInterpreter_This_I32_I32_I32_RetS12, int32_t, int8_t*, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_6(void, CallInterpreter_This_I32_I32_I32_RetS12, int32_t arg0, int8_t* retBuf, int32_t arg1, int32_t arg2, int32_t arg3, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[4];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), retBuf);
+ return;
+ }
+
+ FCDECL4(void, CallInterpreter_This_I32_I32_RetS12, int32_t, int8_t*, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_5(void, CallInterpreter_This_I32_I32_RetS12, int32_t arg0, int8_t* retBuf, int32_t arg1, int32_t arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), retBuf);
+ return;
+ }
+
+ FCDECL2(void, CallInterpreter_This_RetS16, int32_t, int8_t*);
+ WASM_CALLABLE_FUNC_3(void, CallInterpreter_This_RetS16, int32_t arg0, int8_t* retBuf, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), retBuf);
+ return;
+ }
+
+ FCDECL4(void, CallInterpreter_L2_I32_RetS16, int8_t*, int64_t, int64_t, int32_t);
+ WASM_CALLABLE_FUNC_5(void, CallInterpreter_L2_I32_RetS16, int8_t* retBuf, int64_t arg0Lo, int64_t arg0Hi, int32_t arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = arg0Lo;
+ transitionBlock.args[1] = arg0Hi;
+ transitionBlock.args[2] = (int64_t)arg1;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), retBuf);
+ return;
+ }
+
+ FCDECL2(void, CallInterpreter_This_RetS1, int32_t, int8_t*);
+ WASM_CALLABLE_FUNC_3(void, CallInterpreter_This_RetS1, int32_t arg0, int8_t* retBuf, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), retBuf);
+ return;
+ }
+
+ FCDECL5(void, CallInterpreter_This_I32_I32_I32_RetS8, int32_t, int8_t*, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_6(void, CallInterpreter_This_I32_I32_I32_RetS8, int32_t arg0, int8_t* retBuf, int32_t arg1, int32_t arg2, int32_t arg3, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[4];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), retBuf);
+ return;
+ }
+
+ FCDECL3(void, CallInterpreter_This_I32_RetS8, int32_t, int8_t*, int32_t);
+ WASM_CALLABLE_FUNC_4(void, CallInterpreter_This_I32_RetS8, int32_t arg0, int8_t* retBuf, int32_t arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), retBuf);
+ return;
+ }
+
+ FCDECL2(void, CallInterpreter_This_RetS8, int32_t, int8_t*);
+ WASM_CALLABLE_FUNC_3(void, CallInterpreter_This_RetS8, int32_t arg0, int8_t* retBuf, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), retBuf);
+ return;
+ }
+
+ FCDECL3(double, CallInterpreter_F64_F64_F64_RetF64, double, double, double);
+ WASM_CALLABLE_FUNC_4(double, CallInterpreter_F64_F64_F64_RetF64, double arg0, double arg1, double arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ *(double*)&transitionBlock.args[0] = arg0;
+ *(double*)&transitionBlock.args[1] = arg1;
+ *(double*)&transitionBlock.args[2] = arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ double result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL2(double, CallInterpreter_F64_F64_RetF64, double, double);
+ WASM_CALLABLE_FUNC_3(double, CallInterpreter_F64_F64_RetF64, double arg0, double arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ *(double*)&transitionBlock.args[0] = arg0;
+ *(double*)&transitionBlock.args[1] = arg1;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ double result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL2(double, CallInterpreter_F64_I32_RetF64, double, int32_t);
+ WASM_CALLABLE_FUNC_3(double, CallInterpreter_F64_I32_RetF64, double arg0, int32_t arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ *(double*)&transitionBlock.args[0] = arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ double result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL1(double, CallInterpreter_F64_RetF64, double);
+ WASM_CALLABLE_FUNC_2(double, CallInterpreter_F64_RetF64, double arg0, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ *(double*)&transitionBlock.args[0] = arg0;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ double result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL3(float, CallInterpreter_F32_F32_F32_RetF32, float, float, float);
+ WASM_CALLABLE_FUNC_4(float, CallInterpreter_F32_F32_F32_RetF32, float arg0, float arg1, float arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ *(float*)&transitionBlock.args[0] = arg0;
+ *(float*)&transitionBlock.args[1] = arg1;
+ *(float*)&transitionBlock.args[2] = arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ float result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL2(float, CallInterpreter_F32_F32_RetF32, float, float);
+ WASM_CALLABLE_FUNC_3(float, CallInterpreter_F32_F32_RetF32, float arg0, float arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ *(float*)&transitionBlock.args[0] = arg0;
+ *(float*)&transitionBlock.args[1] = arg1;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ float result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL2(float, CallInterpreter_F32_I32_RetF32, float, int32_t);
+ WASM_CALLABLE_FUNC_3(float, CallInterpreter_F32_I32_RetF32, float arg0, int32_t arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ *(float*)&transitionBlock.args[0] = arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ float result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL1(float, CallInterpreter_F32_RetF32, float);
+ WASM_CALLABLE_FUNC_2(float, CallInterpreter_F32_RetF32, float arg0, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ *(float*)&transitionBlock.args[0] = arg0;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ float result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL1(int32_t, CallInterpreter_S8_RetI32, int8_t*);
+ WASM_CALLABLE_FUNC_2(int32_t, CallInterpreter_S8_RetI32, int8_t* arg0, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ memcpy(&transitionBlock.args[0], arg0, 8);
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL3(int32_t, CallInterpreter_This_S12_I32_RetI32, int32_t, int8_t*, int32_t);
+ WASM_CALLABLE_FUNC_4(int32_t, CallInterpreter_This_S12_I32_RetI32, int32_t arg0, int8_t* arg1, int32_t arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[4];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 12);
+ transitionBlock.args[3] = (int64_t)arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL2(int32_t, CallInterpreter_This_S12_RetI32, int32_t, int8_t*);
+ WASM_CALLABLE_FUNC_3(int32_t, CallInterpreter_This_S12_RetI32, int32_t arg0, int8_t* arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 12);
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL3(int32_t, CallInterpreter_This_S8_S8_RetI32, int32_t, int8_t*, int8_t*);
+ WASM_CALLABLE_FUNC_4(int32_t, CallInterpreter_This_S8_S8_RetI32, int32_t arg0, int8_t* arg1, int8_t* arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 8);
+ memcpy(&transitionBlock.args[2], arg2, 8);
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL5(int32_t, CallInterpreter_This_S8_I32_S8_I32_RetI32, int32_t, int8_t*, int32_t, int8_t*, int32_t);
+ WASM_CALLABLE_FUNC_6(int32_t, CallInterpreter_This_S8_I32_S8_I32_RetI32, int32_t arg0, int8_t* arg1, int32_t arg2, int8_t* arg3, int32_t arg4, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[5];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 8);
+ transitionBlock.args[2] = (int64_t)arg2;
+ memcpy(&transitionBlock.args[3], arg3, 8);
+ transitionBlock.args[4] = (int64_t)arg4;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL5(int32_t, CallInterpreter_This_S8_I32_I32_I32_RetI32, int32_t, int8_t*, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_6(int32_t, CallInterpreter_This_S8_I32_I32_I32_RetI32, int32_t arg0, int8_t* arg1, int32_t arg2, int32_t arg3, int32_t arg4, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[5];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 8);
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ transitionBlock.args[4] = (int64_t)arg4;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL3(int32_t, CallInterpreter_This_S8_I32_RetI32, int32_t, int8_t*, int32_t);
+ WASM_CALLABLE_FUNC_4(int32_t, CallInterpreter_This_S8_I32_RetI32, int32_t arg0, int8_t* arg1, int32_t arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 8);
+ transitionBlock.args[2] = (int64_t)arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL2(int32_t, CallInterpreter_This_S8_RetI32, int32_t, int8_t*);
+ WASM_CALLABLE_FUNC_3(int32_t, CallInterpreter_This_S8_RetI32, int32_t arg0, int8_t* arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 8);
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL3(int32_t, CallInterpreter_This_I32_S12_RetI32, int32_t, int32_t, int8_t*);
+ WASM_CALLABLE_FUNC_4(int32_t, CallInterpreter_This_I32_S12_RetI32, int32_t arg0, int32_t arg1, int8_t* arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[4];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ memcpy(&transitionBlock.args[2], arg2, 12);
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL3(int32_t, CallInterpreter_This_I32_S8_RetI32, int32_t, int32_t, int8_t*);
+ WASM_CALLABLE_FUNC_4(int32_t, CallInterpreter_This_I32_S8_RetI32, int32_t arg0, int32_t arg1, int8_t* arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ memcpy(&transitionBlock.args[2], arg2, 8);
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL5(int32_t, CallInterpreter_This_I32_I32_I32_I32_RetI32, int32_t, int32_t, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_6(int32_t, CallInterpreter_This_I32_I32_I32_I32_RetI32, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[5];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ transitionBlock.args[4] = (int64_t)arg4;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL4(int32_t, CallInterpreter_This_I32_I32_I32_RetI32, int32_t, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_5(int32_t, CallInterpreter_This_I32_I32_I32_RetI32, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[4];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL3(int32_t, CallInterpreter_This_I32_I32_RetI32, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_4(int32_t, CallInterpreter_This_I32_I32_RetI32, int32_t arg0, int32_t arg1, int32_t arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL2(int32_t, CallInterpreter_This_I32_RetI32, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_3(int32_t, CallInterpreter_This_I32_RetI32, int32_t arg0, int32_t arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL1(int32_t, CallInterpreter_This_RetI32, int32_t);
+ WASM_CALLABLE_FUNC_2(int32_t, CallInterpreter_This_RetI32, int32_t arg0, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL1(int32_t, CallInterpreter_F64_RetI32, double);
+ WASM_CALLABLE_FUNC_2(int32_t, CallInterpreter_F64_RetI32, double arg0, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ *(double*)&transitionBlock.args[0] = arg0;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL2(int32_t, CallInterpreter_I32_S8_RetI32, int32_t, int8_t*);
+ WASM_CALLABLE_FUNC_3(int32_t, CallInterpreter_I32_S8_RetI32, int32_t arg0, int8_t* arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 8);
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL8(int32_t, CallInterpreter_I32_I32_I32_I32_I32_I32_I32_I32_RetI32, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_9(int32_t, CallInterpreter_I32_I32_I32_I32_I32_I32_I32_I32_RetI32, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, int32_t arg5, int32_t arg6, int32_t arg7, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[8];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ transitionBlock.args[4] = (int64_t)arg4;
+ transitionBlock.args[5] = (int64_t)arg5;
+ transitionBlock.args[6] = (int64_t)arg6;
+ transitionBlock.args[7] = (int64_t)arg7;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL7(int32_t, CallInterpreter_I32_I32_I32_I32_I32_I32_I32_RetI32, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_8(int32_t, CallInterpreter_I32_I32_I32_I32_I32_I32_I32_RetI32, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, int32_t arg5, int32_t arg6, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[7];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ transitionBlock.args[4] = (int64_t)arg4;
+ transitionBlock.args[5] = (int64_t)arg5;
+ transitionBlock.args[6] = (int64_t)arg6;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL6(int32_t, CallInterpreter_I32_I32_I32_I32_I32_I32_RetI32, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_7(int32_t, CallInterpreter_I32_I32_I32_I32_I32_I32_RetI32, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, int32_t arg5, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[6];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ transitionBlock.args[4] = (int64_t)arg4;
+ transitionBlock.args[5] = (int64_t)arg5;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL5(int32_t, CallInterpreter_I32_I32_I32_I32_I32_RetI32, int32_t, int32_t, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_6(int32_t, CallInterpreter_I32_I32_I32_I32_I32_RetI32, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[5];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ transitionBlock.args[4] = (int64_t)arg4;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL4(int32_t, CallInterpreter_I32_I32_I32_I32_RetI32, int32_t, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_5(int32_t, CallInterpreter_I32_I32_I32_I32_RetI32, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[4];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL3(int32_t, CallInterpreter_I32_I32_I32_RetI32, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_4(int32_t, CallInterpreter_I32_I32_I32_RetI32, int32_t arg0, int32_t arg1, int32_t arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL2(int32_t, CallInterpreter_I32_I32_RetI32, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_3(int32_t, CallInterpreter_I32_I32_RetI32, int32_t arg0, int32_t arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL1(int32_t, CallInterpreter_I32_RetI32, int32_t);
+ WASM_CALLABLE_FUNC_2(int32_t, CallInterpreter_I32_RetI32, int32_t arg0, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL0(int32_t, CallInterpreter_Void_RetI32);
+ WASM_CALLABLE_FUNC_1(int32_t, CallInterpreter_Void_RetI32, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, 0, (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL1(int64_t, CallInterpreter_F64_RetI64, double);
+ WASM_CALLABLE_FUNC_2(int64_t, CallInterpreter_F64_RetI64, double arg0, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ *(double*)&transitionBlock.args[0] = arg0;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int64_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL3(int64_t, CallInterpreter_I32_I64_I64_RetI64, int32_t, int64_t, int64_t);
+ WASM_CALLABLE_FUNC_4(int64_t, CallInterpreter_I32_I64_I64_RetI64, int32_t arg0, int64_t arg1, int64_t arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int64_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL2(int64_t, CallInterpreter_I32_I64_RetI64, int32_t, int64_t);
+ WASM_CALLABLE_FUNC_3(int64_t, CallInterpreter_I32_I64_RetI64, int32_t arg0, int64_t arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int64_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL1(int64_t, CallInterpreter_I32_RetI64, int32_t);
+ WASM_CALLABLE_FUNC_2(int64_t, CallInterpreter_I32_RetI64, int32_t arg0, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int64_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL2(int64_t, CallInterpreter_I64_I64_RetI64, int64_t, int64_t);
+ WASM_CALLABLE_FUNC_3(int64_t, CallInterpreter_I64_I64_RetI64, int64_t arg0, int64_t arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int64_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL0(int64_t, CallInterpreter_Void_RetI64);
+ WASM_CALLABLE_FUNC_1(int64_t, CallInterpreter_Void_RetI64, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+
+ int64_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, 0, (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL2(void, CallInterpreter_This_S12_RetVoid, int32_t, int8_t*);
+ WASM_CALLABLE_FUNC_3(void, CallInterpreter_This_S12_RetVoid, int32_t arg0, int8_t* arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 12);
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL2(void, CallInterpreter_This_S32_RetVoid, int32_t, int8_t*);
+ WASM_CALLABLE_FUNC_3(void, CallInterpreter_This_S32_RetVoid, int32_t arg0, int8_t* arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[5];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 32);
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL3(void, CallInterpreter_This_S8_S8_RetVoid, int32_t, int8_t*, int8_t*);
+ WASM_CALLABLE_FUNC_4(void, CallInterpreter_This_S8_S8_RetVoid, int32_t arg0, int8_t* arg1, int8_t* arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 8);
+ memcpy(&transitionBlock.args[2], arg2, 8);
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL3(void, CallInterpreter_This_S8_I32_RetVoid, int32_t, int8_t*, int32_t);
+ WASM_CALLABLE_FUNC_4(void, CallInterpreter_This_S8_I32_RetVoid, int32_t arg0, int8_t* arg1, int32_t arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 8);
+ transitionBlock.args[2] = (int64_t)arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL2(void, CallInterpreter_This_S8_RetVoid, int32_t, int8_t*);
+ WASM_CALLABLE_FUNC_3(void, CallInterpreter_This_S8_RetVoid, int32_t arg0, int8_t* arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 8);
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL3(void, CallInterpreter_This_I32_S8_RetVoid, int32_t, int32_t, int8_t*);
+ WASM_CALLABLE_FUNC_4(void, CallInterpreter_This_I32_S8_RetVoid, int32_t arg0, int32_t arg1, int8_t* arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ memcpy(&transitionBlock.args[2], arg2, 8);
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL7(void, CallInterpreter_This_I32_I32_S8_S8_I32_I32_RetVoid, int32_t, int32_t, int32_t, int8_t*, int8_t*, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_8(void, CallInterpreter_This_I32_I32_S8_S8_I32_I32_RetVoid, int32_t arg0, int32_t arg1, int32_t arg2, int8_t* arg3, int8_t* arg4, int32_t arg5, int32_t arg6, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[7];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ memcpy(&transitionBlock.args[3], arg3, 8);
+ memcpy(&transitionBlock.args[4], arg4, 8);
+ transitionBlock.args[5] = (int64_t)arg5;
+ transitionBlock.args[6] = (int64_t)arg6;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL6(void, CallInterpreter_This_I32_I32_I32_I32_I32_RetVoid, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_7(void, CallInterpreter_This_I32_I32_I32_I32_I32_RetVoid, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, int32_t arg5, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[6];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ transitionBlock.args[4] = (int64_t)arg4;
+ transitionBlock.args[5] = (int64_t)arg5;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL5(void, CallInterpreter_This_I32_I32_I32_I32_RetVoid, int32_t, int32_t, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_6(void, CallInterpreter_This_I32_I32_I32_I32_RetVoid, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[5];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ transitionBlock.args[4] = (int64_t)arg4;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL4(void, CallInterpreter_This_I32_I32_I32_RetVoid, int32_t, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_5(void, CallInterpreter_This_I32_I32_I32_RetVoid, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[4];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL3(void, CallInterpreter_This_I32_I32_RetVoid, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_4(void, CallInterpreter_This_I32_I32_RetVoid, int32_t arg0, int32_t arg1, int32_t arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL2(void, CallInterpreter_This_I32_RetVoid, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_3(void, CallInterpreter_This_I32_RetVoid, int32_t arg0, int32_t arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL1(void, CallInterpreter_This_RetVoid, int32_t);
+ WASM_CALLABLE_FUNC_2(void, CallInterpreter_This_RetVoid, int32_t arg0, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL3(void, CallInterpreter_F64_I32_I32_RetVoid, double, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_4(void, CallInterpreter_F64_I32_I32_RetVoid, double arg0, int32_t arg1, int32_t arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ *(double*)&transitionBlock.args[0] = arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL3(void, CallInterpreter_F32_I32_I32_RetVoid, float, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_4(void, CallInterpreter_F32_I32_I32_RetVoid, float arg0, int32_t arg1, int32_t arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ *(float*)&transitionBlock.args[0] = arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL4(void, CallInterpreter_I32_I32_I32_I32_RetVoid, int32_t, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_5(void, CallInterpreter_I32_I32_I32_I32_RetVoid, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[4];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL3(void, CallInterpreter_I32_I32_I32_RetVoid, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_4(void, CallInterpreter_I32_I32_I32_RetVoid, int32_t arg0, int32_t arg1, int32_t arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL2(void, CallInterpreter_I32_I32_RetVoid, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_3(void, CallInterpreter_I32_I32_RetVoid, int32_t arg0, int32_t arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL1(void, CallInterpreter_I32_RetVoid, int32_t);
+ WASM_CALLABLE_FUNC_2(void, CallInterpreter_I32_RetVoid, int32_t arg0, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL0(void, CallInterpreter_Void_RetVoid);
+ WASM_CALLABLE_FUNC_1(void, CallInterpreter_Void_RetVoid, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, 0, (int8_t*)&result);
+ return;
+ }
+
+}
+
+const StringToWasmSigThunk g_wasmGeneratedPortableEntryPointThunks[] = {
+ { "IS12TS12ip", (void*)&CallInterpreter_This_S12_I32_RetS12 },
+ { "IS12TiS12ip", (void*)&CallInterpreter_This_I32_S12_I32_RetS12 },
+ { "IS12Tiiip", (void*)&CallInterpreter_This_I32_I32_I32_RetS12 },
+ { "IS12Tiip", (void*)&CallInterpreter_This_I32_I32_RetS12 },
+ { "IS16Tp", (void*)&CallInterpreter_This_RetS16 },
+ { "IS16l2ip", (void*)&CallInterpreter_L2_I32_RetS16 },
+ { "IS1Tp", (void*)&CallInterpreter_This_RetS1 },
+ { "IS8Tiiip", (void*)&CallInterpreter_This_I32_I32_I32_RetS8 },
+ { "IS8Tip", (void*)&CallInterpreter_This_I32_RetS8 },
+ { "IS8Tp", (void*)&CallInterpreter_This_RetS8 },
+ { "Iddddp", (void*)&CallInterpreter_F64_F64_F64_RetF64 },
+ { "Idddp", (void*)&CallInterpreter_F64_F64_RetF64 },
+ { "Iddip", (void*)&CallInterpreter_F64_I32_RetF64 },
+ { "Iddp", (void*)&CallInterpreter_F64_RetF64 },
+ { "Iffffp", (void*)&CallInterpreter_F32_F32_F32_RetF32 },
+ { "Ifffp", (void*)&CallInterpreter_F32_F32_RetF32 },
+ { "Iffip", (void*)&CallInterpreter_F32_I32_RetF32 },
+ { "Iffp", (void*)&CallInterpreter_F32_RetF32 },
+ { "IiS8p", (void*)&CallInterpreter_S8_RetI32 },
+ { "IiTS12ip", (void*)&CallInterpreter_This_S12_I32_RetI32 },
+ { "IiTS12p", (void*)&CallInterpreter_This_S12_RetI32 },
+ { "IiTS8S8p", (void*)&CallInterpreter_This_S8_S8_RetI32 },
+ { "IiTS8iS8ip", (void*)&CallInterpreter_This_S8_I32_S8_I32_RetI32 },
+ { "IiTS8iiip", (void*)&CallInterpreter_This_S8_I32_I32_I32_RetI32 },
+ { "IiTS8ip", (void*)&CallInterpreter_This_S8_I32_RetI32 },
+ { "IiTS8p", (void*)&CallInterpreter_This_S8_RetI32 },
+ { "IiTiS12p", (void*)&CallInterpreter_This_I32_S12_RetI32 },
+ { "IiTiS8p", (void*)&CallInterpreter_This_I32_S8_RetI32 },
+ { "IiTiiiip", (void*)&CallInterpreter_This_I32_I32_I32_I32_RetI32 },
+ { "IiTiiip", (void*)&CallInterpreter_This_I32_I32_I32_RetI32 },
+ { "IiTiip", (void*)&CallInterpreter_This_I32_I32_RetI32 },
+ { "IiTip", (void*)&CallInterpreter_This_I32_RetI32 },
+ { "IiTp", (void*)&CallInterpreter_This_RetI32 },
+ { "Iidp", (void*)&CallInterpreter_F64_RetI32 },
+ { "IiiS8p", (void*)&CallInterpreter_I32_S8_RetI32 },
+ { "Iiiiiiiiiip", (void*)&CallInterpreter_I32_I32_I32_I32_I32_I32_I32_I32_RetI32 },
+ { "Iiiiiiiiip", (void*)&CallInterpreter_I32_I32_I32_I32_I32_I32_I32_RetI32 },
+ { "Iiiiiiiip", (void*)&CallInterpreter_I32_I32_I32_I32_I32_I32_RetI32 },
+ { "Iiiiiiip", (void*)&CallInterpreter_I32_I32_I32_I32_I32_RetI32 },
+ { "Iiiiiip", (void*)&CallInterpreter_I32_I32_I32_I32_RetI32 },
+ { "Iiiiip", (void*)&CallInterpreter_I32_I32_I32_RetI32 },
+ { "Iiiip", (void*)&CallInterpreter_I32_I32_RetI32 },
+ { "Iiip", (void*)&CallInterpreter_I32_RetI32 },
+ { "Iip", (void*)&CallInterpreter_Void_RetI32 },
+ { "Ildp", (void*)&CallInterpreter_F64_RetI64 },
+ { "Ilillp", (void*)&CallInterpreter_I32_I64_I64_RetI64 },
+ { "Ililp", (void*)&CallInterpreter_I32_I64_RetI64 },
+ { "Ilip", (void*)&CallInterpreter_I32_RetI64 },
+ { "Illlp", (void*)&CallInterpreter_I64_I64_RetI64 },
+ { "Ilp", (void*)&CallInterpreter_Void_RetI64 },
+ { "IvTS12p", (void*)&CallInterpreter_This_S12_RetVoid },
+ { "IvTS32p", (void*)&CallInterpreter_This_S32_RetVoid },
+ { "IvTS8S8p", (void*)&CallInterpreter_This_S8_S8_RetVoid },
+ { "IvTS8ip", (void*)&CallInterpreter_This_S8_I32_RetVoid },
+ { "IvTS8p", (void*)&CallInterpreter_This_S8_RetVoid },
+ { "IvTiS8p", (void*)&CallInterpreter_This_I32_S8_RetVoid },
+ { "IvTiiS8S8iip", (void*)&CallInterpreter_This_I32_I32_S8_S8_I32_I32_RetVoid },
+ { "IvTiiiiip", (void*)&CallInterpreter_This_I32_I32_I32_I32_I32_RetVoid },
+ { "IvTiiiip", (void*)&CallInterpreter_This_I32_I32_I32_I32_RetVoid },
+ { "IvTiiip", (void*)&CallInterpreter_This_I32_I32_I32_RetVoid },
+ { "IvTiip", (void*)&CallInterpreter_This_I32_I32_RetVoid },
+ { "IvTip", (void*)&CallInterpreter_This_I32_RetVoid },
+ { "IvTp", (void*)&CallInterpreter_This_RetVoid },
+ { "Ivdiip", (void*)&CallInterpreter_F64_I32_I32_RetVoid },
+ { "Ivfiip", (void*)&CallInterpreter_F32_I32_I32_RetVoid },
+ { "Iviiiip", (void*)&CallInterpreter_I32_I32_I32_I32_RetVoid },
+ { "Iviiip", (void*)&CallInterpreter_I32_I32_I32_RetVoid },
+ { "Iviip", (void*)&CallInterpreter_I32_I32_RetVoid },
+ { "Ivip", (void*)&CallInterpreter_I32_RetVoid },
+ { "Ivp", (void*)&CallInterpreter_Void_RetVoid },
+};
+
+const size_t g_wasmGeneratedPortableEntryPointThunksCount = sizeof(g_wasmGeneratedPortableEntryPointThunks) / sizeof(g_wasmGeneratedPortableEntryPointThunks[0]);
diff --git a/src/coreclr/vm/wasm/callhelpers.hpp b/src/coreclr/vm/wasm/callhelpers.hpp
index 6f60164ffa87c9..ddd394cb3f2ec6 100644
--- a/src/coreclr/vm/wasm/callhelpers.hpp
+++ b/src/coreclr/vm/wasm/callhelpers.hpp
@@ -43,6 +43,9 @@ struct StringToWasmSigThunk
extern const StringToWasmSigThunk g_wasmThunks[];
extern const size_t g_wasmThunksCount;
+extern const StringToWasmSigThunk g_wasmGeneratedPortableEntryPointThunks[];
+extern const size_t g_wasmGeneratedPortableEntryPointThunksCount;
+
struct ReverseThunkMapValue
{
MethodDesc** Target;
diff --git a/src/coreclr/vm/wasm/helpers.cpp b/src/coreclr/vm/wasm/helpers.cpp
index 05ad28e3b94eea..77b31d3dacaf86 100644
--- a/src/coreclr/vm/wasm/helpers.cpp
+++ b/src/coreclr/vm/wasm/helpers.cpp
@@ -17,353 +17,8 @@
void ExecuteInterpretedMethodWithArgs_PortableEntryPoint(PCODE portableEntrypoint, TransitionBlock* block, size_t argsSize, int8_t* retBuff);
// -------------------------------------------------
-// Logic that will eventually mostly be pregenerated for R2R to interpreter code
-// -------------------------------------------------
-namespace
-{
- FCDECL0(void, CallInterpreter_RetVoid);
- WASM_CALLABLE_FUNC_1(void, CallInterpreter_RetVoid, PCODE portableEntrypoint)
- {
- struct
- {
- TransitionBlock block;
- } transitionBlock;
- transitionBlock.block.m_ReturnAddress = 0;
- transitionBlock.block.m_StackPointer = callersStackPointer;
- void * result = NULL;
-
- ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, 0, (int8_t*)&result);
- return;
- }
- FCDECL1(void, CallInterpreter_I32_RetVoid, int32_t);
- WASM_CALLABLE_FUNC_2(void, CallInterpreter_I32_RetVoid, int32_t arg0, PCODE portableEntrypoint)
- {
- struct
- {
- TransitionBlock block;
- int64_t args[1];
- } transitionBlock;
- transitionBlock.block.m_ReturnAddress = 0;
- transitionBlock.block.m_StackPointer = callersStackPointer;
- transitionBlock.args[0] = (int64_t)arg0;
- static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
-
- void * result = NULL;
- ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
- return;
- }
- FCDECL2(void, CallInterpreter_I32_I32_RetVoid, int32_t, int32_t);
- WASM_CALLABLE_FUNC_3(void, CallInterpreter_I32_I32_RetVoid, int32_t arg0, int32_t arg1, PCODE portableEntrypoint)
- {
- struct
- {
- TransitionBlock block;
- int64_t args[2];
- } transitionBlock;
- transitionBlock.block.m_ReturnAddress = 0;
- transitionBlock.block.m_StackPointer = callersStackPointer;
- transitionBlock.args[0] = (int64_t)arg0;
- transitionBlock.args[1] = (int64_t)arg1;
- static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
-
- void * result = NULL;
- ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
- return;
- }
- FCDECL3(void, CallInterpreter_I32_I32_I32_RetVoid, int32_t, int32_t, int32_t);
- WASM_CALLABLE_FUNC_4(void, CallInterpreter_I32_I32_I32_RetVoid, int32_t arg0, int32_t arg1, int32_t arg2, PCODE portableEntrypoint)
- {
- struct
- {
- TransitionBlock block;
- int64_t args[3];
- } transitionBlock;
- transitionBlock.block.m_ReturnAddress = 0;
- transitionBlock.block.m_StackPointer = callersStackPointer;
- transitionBlock.args[0] = (int64_t)arg0;
- transitionBlock.args[1] = (int64_t)arg1;
- transitionBlock.args[2] = (int64_t)arg2;
- static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
-
-
- void * result = NULL;
- ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
- return;
- }
- FCDECL4(void, CallInterpreter_I32_I32_I32_I32_RetVoid, int32_t, int32_t, int32_t, int32_t);
- WASM_CALLABLE_FUNC_5(void, CallInterpreter_I32_I32_I32_I32_RetVoid, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, PCODE portableEntrypoint)
- {
- struct
- {
- TransitionBlock block;
- int64_t args[4];
- } transitionBlock;
- transitionBlock.block.m_ReturnAddress = 0;
- transitionBlock.block.m_StackPointer = callersStackPointer;
- transitionBlock.args[0] = (int64_t)arg0;
- transitionBlock.args[1] = (int64_t)arg1;
- transitionBlock.args[2] = (int64_t)arg2;
- transitionBlock.args[3] = (int64_t)arg3;
- static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
-
- void * result = NULL;
- ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
- return;
- }
- FCDECL0(int32_t, CallInterpreter_RetI32);
- WASM_CALLABLE_FUNC_1(int32_t, CallInterpreter_RetI32, PCODE portableEntrypoint)
- {
- struct
- {
- TransitionBlock block;
- } transitionBlock;
- transitionBlock.block.m_ReturnAddress = 0;
- transitionBlock.block.m_StackPointer = callersStackPointer;
- void * result = NULL;
- ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, 0, (int8_t*)&result);
- return (int32_t)result;
- }
- FCDECL1(int32_t, CallInterpreter_I32_RetI32, int32_t);
- WASM_CALLABLE_FUNC_2(int32_t, CallInterpreter_I32_RetI32, int32_t arg0, PCODE portableEntrypoint)
- {
- struct
- {
- TransitionBlock block;
- int64_t args[1];
- } transitionBlock;
- transitionBlock.block.m_ReturnAddress = 0;
- transitionBlock.block.m_StackPointer = callersStackPointer;
- transitionBlock.args[0] = (int64_t)arg0;
- static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
-
- void * result = NULL;
- ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
- return (int32_t)result;
- }
- FCDECL1(int32_t, CallInterpreter_D64_RetI32, double);
- WASM_CALLABLE_FUNC_2(int32_t, CallInterpreter_D64_RetI32, double arg0, PCODE portableEntrypoint)
- {
- struct
- {
- TransitionBlock block;
- double args[1];
- } transitionBlock;
- transitionBlock.block.m_ReturnAddress = 0;
- transitionBlock.block.m_StackPointer = callersStackPointer;
- transitionBlock.args[0] = arg0;
- static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
-
- void * result = NULL;
- ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
- return (int32_t)result;
- }
- FCDECL1(int64_t, CallInterpreter_D64_RetI64, double);
- WASM_CALLABLE_FUNC_2(int64_t, CallInterpreter_D64_RetI64, double arg0, PCODE portableEntrypoint)
- {
- struct
- {
- TransitionBlock block;
- double args[1];
- } transitionBlock;
- transitionBlock.block.m_ReturnAddress = 0;
- transitionBlock.block.m_StackPointer = callersStackPointer;
- transitionBlock.args[0] = arg0;
- static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
-
- int64_t result = 0;
- ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
- return result;
- }
- FCDECL2(int32_t, CallInterpreter_I32_I32_RetI32, int32_t, int32_t);
- WASM_CALLABLE_FUNC_3(int32_t, CallInterpreter_I32_I32_RetI32, int32_t arg0, int32_t arg1, PCODE portableEntrypoint)
- {
- struct
- {
- TransitionBlock block;
- int64_t args[2];
- } transitionBlock;
- transitionBlock.block.m_ReturnAddress = 0;
- transitionBlock.block.m_StackPointer = callersStackPointer;
- transitionBlock.args[0] = (int64_t)arg0;
- transitionBlock.args[1] = (int64_t)arg1;
- static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
-
- void * result = NULL;
- ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
- return (int32_t)result;
- }
- FCDECL2(int32_t, CallInterpreter_I32_S8_RetI32, int32_t, int8_t*);
- WASM_CALLABLE_FUNC_3(int32_t, CallInterpreter_I32_S8_RetI32, int32_t arg0, int8_t* arg1, PCODE portableEntrypoint)
- {
- struct
- {
- TransitionBlock block;
- int64_t args[2];
- } transitionBlock;
- transitionBlock.block.m_ReturnAddress = 0;
- transitionBlock.block.m_StackPointer = callersStackPointer;
- transitionBlock.args[0] = (int64_t)arg0;
- memcpy(&transitionBlock.args[1], arg1, 8);
- static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
-
- void * result = NULL;
- ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
- return (int32_t)result;
- }
- FCDECL3(int32_t, CallInterpreter_I32_I32_I32_RetI32, int32_t, int32_t, int32_t);
- WASM_CALLABLE_FUNC_4(int32_t, CallInterpreter_I32_I32_I32_RetI32, int32_t arg0, int32_t arg1, int32_t arg2, PCODE portableEntrypoint)
- {
- struct
- {
- TransitionBlock block;
- int64_t args[3];
- } transitionBlock;
- transitionBlock.block.m_ReturnAddress = 0;
- transitionBlock.block.m_StackPointer = callersStackPointer;
- transitionBlock.args[0] = (int64_t)arg0;
- transitionBlock.args[1] = (int64_t)arg1;
- transitionBlock.args[2] = (int64_t)arg2;
- static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
-
- void * result = NULL;
- ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
- return (int32_t)result;
- }
- FCDECL4(int32_t, CallInterpreter_I32_I32_I32_I32_RetI32, int32_t, int32_t, int32_t, int32_t);
- WASM_CALLABLE_FUNC_5(int32_t, CallInterpreter_I32_I32_I32_I32_RetI32, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, PCODE portableEntrypoint)
- {
- struct
- {
- TransitionBlock block;
- int64_t args[4];
- } transitionBlock;
- transitionBlock.block.m_ReturnAddress = 0;
- transitionBlock.block.m_StackPointer = callersStackPointer;
- transitionBlock.args[0] = (int64_t)arg0;
- transitionBlock.args[1] = (int64_t)arg1;
- transitionBlock.args[2] = (int64_t)arg2;
- transitionBlock.args[3] = (int64_t)arg3;
- static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
-
- void * result = NULL;
- ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
- return (int32_t)result;
- }
- FCDECL5(int32_t, CallInterpreter_I32_I32_I32_I32_I32_RetI32, int32_t, int32_t, int32_t, int32_t, int32_t);
- WASM_CALLABLE_FUNC_6(int32_t, CallInterpreter_I32_I32_I32_I32_I32_RetI32, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, PCODE portableEntrypoint)
- {
- struct
- {
- TransitionBlock block;
- int64_t args[5];
- } transitionBlock;
- transitionBlock.block.m_ReturnAddress = 0;
- transitionBlock.block.m_StackPointer = callersStackPointer;
- transitionBlock.args[0] = (int64_t)arg0;
- transitionBlock.args[1] = (int64_t)arg1;
- transitionBlock.args[2] = (int64_t)arg2;
- transitionBlock.args[3] = (int64_t)arg3;
- transitionBlock.args[4] = (int64_t)arg4;
- static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
-
- void * result = NULL;
- ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
- return (int32_t)result;
- }
- FCDECL6(int32_t, CallInterpreter_I32_I32_I32_I32_I32_I32_RetI32, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t);
- WASM_CALLABLE_FUNC_7(int32_t, CallInterpreter_I32_I32_I32_I32_I32_I32_RetI32, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, int32_t arg5, PCODE portableEntrypoint)
- {
- struct
- {
- TransitionBlock block;
- int64_t args[6];
- } transitionBlock;
- transitionBlock.block.m_ReturnAddress = 0;
- transitionBlock.block.m_StackPointer = callersStackPointer;
- transitionBlock.args[0] = (int64_t)arg0;
- transitionBlock.args[1] = (int64_t)arg1;
- transitionBlock.args[2] = (int64_t)arg2;
- transitionBlock.args[3] = (int64_t)arg3;
- transitionBlock.args[4] = (int64_t)arg4;
- transitionBlock.args[5] = (int64_t)arg5;
- static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
-
- void * result = NULL;
- ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
- return (int32_t)result;
- }
- FCDECL7(int32_t, CallInterpreter_I32_I32_I32_I32_I32_I32_I32_RetI32, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t);
- WASM_CALLABLE_FUNC_8(int32_t, CallInterpreter_I32_I32_I32_I32_I32_I32_I32_RetI32, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, int32_t arg5, int32_t arg6, PCODE portableEntrypoint)
- {
- struct
- {
- TransitionBlock block;
- int64_t args[7];
- } transitionBlock;
- transitionBlock.block.m_ReturnAddress = 0;
- transitionBlock.block.m_StackPointer = callersStackPointer;
- transitionBlock.args[0] = (int64_t)arg0;
- transitionBlock.args[1] = (int64_t)arg1;
- transitionBlock.args[2] = (int64_t)arg2;
- transitionBlock.args[3] = (int64_t)arg3;
- transitionBlock.args[4] = (int64_t)arg4;
- transitionBlock.args[5] = (int64_t)arg5;
- transitionBlock.args[6] = (int64_t)arg6;
- static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
-
- void * result = NULL;
- ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
- return (int32_t)result;
- }
- FCDECL8(int32_t, CallInterpreter_I32_I32_I32_I32_I32_I32_I32_I32_RetI32, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t);
- WASM_CALLABLE_FUNC_9(int32_t, CallInterpreter_I32_I32_I32_I32_I32_I32_I32_I32_RetI32, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, int32_t arg5, int32_t arg6, int32_t arg7, PCODE portableEntrypoint)
- {
- struct
- {
- TransitionBlock block;
- int64_t args[8];
- } transitionBlock;
- transitionBlock.block.m_ReturnAddress = 0;
- transitionBlock.block.m_StackPointer = callersStackPointer;
- transitionBlock.args[0] = (int64_t)arg0;
- transitionBlock.args[1] = (int64_t)arg1;
- transitionBlock.args[2] = (int64_t)arg2;
- transitionBlock.args[3] = (int64_t)arg3;
- transitionBlock.args[4] = (int64_t)arg4;
- transitionBlock.args[5] = (int64_t)arg5;
- transitionBlock.args[6] = (int64_t)arg6;
- transitionBlock.args[7] = (int64_t)arg7;
- static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
-
- void * result = NULL;
- ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
- return (int32_t)result;
- }
-}
-
-const StringToWasmSigThunk g_wasmPortableEntryPointThunks[] = {
- { "Ivp", (void*)&CallInterpreter_RetVoid },
- { "Ivip", (void*)&CallInterpreter_I32_RetVoid },
- { "Iviip", (void*)&CallInterpreter_I32_I32_RetVoid },
- { "Iviiip", (void*)&CallInterpreter_I32_I32_I32_RetVoid },
- { "Iviiiip", (void*)&CallInterpreter_I32_I32_I32_I32_RetVoid },
- { "Iip", (void*)&CallInterpreter_RetI32 },
- { "Iiip", (void*)&CallInterpreter_I32_RetI32 },
- { "Iiiip", (void*)&CallInterpreter_I32_I32_RetI32 },
- { "Iiiiip", (void*)&CallInterpreter_I32_I32_I32_RetI32 },
- { "Iiiiiip", (void*)&CallInterpreter_I32_I32_I32_I32_RetI32 },
- { "Iiiiiiip", (void*)&CallInterpreter_I32_I32_I32_I32_I32_RetI32 },
- { "Iiiiiiiip", (void*)&CallInterpreter_I32_I32_I32_I32_I32_I32_RetI32 },
- { "Iiiiiiiiip", (void*)&CallInterpreter_I32_I32_I32_I32_I32_I32_I32_RetI32 },
- { "Iiiiiiiiiip", (void*)&CallInterpreter_I32_I32_I32_I32_I32_I32_I32_I32_RetI32 },
- { "Iidp", (void*)&CallInterpreter_D64_RetI32 },
- { "Ildp", (void*)&CallInterpreter_D64_RetI64 },
- { "IiiS8p", (void*)&CallInterpreter_I32_S8_RetI32 }
-};
-
-const size_t g_wasmPortableEntryPointThunksCount = sizeof(g_wasmPortableEntryPointThunks) / sizeof(g_wasmPortableEntryPointThunks[0]);
-// -------------------------------------------------
-// END Logic that will eventually mostly be pregenerated for R2R to interpreter code END
+// The R2R to interpreter thunks are generated into callhelpers-portable-entrypoints.cpp by the
+// WasmAppBuilder generator, one table per target.
// -------------------------------------------------
extern "C" void STDCALL CallCountingStubCode()
@@ -1486,10 +1141,10 @@ namespace
}
InterpreterCalliCookie thunk = LookupThunk(keyBuffer);
-#ifdef _DEBUG
if (thunk == NULL)
- printf("WASM calli missing for key: %s\n", keyBuffer);
-#endif
+ {
+ printf("WASM: no interpreter-to-R2R calli thunk for signature key '%s'. Add it to g_wasmThunks.\n", keyBuffer);
+ }
return thunk;
}
@@ -1532,12 +1187,13 @@ namespace
}
void* thunk = LookupPortableEntryPointThunk(keyBuffer);
-#ifdef _DEBUG
if (thunk == NULL)
{
- LOG((LF_STUBS, LL_INFO100000, "WASM R2R to interpreter call missing for key: %s\n", keyBuffer));
+ // Printed rather than only asserted: the caller's assert compiles out in release, where these
+ // gaps surface, and cannot carry the key. A miss leaves the entry point's table index 0 and
+ // traps later as "null function", far from here.
+ printf("WASM: no R2R-to-interpreter thunk for signature key '%s'. Add it to pregeneratedInterpreterToNativeSignatures in ManagedToNativeGenerator and regenerate.\n", keyBuffer);
}
-#endif
return thunk;
}
@@ -1652,10 +1308,10 @@ void InitializeWasmThunkCaches()
{
StringToWasmSigThunkHash* newTable = new StringToWasmSigThunkHash();
- newTable->Reallocate(g_wasmPortableEntryPointThunksCount * StringToWasmSigThunkHash::s_density_factor_denominator / StringToWasmSigThunkHash::s_density_factor_numerator + 1);
- for (size_t i = 0; i < g_wasmPortableEntryPointThunksCount; i++)
+ newTable->Reallocate(g_wasmGeneratedPortableEntryPointThunksCount * StringToWasmSigThunkHash::s_density_factor_denominator / StringToWasmSigThunkHash::s_density_factor_numerator + 1);
+ for (size_t i = 0; i < g_wasmGeneratedPortableEntryPointThunksCount; i++)
{
- newTable->Add(g_wasmPortableEntryPointThunks[i].key, g_wasmPortableEntryPointThunks[i].value);
+ newTable->Add(g_wasmGeneratedPortableEntryPointThunks[i].key, g_wasmGeneratedPortableEntryPointThunks[i].value);
}
portableEntrypointThunkCache = newTable;
}
@@ -1786,10 +1442,18 @@ void* GetPortableEntryPointToInterpreterThunk(MethodDesc *pMD)
}
thunk = LookupPortableEntryPointThunk(thunkKey);
+ if (thunk == NULL)
+ {
+ PORTABILITY_ASSERT("GetPortableEntryPointToInterpreterThunk: unknown thunk for string constructor");
+ }
}
else
{
thunk = ComputePortableEntryPointToInterpreterThunk(sig);
+ if (thunk == NULL)
+ {
+ PORTABILITY_ASSERT("ComputePortableEntryPointToInterpreterThunk: unknown thunk signature");
+ }
}
return thunk;
diff --git a/src/coreclr/vm/wasm/wasi/callhelpers-interp-to-managed.cpp b/src/coreclr/vm/wasm/wasi/callhelpers-interp-to-managed.cpp
index 0033e59ea2469e..1f128e9aa9f94c 100644
--- a/src/coreclr/vm/wasm/wasi/callhelpers-interp-to-managed.cpp
+++ b/src/coreclr/vm/wasm/wasi/callhelpers-interp-to-managed.cpp
@@ -17,9 +17,83 @@
#define ARG_I64(i) (*(int64_t*)ARG_ADDR(i))
#define ARG_F32(i) (*(float*)ARG_ADDR(i))
#define ARG_F64(i) (*(double*)ARG_ADDR(i))
+typedef struct { char d[1]; } wasm_ret_S1;
+typedef struct { char d[8]; } wasm_ret_S8;
+typedef struct { char d[12]; } wasm_ret_S12;
+typedef struct { char d[16]; } wasm_ret_S16;
namespace
{
+ NOINLINE static void CallFunc_This_S12_I32_RetS12_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int8_t*, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int8_t*, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), pRet, ARG_IND(1), ARG_I32(3), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_S12_I32_RetS12_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int8_t*, int32_t, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int8_t*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), pRet, ARG_I32(1), ARG_IND(2), ARG_I32(4), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_I32_I32_RetS12_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int8_t*, int32_t, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int8_t*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), pRet, ARG_I32(1), ARG_I32(2), ARG_I32(3), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_I32_RetS12_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int8_t*, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int8_t*, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), pRet, ARG_I32(1), ARG_I32(2), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_RetS16_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int8_t*, PCODE) = *(void (**)(int*, int32_t, int8_t*, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), pRet, pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_L2_I32_RetS16_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int8_t*, int64_t, int64_t, int32_t, PCODE) = *(void (**)(int*, int8_t*, int64_t, int64_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, pRet, ARG_I64(0), ARG_I64(1), ARG_I32(2), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_RetS1_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int8_t*, PCODE) = *(void (**)(int*, int32_t, int8_t*, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), pRet, pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_I32_I32_RetS8_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int8_t*, int32_t, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int8_t*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), pRet, ARG_I32(1), ARG_I32(2), ARG_I32(3), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_RetS8_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int8_t*, int32_t, PCODE) = *(void (**)(int*, int32_t, int8_t*, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), pRet, ARG_I32(1), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_RetS8_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int8_t*, PCODE) = *(void (**)(int*, int32_t, int8_t*, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), pRet, pPortableEntryPoint);
+ }
+
NOINLINE static void CallFunc_F64_F64_F64_RetF64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
{
alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
@@ -166,6 +240,97 @@ namespace
*((int32_t*)pRet) = (*fptr)(ARG_IND(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5));
}
+ NOINLINE static void CallFunc_S8_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_IND(0), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_S12_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), ARG_I32(3), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_S12_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_S8_S8_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), ARG_IND(2), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_S8_I32_S8_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), ARG_I32(2), ARG_IND(3), ARG_I32(4), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_S8_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_S8_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), ARG_I32(2), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_S8_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_S12_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_IND(2), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_S8_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_IND(2), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), pPortableEntryPoint);
+ }
+
NOINLINE static void CallFunc_This_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
{
alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
@@ -180,6 +345,13 @@ namespace
*((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), pPortableEntryPoint);
}
+ NOINLINE static void CallFunc_F64_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, double, PCODE) = *(int32_t (**)(int*, double, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_F64(0), pPortableEntryPoint);
+ }
+
static void CallFunc_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet)
{
int32_t (*fptr)(int32_t) = (int32_t (*)(int32_t))pcode;
@@ -198,6 +370,13 @@ namespace
*((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_IND(1), ARG_I32(2), ARG_I32(3), ARG_I32(4));
}
+ NOINLINE static void CallFunc_I32_S8_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), pPortableEntryPoint);
+ }
+
static void CallFunc_I32_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet)
{
int32_t (*fptr)(int32_t, int32_t) = (int32_t (*)(int32_t, int32_t))pcode;
@@ -270,6 +449,20 @@ namespace
*((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5), ARG_I32(6), ARG_I32(7), ARG_I32(8), ARG_I32(9), ARG_I32(10), ARG_I32(11), ARG_I32(12), ARG_I32(13));
}
+ NOINLINE static void CallFunc_I32_I32_I32_I32_I32_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5), ARG_I32(6), ARG_I32(7), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_I32_I32_I32_I32_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int32_t (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = *(int32_t (**)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ *((int32_t*)pRet) = (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5), ARG_I32(6), pPortableEntryPoint);
+ }
+
NOINLINE static void CallFunc_I32_I32_I32_I32_I32_I32_RetI32_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
{
alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
@@ -385,6 +578,13 @@ namespace
*((int64_t*)pRet) = (*fptr)();
}
+ NOINLINE static void CallFunc_F64_RetI64_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ int64_t (*fptr)(int*, double, PCODE) = *(int64_t (**)(int*, double, PCODE))(pPortableEntryPoint);
+ *((int64_t*)pRet) = (*fptr)(&framePointer, ARG_F64(0), pPortableEntryPoint);
+ }
+
static void CallFunc_I32_RetI64(PCODE pcode, int8_t* pArgs, int8_t* pRet)
{
int64_t (*fptr)(int32_t) = (int64_t (*)(int32_t))pcode;
@@ -510,6 +710,90 @@ namespace
(*fptr)(ARG_IND(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5), ARG_I32(6), ARG_I32(7), ARG_I32(8), ARG_I32(9), ARG_I32(10), ARG_I32(11));
}
+ NOINLINE static void CallFunc_This_S12_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_S32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_S8_S8_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), ARG_IND(2), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_S8_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), ARG_I32(2), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_S8_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_IND(1), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_S8_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_IND(2), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_I32_S8_S8_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_IND(3), ARG_IND(4), ARG_I32(5), ARG_I32(6), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_I32_I32_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_I32_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), pPortableEntryPoint);
+ }
+
+ NOINLINE static void CallFunc_This_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), pPortableEntryPoint);
+ }
+
NOINLINE static void CallFunc_This_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
{
alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
@@ -597,6 +881,13 @@ namespace
(*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5));
}
+ NOINLINE static void CallFunc_I32_I32_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
+ {
+ alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
+ void (*fptr)(int*, int32_t, int32_t, int32_t, int32_t, PCODE) = *(void (**)(int*, int32_t, int32_t, int32_t, int32_t, PCODE))(pPortableEntryPoint);
+ (*fptr)(&framePointer, ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), pPortableEntryPoint);
+ }
+
NOINLINE static void CallFunc_I32_I32_I32_RetVoid_PE(PCODE pPortableEntryPoint, int8_t* pArgs, int8_t* pRet)
{
alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;
@@ -639,6 +930,16 @@ namespace
}
const StringToWasmSigThunk g_wasmThunks[] = {
+ { "MS12TS12ip", (void*)&CallFunc_This_S12_I32_RetS12_PE },
+ { "MS12TiS12ip", (void*)&CallFunc_This_I32_S12_I32_RetS12_PE },
+ { "MS12Tiiip", (void*)&CallFunc_This_I32_I32_I32_RetS12_PE },
+ { "MS12Tiip", (void*)&CallFunc_This_I32_I32_RetS12_PE },
+ { "MS16Tp", (void*)&CallFunc_This_RetS16_PE },
+ { "MS16l2ip", (void*)&CallFunc_L2_I32_RetS16_PE },
+ { "MS1Tp", (void*)&CallFunc_This_RetS1_PE },
+ { "MS8Tiiip", (void*)&CallFunc_This_I32_I32_I32_RetS8_PE },
+ { "MS8Tip", (void*)&CallFunc_This_I32_RetS8_PE },
+ { "MS8Tp", (void*)&CallFunc_This_RetS8_PE },
{ "Mddddp", (void*)&CallFunc_F64_F64_F64_RetF64_PE },
{ "Mdddp", (void*)&CallFunc_F64_F64_RetF64_PE },
{ "Mddip", (void*)&CallFunc_F64_I32_RetF64_PE },
@@ -662,11 +963,26 @@ const StringToWasmSigThunk g_wasmThunks[] = {
{ "MiS8iii", (void*)&CallFunc_S8_I32_I32_I32_RetI32 },
{ "MiS8iiii", (void*)&CallFunc_S8_I32_I32_I32_I32_RetI32 },
{ "MiS8iiiii", (void*)&CallFunc_S8_I32_I32_I32_I32_I32_RetI32 },
+ { "MiS8p", (void*)&CallFunc_S8_RetI32_PE },
+ { "MiTS12ip", (void*)&CallFunc_This_S12_I32_RetI32_PE },
+ { "MiTS12p", (void*)&CallFunc_This_S12_RetI32_PE },
+ { "MiTS8S8p", (void*)&CallFunc_This_S8_S8_RetI32_PE },
+ { "MiTS8iS8ip", (void*)&CallFunc_This_S8_I32_S8_I32_RetI32_PE },
+ { "MiTS8iiip", (void*)&CallFunc_This_S8_I32_I32_I32_RetI32_PE },
+ { "MiTS8ip", (void*)&CallFunc_This_S8_I32_RetI32_PE },
+ { "MiTS8p", (void*)&CallFunc_This_S8_RetI32_PE },
+ { "MiTiS12p", (void*)&CallFunc_This_I32_S12_RetI32_PE },
+ { "MiTiS8p", (void*)&CallFunc_This_I32_S8_RetI32_PE },
+ { "MiTiiiip", (void*)&CallFunc_This_I32_I32_I32_I32_RetI32_PE },
+ { "MiTiiip", (void*)&CallFunc_This_I32_I32_I32_RetI32_PE },
+ { "MiTiip", (void*)&CallFunc_This_I32_I32_RetI32_PE },
{ "MiTip", (void*)&CallFunc_This_I32_RetI32_PE },
{ "MiTp", (void*)&CallFunc_This_RetI32_PE },
+ { "Midp", (void*)&CallFunc_F64_RetI32_PE },
{ "Mii", (void*)&CallFunc_I32_RetI32 },
{ "MiiS8i", (void*)&CallFunc_I32_S8_I32_RetI32 },
{ "MiiS8iii", (void*)&CallFunc_I32_S8_I32_I32_I32_RetI32 },
+ { "MiiS8p", (void*)&CallFunc_I32_S8_RetI32_PE },
{ "Miii", (void*)&CallFunc_I32_I32_RetI32 },
{ "MiiiS8iiS8", (void*)&CallFunc_I32_I32_S8_I32_I32_S8_RetI32 },
{ "MiiiS8iiii", (void*)&CallFunc_I32_I32_S8_I32_I32_I32_I32_RetI32 },
@@ -679,6 +995,8 @@ const StringToWasmSigThunk g_wasmThunks[] = {
{ "Miiiiiiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_I32_I32_RetI32 },
{ "Miiiiiiiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_I32_I32_I32_RetI32 },
{ "Miiiiiiiiiiiiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_RetI32 },
+ { "Miiiiiiiiip", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_I32_I32_RetI32_PE },
+ { "Miiiiiiiip", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_I32_RetI32_PE },
{ "Miiiiiiip", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_RetI32_PE },
{ "Miiiiiip", (void*)&CallFunc_I32_I32_I32_I32_I32_RetI32_PE },
{ "Miiiiip", (void*)&CallFunc_I32_I32_I32_I32_RetI32_PE },
@@ -697,6 +1015,7 @@ const StringToWasmSigThunk g_wasmThunks[] = {
{ "Milili", (void*)&CallFunc_I64_I32_I64_I32_RetI32 },
{ "Mip", (void*)&CallFunc_Void_RetI32_PE },
{ "Ml", (void*)&CallFunc_Void_RetI64 },
+ { "Mldp", (void*)&CallFunc_F64_RetI64_PE },
{ "Mli", (void*)&CallFunc_I32_RetI64 },
{ "Mliii", (void*)&CallFunc_I32_I32_I32_RetI64 },
{ "Mliiil", (void*)&CallFunc_I32_I32_I32_I64_RetI64 },
@@ -717,6 +1036,18 @@ const StringToWasmSigThunk g_wasmThunks[] = {
{ "MvS8iiiii", (void*)&CallFunc_S8_I32_I32_I32_I32_I32_RetVoid },
{ "MvS8iiiiii", (void*)&CallFunc_S8_I32_I32_I32_I32_I32_I32_RetVoid },
{ "MvS8iiiiiiiiiii", (void*)&CallFunc_S8_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_RetVoid },
+ { "MvTS12p", (void*)&CallFunc_This_S12_RetVoid_PE },
+ { "MvTS32p", (void*)&CallFunc_This_S32_RetVoid_PE },
+ { "MvTS8S8p", (void*)&CallFunc_This_S8_S8_RetVoid_PE },
+ { "MvTS8ip", (void*)&CallFunc_This_S8_I32_RetVoid_PE },
+ { "MvTS8p", (void*)&CallFunc_This_S8_RetVoid_PE },
+ { "MvTiS8p", (void*)&CallFunc_This_I32_S8_RetVoid_PE },
+ { "MvTiiS8S8iip", (void*)&CallFunc_This_I32_I32_S8_S8_I32_I32_RetVoid_PE },
+ { "MvTiiiiip", (void*)&CallFunc_This_I32_I32_I32_I32_I32_RetVoid_PE },
+ { "MvTiiiip", (void*)&CallFunc_This_I32_I32_I32_I32_RetVoid_PE },
+ { "MvTiiip", (void*)&CallFunc_This_I32_I32_I32_RetVoid_PE },
+ { "MvTiip", (void*)&CallFunc_This_I32_I32_RetVoid_PE },
+ { "MvTip", (void*)&CallFunc_This_I32_RetVoid_PE },
{ "MvTp", (void*)&CallFunc_This_RetVoid_PE },
{ "Mvdiip", (void*)&CallFunc_F64_I32_I32_RetVoid_PE },
{ "Mvfiip", (void*)&CallFunc_F32_I32_I32_RetVoid_PE },
@@ -731,6 +1062,7 @@ const StringToWasmSigThunk g_wasmThunks[] = {
{ "Mviiii", (void*)&CallFunc_I32_I32_I32_I32_RetVoid },
{ "Mviiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_RetVoid },
{ "Mviiiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_RetVoid },
+ { "Mviiiip", (void*)&CallFunc_I32_I32_I32_I32_RetVoid_PE },
{ "Mviiip", (void*)&CallFunc_I32_I32_I32_RetVoid_PE },
{ "Mviip", (void*)&CallFunc_I32_I32_RetVoid_PE },
{ "Mvili", (void*)&CallFunc_I32_I64_I32_RetVoid },
diff --git a/src/coreclr/vm/wasm/wasi/callhelpers-pinvoke.cpp b/src/coreclr/vm/wasm/wasi/callhelpers-pinvoke.cpp
index e128a77b7bd640..493539a07f5216 100644
--- a/src/coreclr/vm/wasm/wasi/callhelpers-pinvoke.cpp
+++ b/src/coreclr/vm/wasm/wasi/callhelpers-pinvoke.cpp
@@ -11,7 +11,6 @@
#include
extern "C" {
- uint32_t CompressionNative_CompressBound (uint32_t);
uint32_t CompressionNative_Crc32 (uint32_t, void *, int32_t);
int32_t CompressionNative_Deflate (void *, int32_t);
int32_t CompressionNative_DeflateEnd (void *);
@@ -94,6 +93,7 @@ extern "C" {
int32_t SystemNative_GetBytesAvailable (void *, void *);
int32_t SystemNative_GetControlMessageBufferSize (int32_t, int32_t);
double SystemNative_GetCpuUtilization (void *);
+ int32_t SystemNative_GetCryptographicallySecureRandomBytes (void *, int32_t);
void * SystemNative_GetCwd (void *, int32_t);
void * SystemNative_GetDefaultSearchOrderPseudoHandle ();
int32_t SystemNative_GetErrNo ();
@@ -290,7 +290,6 @@ static const Entry s_libSystem_Globalization_Native [] = {
};
static const Entry s_libSystem_IO_Compression_Native [] = {
- DllImportEntry(CompressionNative_CompressBound) // System.IO.Compression
DllImportEntry(CompressionNative_Crc32) // System.IO.Compression
DllImportEntry(CompressionNative_Deflate) // System.IO.Compression
DllImportEntry(CompressionNative_DeflateEnd) // System.IO.Compression
@@ -342,9 +341,10 @@ static const Entry s_libSystem_Native [] = {
DllImportEntry(SystemNative_GetBytesAvailable) // System.Net.Sockets
DllImportEntry(SystemNative_GetControlMessageBufferSize) // System.Net.Sockets
DllImportEntry(SystemNative_GetCpuUtilization) // System.Private.CoreLib
+ DllImportEntry(SystemNative_GetCryptographicallySecureRandomBytes) // System.IO.Compression
DllImportEntry(SystemNative_GetCwd) // System.Private.CoreLib
DllImportEntry(SystemNative_GetDefaultSearchOrderPseudoHandle) // System.Private.CoreLib
- DllImportEntry(SystemNative_GetErrNo) // System.Net.NameResolution, System.Private.CoreLib
+ DllImportEntry(SystemNative_GetErrNo) // System.Private.CoreLib
DllImportEntry(SystemNative_GetHostEntryForName) // System.Net.NameResolution
DllImportEntry(SystemNative_GetHostName) // System.Net.NameResolution
DllImportEntry(SystemNative_GetIPv4Address) // System.Net.Primitives, System.Net.Sockets
@@ -526,8 +526,8 @@ typedef struct PInvokeTable {
static PInvokeTable s_PInvokeTables[] = {
{"libSystem.Globalization.Native", s_libSystem_Globalization_Native, 34},
- {"libSystem.IO.Compression.Native", s_libSystem_IO_Compression_Native, 10},
- {"libSystem.Native", s_libSystem_Native, 147},
+ {"libSystem.IO.Compression.Native", s_libSystem_IO_Compression_Native, 9},
+ {"libSystem.Native", s_libSystem_Native, 148},
{"libSystem.Native.Browser", s_libSystem_Native_Browser, 0},
{"libSystem.Runtime.InteropServices.JavaScript.Native", s_libSystem_Runtime_InteropServices_JavaScript_Native, 0},
{"wasi:clocks/monotonic-clock@0.2.8", s_wasi_3A_clocks_2F_monotonic_clock_40_0_2_8, 4},
diff --git a/src/coreclr/vm/wasm/wasi/callhelpers-portable-entrypoints.cpp b/src/coreclr/vm/wasm/wasi/callhelpers-portable-entrypoints.cpp
new file mode 100644
index 00000000000000..cbe20c0ef987a0
--- /dev/null
+++ b/src/coreclr/vm/wasm/wasi/callhelpers-portable-entrypoints.cpp
@@ -0,0 +1,1461 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+//
+
+//
+// GENERATED FILE, DON'T EDIT
+// Generated by coreclr InterpToNativeGenerator
+//
+
+#include
+#include
+#include "callhelpers.hpp"
+
+void ExecuteInterpretedMethodWithArgs_PortableEntryPoint(PCODE portableEntrypoint, TransitionBlock* block, size_t argsSize, int8_t* retBuff);
+
+namespace
+{
+ FCDECL4(void, CallInterpreter_This_S12_I32_RetS12, int32_t, int8_t*, int8_t*, int32_t);
+ WASM_CALLABLE_FUNC_5(void, CallInterpreter_This_S12_I32_RetS12, int32_t arg0, int8_t* retBuf, int8_t* arg1, int32_t arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[4];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 12);
+ transitionBlock.args[3] = (int64_t)arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), retBuf);
+ return;
+ }
+
+ FCDECL5(void, CallInterpreter_This_I32_S12_I32_RetS12, int32_t, int8_t*, int32_t, int8_t*, int32_t);
+ WASM_CALLABLE_FUNC_6(void, CallInterpreter_This_I32_S12_I32_RetS12, int32_t arg0, int8_t* retBuf, int32_t arg1, int8_t* arg2, int32_t arg3, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[5];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ memcpy(&transitionBlock.args[2], arg2, 12);
+ transitionBlock.args[4] = (int64_t)arg3;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), retBuf);
+ return;
+ }
+
+ FCDECL5(void, CallInterpreter_This_I32_I32_I32_RetS12, int32_t, int8_t*, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_6(void, CallInterpreter_This_I32_I32_I32_RetS12, int32_t arg0, int8_t* retBuf, int32_t arg1, int32_t arg2, int32_t arg3, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[4];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), retBuf);
+ return;
+ }
+
+ FCDECL4(void, CallInterpreter_This_I32_I32_RetS12, int32_t, int8_t*, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_5(void, CallInterpreter_This_I32_I32_RetS12, int32_t arg0, int8_t* retBuf, int32_t arg1, int32_t arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), retBuf);
+ return;
+ }
+
+ FCDECL2(void, CallInterpreter_This_RetS16, int32_t, int8_t*);
+ WASM_CALLABLE_FUNC_3(void, CallInterpreter_This_RetS16, int32_t arg0, int8_t* retBuf, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), retBuf);
+ return;
+ }
+
+ FCDECL4(void, CallInterpreter_L2_I32_RetS16, int8_t*, int64_t, int64_t, int32_t);
+ WASM_CALLABLE_FUNC_5(void, CallInterpreter_L2_I32_RetS16, int8_t* retBuf, int64_t arg0Lo, int64_t arg0Hi, int32_t arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = arg0Lo;
+ transitionBlock.args[1] = arg0Hi;
+ transitionBlock.args[2] = (int64_t)arg1;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), retBuf);
+ return;
+ }
+
+ FCDECL2(void, CallInterpreter_This_RetS1, int32_t, int8_t*);
+ WASM_CALLABLE_FUNC_3(void, CallInterpreter_This_RetS1, int32_t arg0, int8_t* retBuf, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), retBuf);
+ return;
+ }
+
+ FCDECL5(void, CallInterpreter_This_I32_I32_I32_RetS8, int32_t, int8_t*, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_6(void, CallInterpreter_This_I32_I32_I32_RetS8, int32_t arg0, int8_t* retBuf, int32_t arg1, int32_t arg2, int32_t arg3, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[4];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), retBuf);
+ return;
+ }
+
+ FCDECL3(void, CallInterpreter_This_I32_RetS8, int32_t, int8_t*, int32_t);
+ WASM_CALLABLE_FUNC_4(void, CallInterpreter_This_I32_RetS8, int32_t arg0, int8_t* retBuf, int32_t arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), retBuf);
+ return;
+ }
+
+ FCDECL2(void, CallInterpreter_This_RetS8, int32_t, int8_t*);
+ WASM_CALLABLE_FUNC_3(void, CallInterpreter_This_RetS8, int32_t arg0, int8_t* retBuf, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), retBuf);
+ return;
+ }
+
+ FCDECL3(double, CallInterpreter_F64_F64_F64_RetF64, double, double, double);
+ WASM_CALLABLE_FUNC_4(double, CallInterpreter_F64_F64_F64_RetF64, double arg0, double arg1, double arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ *(double*)&transitionBlock.args[0] = arg0;
+ *(double*)&transitionBlock.args[1] = arg1;
+ *(double*)&transitionBlock.args[2] = arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ double result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL2(double, CallInterpreter_F64_F64_RetF64, double, double);
+ WASM_CALLABLE_FUNC_3(double, CallInterpreter_F64_F64_RetF64, double arg0, double arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ *(double*)&transitionBlock.args[0] = arg0;
+ *(double*)&transitionBlock.args[1] = arg1;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ double result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL2(double, CallInterpreter_F64_I32_RetF64, double, int32_t);
+ WASM_CALLABLE_FUNC_3(double, CallInterpreter_F64_I32_RetF64, double arg0, int32_t arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ *(double*)&transitionBlock.args[0] = arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ double result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL1(double, CallInterpreter_F64_RetF64, double);
+ WASM_CALLABLE_FUNC_2(double, CallInterpreter_F64_RetF64, double arg0, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ *(double*)&transitionBlock.args[0] = arg0;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ double result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL3(float, CallInterpreter_F32_F32_F32_RetF32, float, float, float);
+ WASM_CALLABLE_FUNC_4(float, CallInterpreter_F32_F32_F32_RetF32, float arg0, float arg1, float arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ *(float*)&transitionBlock.args[0] = arg0;
+ *(float*)&transitionBlock.args[1] = arg1;
+ *(float*)&transitionBlock.args[2] = arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ float result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL2(float, CallInterpreter_F32_F32_RetF32, float, float);
+ WASM_CALLABLE_FUNC_3(float, CallInterpreter_F32_F32_RetF32, float arg0, float arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ *(float*)&transitionBlock.args[0] = arg0;
+ *(float*)&transitionBlock.args[1] = arg1;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ float result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL2(float, CallInterpreter_F32_I32_RetF32, float, int32_t);
+ WASM_CALLABLE_FUNC_3(float, CallInterpreter_F32_I32_RetF32, float arg0, int32_t arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ *(float*)&transitionBlock.args[0] = arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ float result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL1(float, CallInterpreter_F32_RetF32, float);
+ WASM_CALLABLE_FUNC_2(float, CallInterpreter_F32_RetF32, float arg0, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ *(float*)&transitionBlock.args[0] = arg0;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ float result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL1(int32_t, CallInterpreter_S8_RetI32, int8_t*);
+ WASM_CALLABLE_FUNC_2(int32_t, CallInterpreter_S8_RetI32, int8_t* arg0, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ memcpy(&transitionBlock.args[0], arg0, 8);
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL3(int32_t, CallInterpreter_This_S12_I32_RetI32, int32_t, int8_t*, int32_t);
+ WASM_CALLABLE_FUNC_4(int32_t, CallInterpreter_This_S12_I32_RetI32, int32_t arg0, int8_t* arg1, int32_t arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[4];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 12);
+ transitionBlock.args[3] = (int64_t)arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL2(int32_t, CallInterpreter_This_S12_RetI32, int32_t, int8_t*);
+ WASM_CALLABLE_FUNC_3(int32_t, CallInterpreter_This_S12_RetI32, int32_t arg0, int8_t* arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 12);
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL3(int32_t, CallInterpreter_This_S8_S8_RetI32, int32_t, int8_t*, int8_t*);
+ WASM_CALLABLE_FUNC_4(int32_t, CallInterpreter_This_S8_S8_RetI32, int32_t arg0, int8_t* arg1, int8_t* arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 8);
+ memcpy(&transitionBlock.args[2], arg2, 8);
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL5(int32_t, CallInterpreter_This_S8_I32_S8_I32_RetI32, int32_t, int8_t*, int32_t, int8_t*, int32_t);
+ WASM_CALLABLE_FUNC_6(int32_t, CallInterpreter_This_S8_I32_S8_I32_RetI32, int32_t arg0, int8_t* arg1, int32_t arg2, int8_t* arg3, int32_t arg4, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[5];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 8);
+ transitionBlock.args[2] = (int64_t)arg2;
+ memcpy(&transitionBlock.args[3], arg3, 8);
+ transitionBlock.args[4] = (int64_t)arg4;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL5(int32_t, CallInterpreter_This_S8_I32_I32_I32_RetI32, int32_t, int8_t*, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_6(int32_t, CallInterpreter_This_S8_I32_I32_I32_RetI32, int32_t arg0, int8_t* arg1, int32_t arg2, int32_t arg3, int32_t arg4, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[5];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 8);
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ transitionBlock.args[4] = (int64_t)arg4;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL3(int32_t, CallInterpreter_This_S8_I32_RetI32, int32_t, int8_t*, int32_t);
+ WASM_CALLABLE_FUNC_4(int32_t, CallInterpreter_This_S8_I32_RetI32, int32_t arg0, int8_t* arg1, int32_t arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 8);
+ transitionBlock.args[2] = (int64_t)arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL2(int32_t, CallInterpreter_This_S8_RetI32, int32_t, int8_t*);
+ WASM_CALLABLE_FUNC_3(int32_t, CallInterpreter_This_S8_RetI32, int32_t arg0, int8_t* arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 8);
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL3(int32_t, CallInterpreter_This_I32_S12_RetI32, int32_t, int32_t, int8_t*);
+ WASM_CALLABLE_FUNC_4(int32_t, CallInterpreter_This_I32_S12_RetI32, int32_t arg0, int32_t arg1, int8_t* arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[4];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ memcpy(&transitionBlock.args[2], arg2, 12);
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL3(int32_t, CallInterpreter_This_I32_S8_RetI32, int32_t, int32_t, int8_t*);
+ WASM_CALLABLE_FUNC_4(int32_t, CallInterpreter_This_I32_S8_RetI32, int32_t arg0, int32_t arg1, int8_t* arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ memcpy(&transitionBlock.args[2], arg2, 8);
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL5(int32_t, CallInterpreter_This_I32_I32_I32_I32_RetI32, int32_t, int32_t, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_6(int32_t, CallInterpreter_This_I32_I32_I32_I32_RetI32, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[5];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ transitionBlock.args[4] = (int64_t)arg4;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL4(int32_t, CallInterpreter_This_I32_I32_I32_RetI32, int32_t, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_5(int32_t, CallInterpreter_This_I32_I32_I32_RetI32, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[4];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL3(int32_t, CallInterpreter_This_I32_I32_RetI32, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_4(int32_t, CallInterpreter_This_I32_I32_RetI32, int32_t arg0, int32_t arg1, int32_t arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL2(int32_t, CallInterpreter_This_I32_RetI32, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_3(int32_t, CallInterpreter_This_I32_RetI32, int32_t arg0, int32_t arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL1(int32_t, CallInterpreter_This_RetI32, int32_t);
+ WASM_CALLABLE_FUNC_2(int32_t, CallInterpreter_This_RetI32, int32_t arg0, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL1(int32_t, CallInterpreter_F64_RetI32, double);
+ WASM_CALLABLE_FUNC_2(int32_t, CallInterpreter_F64_RetI32, double arg0, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ *(double*)&transitionBlock.args[0] = arg0;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL2(int32_t, CallInterpreter_I32_S8_RetI32, int32_t, int8_t*);
+ WASM_CALLABLE_FUNC_3(int32_t, CallInterpreter_I32_S8_RetI32, int32_t arg0, int8_t* arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 8);
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL8(int32_t, CallInterpreter_I32_I32_I32_I32_I32_I32_I32_I32_RetI32, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_9(int32_t, CallInterpreter_I32_I32_I32_I32_I32_I32_I32_I32_RetI32, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, int32_t arg5, int32_t arg6, int32_t arg7, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[8];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ transitionBlock.args[4] = (int64_t)arg4;
+ transitionBlock.args[5] = (int64_t)arg5;
+ transitionBlock.args[6] = (int64_t)arg6;
+ transitionBlock.args[7] = (int64_t)arg7;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL7(int32_t, CallInterpreter_I32_I32_I32_I32_I32_I32_I32_RetI32, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_8(int32_t, CallInterpreter_I32_I32_I32_I32_I32_I32_I32_RetI32, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, int32_t arg5, int32_t arg6, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[7];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ transitionBlock.args[4] = (int64_t)arg4;
+ transitionBlock.args[5] = (int64_t)arg5;
+ transitionBlock.args[6] = (int64_t)arg6;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL6(int32_t, CallInterpreter_I32_I32_I32_I32_I32_I32_RetI32, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_7(int32_t, CallInterpreter_I32_I32_I32_I32_I32_I32_RetI32, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, int32_t arg5, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[6];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ transitionBlock.args[4] = (int64_t)arg4;
+ transitionBlock.args[5] = (int64_t)arg5;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL5(int32_t, CallInterpreter_I32_I32_I32_I32_I32_RetI32, int32_t, int32_t, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_6(int32_t, CallInterpreter_I32_I32_I32_I32_I32_RetI32, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[5];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ transitionBlock.args[4] = (int64_t)arg4;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL4(int32_t, CallInterpreter_I32_I32_I32_I32_RetI32, int32_t, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_5(int32_t, CallInterpreter_I32_I32_I32_I32_RetI32, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[4];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL3(int32_t, CallInterpreter_I32_I32_I32_RetI32, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_4(int32_t, CallInterpreter_I32_I32_I32_RetI32, int32_t arg0, int32_t arg1, int32_t arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL2(int32_t, CallInterpreter_I32_I32_RetI32, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_3(int32_t, CallInterpreter_I32_I32_RetI32, int32_t arg0, int32_t arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL1(int32_t, CallInterpreter_I32_RetI32, int32_t);
+ WASM_CALLABLE_FUNC_2(int32_t, CallInterpreter_I32_RetI32, int32_t arg0, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL0(int32_t, CallInterpreter_Void_RetI32);
+ WASM_CALLABLE_FUNC_1(int32_t, CallInterpreter_Void_RetI32, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+
+ int32_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, 0, (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL1(int64_t, CallInterpreter_F64_RetI64, double);
+ WASM_CALLABLE_FUNC_2(int64_t, CallInterpreter_F64_RetI64, double arg0, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ *(double*)&transitionBlock.args[0] = arg0;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int64_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL3(int64_t, CallInterpreter_I32_I64_I64_RetI64, int32_t, int64_t, int64_t);
+ WASM_CALLABLE_FUNC_4(int64_t, CallInterpreter_I32_I64_I64_RetI64, int32_t arg0, int64_t arg1, int64_t arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int64_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL2(int64_t, CallInterpreter_I32_I64_RetI64, int32_t, int64_t);
+ WASM_CALLABLE_FUNC_3(int64_t, CallInterpreter_I32_I64_RetI64, int32_t arg0, int64_t arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int64_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL1(int64_t, CallInterpreter_I32_RetI64, int32_t);
+ WASM_CALLABLE_FUNC_2(int64_t, CallInterpreter_I32_RetI64, int32_t arg0, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int64_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL2(int64_t, CallInterpreter_I64_I64_RetI64, int64_t, int64_t);
+ WASM_CALLABLE_FUNC_3(int64_t, CallInterpreter_I64_I64_RetI64, int64_t arg0, int64_t arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ int64_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL0(int64_t, CallInterpreter_Void_RetI64);
+ WASM_CALLABLE_FUNC_1(int64_t, CallInterpreter_Void_RetI64, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+
+ int64_t result = 0;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, 0, (int8_t*)&result);
+ return result;
+ }
+
+ FCDECL2(void, CallInterpreter_This_S12_RetVoid, int32_t, int8_t*);
+ WASM_CALLABLE_FUNC_3(void, CallInterpreter_This_S12_RetVoid, int32_t arg0, int8_t* arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 12);
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL2(void, CallInterpreter_This_S32_RetVoid, int32_t, int8_t*);
+ WASM_CALLABLE_FUNC_3(void, CallInterpreter_This_S32_RetVoid, int32_t arg0, int8_t* arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[5];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 32);
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL3(void, CallInterpreter_This_S8_S8_RetVoid, int32_t, int8_t*, int8_t*);
+ WASM_CALLABLE_FUNC_4(void, CallInterpreter_This_S8_S8_RetVoid, int32_t arg0, int8_t* arg1, int8_t* arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 8);
+ memcpy(&transitionBlock.args[2], arg2, 8);
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL3(void, CallInterpreter_This_S8_I32_RetVoid, int32_t, int8_t*, int32_t);
+ WASM_CALLABLE_FUNC_4(void, CallInterpreter_This_S8_I32_RetVoid, int32_t arg0, int8_t* arg1, int32_t arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 8);
+ transitionBlock.args[2] = (int64_t)arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL2(void, CallInterpreter_This_S8_RetVoid, int32_t, int8_t*);
+ WASM_CALLABLE_FUNC_3(void, CallInterpreter_This_S8_RetVoid, int32_t arg0, int8_t* arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ memcpy(&transitionBlock.args[1], arg1, 8);
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL3(void, CallInterpreter_This_I32_S8_RetVoid, int32_t, int32_t, int8_t*);
+ WASM_CALLABLE_FUNC_4(void, CallInterpreter_This_I32_S8_RetVoid, int32_t arg0, int32_t arg1, int8_t* arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ memcpy(&transitionBlock.args[2], arg2, 8);
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL7(void, CallInterpreter_This_I32_I32_S8_S8_I32_I32_RetVoid, int32_t, int32_t, int32_t, int8_t*, int8_t*, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_8(void, CallInterpreter_This_I32_I32_S8_S8_I32_I32_RetVoid, int32_t arg0, int32_t arg1, int32_t arg2, int8_t* arg3, int8_t* arg4, int32_t arg5, int32_t arg6, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[7];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ memcpy(&transitionBlock.args[3], arg3, 8);
+ memcpy(&transitionBlock.args[4], arg4, 8);
+ transitionBlock.args[5] = (int64_t)arg5;
+ transitionBlock.args[6] = (int64_t)arg6;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL6(void, CallInterpreter_This_I32_I32_I32_I32_I32_RetVoid, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_7(void, CallInterpreter_This_I32_I32_I32_I32_I32_RetVoid, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, int32_t arg5, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[6];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ transitionBlock.args[4] = (int64_t)arg4;
+ transitionBlock.args[5] = (int64_t)arg5;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL5(void, CallInterpreter_This_I32_I32_I32_I32_RetVoid, int32_t, int32_t, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_6(void, CallInterpreter_This_I32_I32_I32_I32_RetVoid, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[5];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ transitionBlock.args[4] = (int64_t)arg4;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL4(void, CallInterpreter_This_I32_I32_I32_RetVoid, int32_t, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_5(void, CallInterpreter_This_I32_I32_I32_RetVoid, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[4];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL3(void, CallInterpreter_This_I32_I32_RetVoid, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_4(void, CallInterpreter_This_I32_I32_RetVoid, int32_t arg0, int32_t arg1, int32_t arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL2(void, CallInterpreter_This_I32_RetVoid, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_3(void, CallInterpreter_This_I32_RetVoid, int32_t arg0, int32_t arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL1(void, CallInterpreter_This_RetVoid, int32_t);
+ WASM_CALLABLE_FUNC_2(void, CallInterpreter_This_RetVoid, int32_t arg0, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL3(void, CallInterpreter_F64_I32_I32_RetVoid, double, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_4(void, CallInterpreter_F64_I32_I32_RetVoid, double arg0, int32_t arg1, int32_t arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ *(double*)&transitionBlock.args[0] = arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL3(void, CallInterpreter_F32_I32_I32_RetVoid, float, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_4(void, CallInterpreter_F32_I32_I32_RetVoid, float arg0, int32_t arg1, int32_t arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ *(float*)&transitionBlock.args[0] = arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL4(void, CallInterpreter_I32_I32_I32_I32_RetVoid, int32_t, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_5(void, CallInterpreter_I32_I32_I32_I32_RetVoid, int32_t arg0, int32_t arg1, int32_t arg2, int32_t arg3, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[4];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ transitionBlock.args[3] = (int64_t)arg3;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL3(void, CallInterpreter_I32_I32_I32_RetVoid, int32_t, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_4(void, CallInterpreter_I32_I32_I32_RetVoid, int32_t arg0, int32_t arg1, int32_t arg2, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[3];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ transitionBlock.args[2] = (int64_t)arg2;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL2(void, CallInterpreter_I32_I32_RetVoid, int32_t, int32_t);
+ WASM_CALLABLE_FUNC_3(void, CallInterpreter_I32_I32_RetVoid, int32_t arg0, int32_t arg1, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[2];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ transitionBlock.args[1] = (int64_t)arg1;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL1(void, CallInterpreter_I32_RetVoid, int32_t);
+ WASM_CALLABLE_FUNC_2(void, CallInterpreter_I32_RetVoid, int32_t arg0, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ int64_t args[1];
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+ transitionBlock.args[0] = (int64_t)arg0;
+ static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), "Args array must be at a TransitionBlock offset from the start of the block");
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, sizeof(transitionBlock.args), (int8_t*)&result);
+ return;
+ }
+
+ FCDECL0(void, CallInterpreter_Void_RetVoid);
+ WASM_CALLABLE_FUNC_1(void, CallInterpreter_Void_RetVoid, PCODE portableEntrypoint)
+ {
+ struct
+ {
+ TransitionBlock block;
+ } transitionBlock;
+ transitionBlock.block.m_ReturnAddress = 0;
+ transitionBlock.block.m_StackPointer = callersStackPointer;
+
+ void * result = NULL;
+ ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, 0, (int8_t*)&result);
+ return;
+ }
+
+}
+
+const StringToWasmSigThunk g_wasmGeneratedPortableEntryPointThunks[] = {
+ { "IS12TS12ip", (void*)&CallInterpreter_This_S12_I32_RetS12 },
+ { "IS12TiS12ip", (void*)&CallInterpreter_This_I32_S12_I32_RetS12 },
+ { "IS12Tiiip", (void*)&CallInterpreter_This_I32_I32_I32_RetS12 },
+ { "IS12Tiip", (void*)&CallInterpreter_This_I32_I32_RetS12 },
+ { "IS16Tp", (void*)&CallInterpreter_This_RetS16 },
+ { "IS16l2ip", (void*)&CallInterpreter_L2_I32_RetS16 },
+ { "IS1Tp", (void*)&CallInterpreter_This_RetS1 },
+ { "IS8Tiiip", (void*)&CallInterpreter_This_I32_I32_I32_RetS8 },
+ { "IS8Tip", (void*)&CallInterpreter_This_I32_RetS8 },
+ { "IS8Tp", (void*)&CallInterpreter_This_RetS8 },
+ { "Iddddp", (void*)&CallInterpreter_F64_F64_F64_RetF64 },
+ { "Idddp", (void*)&CallInterpreter_F64_F64_RetF64 },
+ { "Iddip", (void*)&CallInterpreter_F64_I32_RetF64 },
+ { "Iddp", (void*)&CallInterpreter_F64_RetF64 },
+ { "Iffffp", (void*)&CallInterpreter_F32_F32_F32_RetF32 },
+ { "Ifffp", (void*)&CallInterpreter_F32_F32_RetF32 },
+ { "Iffip", (void*)&CallInterpreter_F32_I32_RetF32 },
+ { "Iffp", (void*)&CallInterpreter_F32_RetF32 },
+ { "IiS8p", (void*)&CallInterpreter_S8_RetI32 },
+ { "IiTS12ip", (void*)&CallInterpreter_This_S12_I32_RetI32 },
+ { "IiTS12p", (void*)&CallInterpreter_This_S12_RetI32 },
+ { "IiTS8S8p", (void*)&CallInterpreter_This_S8_S8_RetI32 },
+ { "IiTS8iS8ip", (void*)&CallInterpreter_This_S8_I32_S8_I32_RetI32 },
+ { "IiTS8iiip", (void*)&CallInterpreter_This_S8_I32_I32_I32_RetI32 },
+ { "IiTS8ip", (void*)&CallInterpreter_This_S8_I32_RetI32 },
+ { "IiTS8p", (void*)&CallInterpreter_This_S8_RetI32 },
+ { "IiTiS12p", (void*)&CallInterpreter_This_I32_S12_RetI32 },
+ { "IiTiS8p", (void*)&CallInterpreter_This_I32_S8_RetI32 },
+ { "IiTiiiip", (void*)&CallInterpreter_This_I32_I32_I32_I32_RetI32 },
+ { "IiTiiip", (void*)&CallInterpreter_This_I32_I32_I32_RetI32 },
+ { "IiTiip", (void*)&CallInterpreter_This_I32_I32_RetI32 },
+ { "IiTip", (void*)&CallInterpreter_This_I32_RetI32 },
+ { "IiTp", (void*)&CallInterpreter_This_RetI32 },
+ { "Iidp", (void*)&CallInterpreter_F64_RetI32 },
+ { "IiiS8p", (void*)&CallInterpreter_I32_S8_RetI32 },
+ { "Iiiiiiiiiip", (void*)&CallInterpreter_I32_I32_I32_I32_I32_I32_I32_I32_RetI32 },
+ { "Iiiiiiiiip", (void*)&CallInterpreter_I32_I32_I32_I32_I32_I32_I32_RetI32 },
+ { "Iiiiiiiip", (void*)&CallInterpreter_I32_I32_I32_I32_I32_I32_RetI32 },
+ { "Iiiiiiip", (void*)&CallInterpreter_I32_I32_I32_I32_I32_RetI32 },
+ { "Iiiiiip", (void*)&CallInterpreter_I32_I32_I32_I32_RetI32 },
+ { "Iiiiip", (void*)&CallInterpreter_I32_I32_I32_RetI32 },
+ { "Iiiip", (void*)&CallInterpreter_I32_I32_RetI32 },
+ { "Iiip", (void*)&CallInterpreter_I32_RetI32 },
+ { "Iip", (void*)&CallInterpreter_Void_RetI32 },
+ { "Ildp", (void*)&CallInterpreter_F64_RetI64 },
+ { "Ilillp", (void*)&CallInterpreter_I32_I64_I64_RetI64 },
+ { "Ililp", (void*)&CallInterpreter_I32_I64_RetI64 },
+ { "Ilip", (void*)&CallInterpreter_I32_RetI64 },
+ { "Illlp", (void*)&CallInterpreter_I64_I64_RetI64 },
+ { "Ilp", (void*)&CallInterpreter_Void_RetI64 },
+ { "IvTS12p", (void*)&CallInterpreter_This_S12_RetVoid },
+ { "IvTS32p", (void*)&CallInterpreter_This_S32_RetVoid },
+ { "IvTS8S8p", (void*)&CallInterpreter_This_S8_S8_RetVoid },
+ { "IvTS8ip", (void*)&CallInterpreter_This_S8_I32_RetVoid },
+ { "IvTS8p", (void*)&CallInterpreter_This_S8_RetVoid },
+ { "IvTiS8p", (void*)&CallInterpreter_This_I32_S8_RetVoid },
+ { "IvTiiS8S8iip", (void*)&CallInterpreter_This_I32_I32_S8_S8_I32_I32_RetVoid },
+ { "IvTiiiiip", (void*)&CallInterpreter_This_I32_I32_I32_I32_I32_RetVoid },
+ { "IvTiiiip", (void*)&CallInterpreter_This_I32_I32_I32_I32_RetVoid },
+ { "IvTiiip", (void*)&CallInterpreter_This_I32_I32_I32_RetVoid },
+ { "IvTiip", (void*)&CallInterpreter_This_I32_I32_RetVoid },
+ { "IvTip", (void*)&CallInterpreter_This_I32_RetVoid },
+ { "IvTp", (void*)&CallInterpreter_This_RetVoid },
+ { "Ivdiip", (void*)&CallInterpreter_F64_I32_I32_RetVoid },
+ { "Ivfiip", (void*)&CallInterpreter_F32_I32_I32_RetVoid },
+ { "Iviiiip", (void*)&CallInterpreter_I32_I32_I32_I32_RetVoid },
+ { "Iviiip", (void*)&CallInterpreter_I32_I32_I32_RetVoid },
+ { "Iviip", (void*)&CallInterpreter_I32_I32_RetVoid },
+ { "Ivip", (void*)&CallInterpreter_I32_RetVoid },
+ { "Ivp", (void*)&CallInterpreter_Void_RetVoid },
+};
+
+const size_t g_wasmGeneratedPortableEntryPointThunksCount = sizeof(g_wasmGeneratedPortableEntryPointThunks) / sizeof(g_wasmGeneratedPortableEntryPointThunks[0]);
diff --git a/src/native/libs/build-native.cmd b/src/native/libs/build-native.cmd
index 0369fc8db2e684..0c96c064b590aa 100644
--- a/src/native/libs/build-native.cmd
+++ b/src/native/libs/build-native.cmd
@@ -63,6 +63,9 @@ if "%__TargetOS%"=="android" (
if "%__TargetOS%"=="browser" (
set __CrossTarget=1
)
+if "%__TargetOS%"=="wasi" (
+ set __CrossTarget=1
+)
if %__CrossTarget% EQU 0 (
call "%__repoRoot%\eng\native\version\copy_version_files.cmd"
diff --git a/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj b/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj
index 32cac2b06a82d4..701a1d062af057 100644
--- a/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj
+++ b/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj
@@ -81,7 +81,8 @@
TargetOS="$(_RunGeneratorTargetOS)"
PInvokeOutputPath="$(GeneratorOutputPath)callhelpers-pinvoke.cpp"
ReversePInvokeOutputPath="$(GeneratorOutputPath)callhelpers-reverse.cpp"
- InterpToNativeOutputPath="$(GeneratorOutputPath)callhelpers-interp-to-managed.cpp">
+ InterpToNativeOutputPath="$(GeneratorOutputPath)callhelpers-interp-to-managed.cpp"
+ PortableEntryPointOutputPath="$(GeneratorOutputPath)callhelpers-portable-entrypoints.cpp">
diff --git a/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs b/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs
index e5183182df8088..821214d6e6420b 100644
--- a/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs
+++ b/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs
@@ -57,6 +57,160 @@ private static string CallFuncName(IEnumerable args, string result, bool
return $"CallFunc_{paramTypes}_Ret{result}{(isPortableEntryPointCall ? "_PE" : "")}";
}
+ ///
+ /// Emits the R2R-to-interpreter side of the portable entrypoint boundary: the thunks that
+ /// g_wasmThunks' _PE helpers call into. Struct returns are not emitted yet; their
+ /// wasm sret convention across this boundary is not settled, and no _PE helper exercises one.
+ ///
+ public void GeneratePortableEntryPoints(IEnumerable cookies, string outputPath)
+ {
+ using TempFileName tmpFileName = new();
+ using (var w = File.CreateText(tmpFileName.Path))
+ {
+ EmitPortableEntryPoints(w, cookies);
+ }
+
+ if (Utils.CopyIfDifferent(tmpFileName.Path, outputPath, useHash: false))
+ Log.LogMessage(MessageImportance.Low, $"Generating portable entrypoint thunks to '{outputPath}'.");
+ else
+ Log.LogMessage(MessageImportance.Low, $"Portable entrypoint thunks in {outputPath} are unchanged.");
+ }
+
+ private static string CallInterpreterName(IEnumerable args, string result)
+ {
+ var paramTypes = args.Any() ? string.Join("_", args.Select(static t => SignatureMapper.TokenToNameType(t))) : "Void";
+
+ return $"CallInterpreter_{paramTypes}_Ret{result}";
+ }
+
+ private static bool IsStructToken(string token) => PortableEntryPointThunkSignature.IsStructToken(token);
+
+ private static void EmitPortableEntryPoints(StreamWriter w, IEnumerable cookies)
+ {
+ var signatures = cookies.Distinct().OrderBy(c => c, StringComparer.Ordinal).ToArray();
+
+ w.Write(
+ """
+ // Licensed to the .NET Foundation under one or more agreements.
+ // The .NET Foundation licenses this file to you under the MIT license.
+ //
+
+ //
+ // GENERATED FILE, DON'T EDIT
+ // Generated by coreclr InterpToNativeGenerator
+ //
+
+ #include
+ #include
+ #include "callhelpers.hpp"
+
+ void ExecuteInterpretedMethodWithArgs_PortableEntryPoint(PCODE portableEntrypoint, TransitionBlock* block, size_t argsSize, int8_t* retBuff);
+
+ namespace
+ {
+
+ """);
+
+ var emitted = new List<(string Key, string Name)>();
+
+ foreach (var signature in signatures)
+ {
+ var tokens = SignatureMapper.ParseSignatureTokens(signature);
+ if (!IsPortableEntryPointCall(tokens))
+ continue;
+
+ string returnToken = tokens[0];
+
+ tokens.RemoveAt(tokens.Count - 1);
+ RemoveAsyncCallMarker(tokens);
+ var args = Args(tokens);
+
+ string retName = SignatureMapper.TokenToNameType(returnToken);
+ string name = CallInterpreterName(args, retName);
+ if (emitted.Any(e => e.Name == name))
+ continue;
+
+ // crossgen2 passes a struct return through an explicit buffer parameter rather than by value.
+ // Returning the struct by value instead would make the compiler insert its own sret pointer
+ // ahead of callersStackPointer, silently transposing the two.
+ bool isStructReturn = IsStructToken(returnToken);
+ string retType = isStructReturn ? "void" : SignatureMapper.TokenToNativeType(returnToken);
+ bool isVoid = isStructReturn || returnToken == "v";
+
+ var parameters = PortableEntryPointThunkSignature.GetDeclaredParameters(args, isStructReturn);
+ var declTypes = parameters.Select(static p => p.NativeType).ToList();
+ var namedArgs = parameters.Select(static p => $"{p.NativeType} {p.Name}").ToList();
+
+ int slot = 0;
+ var stores = new List();
+ for (int i = 0; i < args.Count; i++)
+ {
+ string t = args[i];
+ if (t[0] == 'A')
+ slot = (slot + 1) & ~1;
+
+ // A float or double occupies its slot as itself: casting to int64_t would convert the
+ // value rather than store its bits, and the interpreter reads the slot back through
+ // ARG_F32/ARG_F64.
+ if (SignatureMapper.TryGetMultiSlotToken(t, out int multiSlotCount))
+ {
+ for (int s = 0; s < multiSlotCount; s++)
+ stores.Add($" transitionBlock.args[{slot + s}] = {PortableEntryPointThunkSignature.MultiSlotParameterName(i, s, multiSlotCount)};");
+ }
+ else
+ {
+ stores.Add(t switch
+ {
+ _ when IsStructToken(t) => $" memcpy(&transitionBlock.args[{slot}], arg{i}, {SignatureMapper.GetStructSize(t)});",
+ "f" => $" *(float*)&transitionBlock.args[{slot}] = arg{i};",
+ "d" => $" *(double*)&transitionBlock.args[{slot}] = arg{i};",
+ _ => $" transitionBlock.args[{slot}] = (int64_t)arg{i};",
+ });
+ }
+
+ slot += SignatureMapper.TokenToSlotCount(t);
+ }
+
+ string declArgs = declTypes.Count > 0 ? ", " + string.Join(", ", declTypes) : "";
+ string sigArgs = namedArgs.Count > 0 ? string.Join(", ", namedArgs) + ", " : "";
+
+ w.WriteLine($" FCDECL{declTypes.Count}({retType}, {name}{declArgs});");
+ w.WriteLine($" WASM_CALLABLE_FUNC_{declTypes.Count + 1}({retType}, {name}, {sigArgs}PCODE portableEntrypoint)");
+ w.WriteLine(" {");
+ w.WriteLine(" struct");
+ w.WriteLine(" {");
+ w.WriteLine(" TransitionBlock block;");
+ if (slot > 0)
+ w.WriteLine($" int64_t args[{slot}];");
+ w.WriteLine(" } transitionBlock;");
+ w.WriteLine(" transitionBlock.block.m_ReturnAddress = 0;");
+ w.WriteLine(" transitionBlock.block.m_StackPointer = callersStackPointer;");
+ foreach (var store in stores)
+ w.WriteLine(store);
+ if (slot > 0)
+ w.WriteLine(" static_assert(offsetof(decltype(transitionBlock), args) == sizeof(TransitionBlock), \"Args array must be at a TransitionBlock offset from the start of the block\");");
+ w.WriteLine();
+ if (!isStructReturn)
+ w.WriteLine(isVoid ? " void * result = NULL;" : $" {retType} result = 0;");
+ string retBuffArg = isStructReturn ? "retBuf" : "(int8_t*)&result";
+ w.WriteLine($" ExecuteInterpretedMethodWithArgs_PortableEntryPoint(portableEntrypoint, &transitionBlock.block, {(slot > 0 ? "sizeof(transitionBlock.args)" : "0")}, {retBuffArg});");
+ w.WriteLine(isVoid ? " return;" : " return result;");
+ w.WriteLine(" }");
+ w.WriteLine();
+
+ emitted.Add(("I" + signature, name));
+ }
+
+ w.WriteLine("}");
+ w.WriteLine();
+ w.WriteLine("const StringToWasmSigThunk g_wasmGeneratedPortableEntryPointThunks[] = {");
+ foreach (var (key, name) in emitted)
+ w.WriteLine($" {{ \"{key}\", (void*)&{name} }},");
+ w.WriteLine("};");
+ w.WriteLine();
+ w.WriteLine("const size_t g_wasmGeneratedPortableEntryPointThunksCount = sizeof(g_wasmGeneratedPortableEntryPointThunks) / sizeof(g_wasmGeneratedPortableEntryPointThunks[0]);");
+ }
+
private static void Emit(StreamWriter w, IEnumerable cookies)
{
// Use OrderBy because Order() is not available on .NET Framework
@@ -128,7 +282,39 @@ private static void Emit(StreamWriter w, IEnumerable cookies)
var args = Args(tokens);
- var portableEntryPointComma = args.Count > 0 ? ", " : "";
+ var argTypes = new List();
+ foreach (var argToken in args)
+ {
+ if (SignatureMapper.TryGetMultiSlotToken(argToken, out int multiSlotCount))
+ {
+ string slotType = SignatureMapper.MultiSlotElementNativeType(argToken);
+ for (int s = 0; s < multiSlotCount; s++)
+ argTypes.Add(slotType);
+ }
+ else
+ {
+ argTypes.Add(SignatureMapper.TokenToNativeType(argToken));
+ }
+ }
+
+ var argValues = ArgsWithSlotOffsets(args).ToList();
+
+ // R2R code takes a struct return through an explicit buffer that follows the stack
+ // pointer and 'this', so the pointer this calls through must spell it out. Declaring
+ // the call as returning the struct would make the compiler insert its own sret
+ // pointer at parameter 0 instead, ahead of the stack pointer. Native callees keep the
+ // by-value form, which is what their own C ABI gives them.
+ bool isStructReturn = isPortableEntryPointCall && IsStructToken(returnToken);
+ if (isStructReturn)
+ {
+ argTypes.Insert(args.Count > 0 && args[0] == "T" ? 1 : 0, "int8_t*");
+ argValues.Insert(args.Count > 0 && args[0] == "T" ? 1 : 0, "pRet");
+ }
+
+ string fptrReturn = isStructReturn ? "void" : result.nativeType;
+ string assignResult = isStructReturn || result.isVoid ? "" : $"*(({result.nativeType}*)pRet) = ";
+
+ var portableEntryPointComma = argTypes.Count > 0 ? ", " : "";
var portableEntrypointDeclaration = isPortableEntryPointCall ? portableEntryPointComma + "PCODE" : "";
var portableEntrypointParam = isPortableEntryPointCall ? portableEntryPointComma + "pPortableEntryPoint" : "";
var portableEntrypointStackDeclaration = isPortableEntryPointCall ? "int*, " : "";
@@ -139,8 +325,8 @@ private static void Emit(StreamWriter w, IEnumerable cookies)
{{(isPortableEntryPointCall ? "NOINLINE " : "")}}static void {{CallFuncName(args, SignatureMapper.TokenToNameType(returnToken), isPortableEntryPointCall)}}(PCODE {{(isPortableEntryPointCall ? "pPortableEntryPoint" : "pcode")}}, int8_t* pArgs, int8_t* pRet)
{{{(isPortableEntryPointCall ? "\n alignas(16) int framePointer = TERMINATE_R2R_STACK_WALK;" : "")}}
- {{result.nativeType}} (*fptr)({{portableEntrypointStackDeclaration}}{{string.Join(", ", args.Select(static t => SignatureMapper.TokenToNativeType(t)))}}{{portableEntrypointDeclaration}}) = {{portableEntrypointPointerRD}}({{result.nativeType}} ({{portableEntrypointPointerRD}}*)({{portableEntrypointStackDeclaration}}{{string.Join(", ", args.Select(static t => SignatureMapper.TokenToNativeType(t)))}}{{portableEntrypointDeclaration}})){{(isPortableEntryPointCall ? "(pPortableEntryPoint)" : "pcode")}};
- {{(result.isVoid ? "" : "*" + "((" + result.nativeType + "*)pRet) = ")}}(*fptr)({{portableEntrypointStackParam}}{{string.Join(", ", ArgsWithSlotOffsets(args))}}{{portableEntrypointParam}});
+ {{fptrReturn}} (*fptr)({{portableEntrypointStackDeclaration}}{{string.Join(", ", argTypes)}}{{portableEntrypointDeclaration}}) = {{portableEntrypointPointerRD}}({{fptrReturn}} ({{portableEntrypointPointerRD}}*)({{portableEntrypointStackDeclaration}}{{string.Join(", ", argTypes)}}{{portableEntrypointDeclaration}})){{(isPortableEntryPointCall ? "(pPortableEntryPoint)" : "pcode")}};
+ {{assignResult}}(*fptr)({{portableEntrypointStackParam}}{{string.Join(", ", argValues)}}{{portableEntrypointParam}});
}
""");
@@ -173,11 +359,6 @@ private static void Emit(StreamWriter w, IEnumerable cookies)
""");
- static List Args(List tokens)
- {
- return tokens.Count > 1 ? tokens.GetRange(1, tokens.Count - 1) : new List();
- }
-
static List ArgsWithSlotOffsets(List args)
{
var result = new List();
@@ -189,7 +370,17 @@ static List ArgsWithSlotOffsets(List args)
slot = (slot + 1) & ~1;
}
- result.Add($"{SignatureMapper.TokenToArgType(token)}({slot})");
+ if (SignatureMapper.TryGetMultiSlotToken(token, out int multiSlotCount))
+ {
+ string slotArgType = SignatureMapper.MultiSlotElementArgType(token);
+ for (int s = 0; s < multiSlotCount; s++)
+ result.Add($"{slotArgType}({slot + s})");
+ }
+ else
+ {
+ result.Add($"{SignatureMapper.TokenToArgType(token)}({slot})");
+ }
+
slot += SignatureMapper.TokenToSlotCount(token);
}
@@ -204,19 +395,25 @@ static List ArgsWithSlotOffsets(List args)
return new(returnToken == "v", SignatureMapper.TokenToNativeType(returnToken));
}
- static bool IsPortableEntryPointCall(List tokens)
- {
- return tokens.Count > 0 && tokens[tokens.Count - 1] == "p";
- }
+ }
- static bool RemoveAsyncCallMarker(List tokens)
- {
- int asyncMarkerIndex = tokens.IndexOf("a");
- if (asyncMarkerIndex < 0)
- return false;
+ private static List Args(List tokens)
+ {
+ return tokens.Count > 1 ? tokens.GetRange(1, tokens.Count - 1) : new List();
+ }
- tokens.RemoveAt(asyncMarkerIndex);
- return true;
- }
+ private static bool IsPortableEntryPointCall(List tokens)
+ {
+ return tokens.Count > 0 && tokens[tokens.Count - 1] == "p";
+ }
+
+ private static bool RemoveAsyncCallMarker(List tokens)
+ {
+ int asyncMarkerIndex = tokens.IndexOf("a");
+ if (asyncMarkerIndex < 0)
+ return false;
+
+ tokens.RemoveAt(asyncMarkerIndex);
+ return true;
}
}
diff --git a/src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs b/src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs
index f033d8b39ca3ed..7e92fbfd71beb4 100644
--- a/src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs
+++ b/src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs
@@ -31,6 +31,9 @@ public class ManagedToNativeGenerator : Task
[Required, NotNull]
public string? InterpToNativeOutputPath { get; set; }
+
+ /// Set only by the in-tree RunGenerator target; app builds use the runtime's copy.
+ public string? PortableEntryPointOutputPath { get; set; }
public string? CacheFilePath { get; set; }
public bool IsLibraryMode { get; set; }
@@ -117,7 +120,19 @@ private void ExecuteInternal(LogAdapter log)
// The signatures should be in the form of a string where the first character represents the return type and the
// following characters represent the argument types. The type characters should match those used by the
// SignatureMapper.CharToNativeType method.
- string[] pregeneratedInterpreterToNativeSignatures = Array.Empty(); // Currently none, but can be added here as needed in the future.
+ // The instance ('T') shapes below are the ones a Blazor app hits on startup. The static shapes on
+ // the last line were hand-written in vm/wasm/helpers.cpp before this generator emitted the table.
+ string[] pregeneratedInterpreterToNativeSignatures = new[]
+ {
+ "iTp", "iTip", "iTiip", "iTiiip", "iTiiiip",
+ "vTp", "vTip", "vTiip", "vTiiip", "vTiiiip", "vTiiiiip",
+ "iTS8p", "iTS8ip", "iTS8S8p", "iTS8iS8ip", "iTS8iiip", "iTiS8p",
+ "iTS12p", "iTS12ip", "iTiS12p",
+ "vTS8p", "vTS8ip", "vTS8S8p", "vTiS8p", "vTS12p", "vTS32p", "vTiiS8S8iip",
+ "S8Tp", "S8Tip", "S8Tiiip", "S12Tiip", "S12Tiiip", "S12TS12ip", "S16Tp", "S1Tp",
+ "S12TiS12ip",
+ "viiiip", "iiiiiiiip", "iiiiiiiiip", "idp", "ldp", "iiS8p", "iS8p", "S16l2ip",
+ };
IEnumerable cookies = pinvoke.Generate(PInvokeModules, IgnoredPInvokeModules, PInvokeOutputPath, ReversePInvokeOutputPath);
cookies = cookies.Concat(internalCallCollector.GetSignatures());
@@ -126,6 +141,9 @@ private void ExecuteInternal(LogAdapter log)
var m2n = new InterpToNativeGenerator(log);
m2n.Generate(cookies, InterpToNativeOutputPath);
+ if (!string.IsNullOrEmpty(PortableEntryPointOutputPath))
+ m2n.GeneratePortableEntryPoints(cookies, PortableEntryPointOutputPath);
+
if (!string.IsNullOrEmpty(CacheFilePath))
{
IEnumerable cacheLines = PInvokeModules
diff --git a/src/tasks/WasmAppBuilder/coreclr/PortableEntryPointThunkSignature.cs b/src/tasks/WasmAppBuilder/coreclr/PortableEntryPointThunkSignature.cs
new file mode 100644
index 00000000000000..2f70740df0807f
--- /dev/null
+++ b/src/tasks/WasmAppBuilder/coreclr/PortableEntryPointThunkSignature.cs
@@ -0,0 +1,70 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Generic;
+
+namespace Microsoft.WebAssembly.Build.Tasks.CoreClr;
+
+// Parameter layout of a generated R2R-to-interpreter thunk. Shared with the tests, which compare
+// it against the wasm signature crossgen2 computes for the same key, so it must stay free of
+// MSBuild dependencies.
+internal static class PortableEntryPointThunkSignature
+{
+ internal readonly struct Parameter
+ {
+ public Parameter(string nativeType, string name)
+ {
+ NativeType = nativeType;
+ Name = name;
+ }
+
+ public string NativeType { get; }
+ public string Name { get; }
+ }
+
+ public static bool IsStructToken(string token) => token[0] is 'S' or 'A' && token.Length > 1;
+
+ // A struct argument arrives as the address of its interpreter stack slot.
+ public static string DeclType(string token)
+ => IsStructToken(token) ? "int8_t*" : SignatureMapper.TokenToNativeType(token);
+
+ ///
+ /// The name of one slot of a multi-slot argument, which occupies several wasm parameters.
+ ///
+ public static string MultiSlotParameterName(int argIndex, int slot, int slotCount)
+ => slotCount == 2 ? $"arg{argIndex}{(slot == 0 ? "Lo" : "Hi")}" : $"arg{argIndex}_{slot}";
+
+ ///
+ /// The thunk's declared C parameters, in the order crossgen2 passes them:
+ /// (callersStackPointer, [this], retBuf, args..., portableEntrypoint). The stack pointer comes
+ /// from the WASM_CALLABLE_FUNC macro and the entrypoint is appended by the caller, so neither
+ /// appears here.
+ ///
+ public static List GetDeclaredParameters(IReadOnlyList args, bool isStructReturn)
+ {
+ var parameters = new List(args.Count + 1);
+ for (int i = 0; i < args.Count; i++)
+ {
+ if (SignatureMapper.TryGetMultiSlotToken(args[i], out int slotCount))
+ {
+ string slotType = SignatureMapper.MultiSlotElementNativeType(args[i]);
+ for (int slot = 0; slot < slotCount; slot++)
+ parameters.Add(new Parameter(slotType, MultiSlotParameterName(i, slot, slotCount)));
+ }
+ else
+ {
+ parameters.Add(new Parameter(DeclType(args[i]), $"arg{i}"));
+ }
+ }
+
+ if (isStructReturn)
+ {
+ // The hidden return buffer follows the 'this' pointer rather than preceding it.
+ // See WasmR2RToInterpreterThunkNode.EmitCode: retBufLocalIndex = 1 + (hasThis ? 1 : 0).
+ int retBufIndex = args.Count > 0 && args[0] == "T" ? 1 : 0;
+ parameters.Insert(retBufIndex, new Parameter("int8_t*", "retBuf"));
+ }
+
+ return parameters;
+ }
+}
diff --git a/src/tasks/WasmAppBuilder/coreclr/SignatureMapper.Tokens.cs b/src/tasks/WasmAppBuilder/coreclr/SignatureMapper.Tokens.cs
new file mode 100644
index 00000000000000..a025fb04d702cb
--- /dev/null
+++ b/src/tasks/WasmAppBuilder/coreclr/SignatureMapper.Tokens.cs
@@ -0,0 +1,177 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+
+namespace Microsoft.WebAssembly.Build.Tasks.CoreClr;
+
+// The half of SignatureMapper that maps signature tokens to native types. It is kept free of
+// MSBuild dependencies so that tests can compile it directly; the reflection-based half needs a
+// LogAdapter and cannot be linked on its own.
+internal static partial class SignatureMapper
+{
+ ///
+ /// Parses a signature string into individual tokens.
+ /// Single-char types produce one-char tokens; struct encodings produce multi-char tokens like
+ /// "S8" or "A32", and a multi-slot parameter produces a two-char token like "l2" or "V4".
+ /// The 'a' and 'p' suffixes are included as their own tokens.
+ ///
+ public static List ParseSignatureTokens(string signature)
+ {
+ var tokens = new List();
+ int i = 0;
+ while (i < signature.Length)
+ {
+ if (signature[i] is 'S' or 'A')
+ {
+ int start = i;
+ i++; // skip 'S'/'A'
+ while (i < signature.Length && char.IsDigit(signature[i]))
+ i++;
+ tokens.Add(signature.Substring(start, i - start));
+ }
+ else if (signature[i] is 'l' or 'V' && i + 1 < signature.Length && char.IsDigit(signature[i + 1]))
+ {
+ tokens.Add(signature.Substring(i, 2));
+ i += 2;
+ }
+ else
+ {
+ tokens.Add(signature[i].ToString());
+ i++;
+ }
+ }
+
+ return tokens;
+ }
+
+ ///
+ /// True for a token describing a type passed by value across several wasm parameters ("l2",
+ /// "V2", "V4"), reporting how many it occupies. A caller has to expand it into one parameter per
+ /// slot; the single-type accessors below still reject it so an unexpanded token cannot slip
+ /// through as one parameter.
+ ///
+ public static bool TryGetMultiSlotToken(string token, out int slotCount)
+ {
+ if (token.Length == 2 && token[0] is 'l' or 'V' && char.IsDigit(token[1]))
+ {
+ slotCount = token[1] - '0';
+ return true;
+ }
+
+ slotCount = 0;
+ return false;
+ }
+
+ /// The type of one slot of a multi-slot token.
+ public static string MultiSlotElementNativeType(string token) => token[0] switch
+ {
+ 'l' => "int64_t",
+ _ => throw new NotSupportedException($"Multi-slot token '{token}' has no native type these thunks can spell")
+ };
+
+ /// The interpreter stack accessor for one slot of a multi-slot token.
+ public static string MultiSlotElementArgType(string token) => token[0] switch
+ {
+ 'l' => "ARG_I64",
+ _ => throw new NotSupportedException($"Multi-slot token '{token}' has no interpreter stack accessor")
+ };
+
+ private static void RejectMultiSlotToken(string token)
+ {
+ if (TryGetMultiSlotToken(token, out _))
+ throw new NotSupportedException($"Multi-slot signature token '{token}' must be expanded into one parameter per slot");
+ }
+
+ public static string TokenToNativeType(string token)
+ {
+ RejectMultiSlotToken(token);
+ return token[0] switch
+ {
+ 'v' => "void",
+ 'i' => "int32_t",
+ 'l' => "int64_t",
+ 'f' => "float",
+ 'd' => "double",
+ 'S' or 'A' => "int32_t",
+ 'T' => "int32_t",
+ 'p' => "PCODE",
+ _ => throw new InvalidSignatureCharException(token[0])
+ };
+ }
+
+ public static string TokenToNameType(string token)
+ {
+ if (TryGetMultiSlotToken(token, out int multiSlotCount))
+ return $"{char.ToUpperInvariant(token[0])}{multiSlotCount}";
+
+ return token[0] switch
+ {
+ 'v' => "Void",
+ 'i' => "I32",
+ 'l' => "I64",
+ 'f' => "F32",
+ 'd' => "F64",
+ 'S' or 'A' => token,
+ 'T' => "This",
+ 'p' => "PE",
+ _ => throw new InvalidSignatureCharException(token[0])
+ };
+ }
+
+ public static string TokenToArgType(string token)
+ {
+ RejectMultiSlotToken(token);
+ return token[0] switch
+ {
+ 'i' => "ARG_I32",
+ 'l' => "ARG_I64",
+ 'f' => "ARG_F32",
+ 'd' => "ARG_F64",
+ 'S' or 'A' => "ARG_IND",
+ 'T' => "ARG_I32",
+ _ => throw new InvalidSignatureCharException(token[0])
+ };
+ }
+
+ ///
+ /// Returns the number of INTERP_STACK_SLOT_SIZE slots consumed by a token.
+ /// Struct tokens consume max((size + 7) / 8, 1) slots; all others consume 1.
+ ///
+ public static int TokenToSlotCount(string token)
+ {
+ if (TryGetMultiSlotToken(token, out int multiSlotCount))
+ {
+ // An i64 slot is one interpreter slot; a v128 slot would be two, but nothing spells one yet.
+ return token[0] == 'l'
+ ? multiSlotCount
+ : throw new NotSupportedException($"Multi-slot token '{token}' has no known interpreter slot size");
+ }
+
+ if (token[0] is not ('S' or 'A') || token.Length < 2)
+ return 1;
+
+ int size = GetStructSize(token);
+ return Math.Max((size + 7) / 8, 1);
+ }
+
+ internal static int GetStructSize(string token)
+ {
+ return int.Parse(token.Substring(1));
+ }
+
+ // Legacy single-char overloads — still used by consumers that don't encounter S tokens.
+ public static string CharToNativeType(char c) => TokenToNativeType(c.ToString());
+ public static string CharToNameType(char c) => TokenToNameType(c.ToString());
+ public static string CharToArgType(char c) => TokenToArgType(c.ToString());
+
+ public static bool IsVoidSignature(string signature) => signature[0] == 'v';
+}
+
+internal sealed class InvalidSignatureCharException : Exception
+{
+ public char Char { get; private set; }
+
+ public InvalidSignatureCharException(char c) : base($"Can't handle signature '{c}'") => Char = c;
+}
diff --git a/src/tasks/WasmAppBuilder/coreclr/SignatureMapper.cs b/src/tasks/WasmAppBuilder/coreclr/SignatureMapper.cs
index c1f07ec01067d9..395cd7dbb75049 100644
--- a/src/tasks/WasmAppBuilder/coreclr/SignatureMapper.cs
+++ b/src/tasks/WasmAppBuilder/coreclr/SignatureMapper.cs
@@ -13,7 +13,7 @@ namespace Microsoft.WebAssembly.Build.Tasks.CoreClr;
// Computes Wasm signature strings from reflection metadata.
// The signature string format is documented in docs/design/coreclr/botr/readytorun-format.md
// (section "Wasm Signature String Encoding").
-internal static class SignatureMapper
+internal static partial class SignatureMapper
{
// Hardcoded struct layouts for types that crossgen2 encodes as struct tokens.
// The fully general case is handled by crossgen2's type system; these
@@ -262,126 +262,6 @@ private static bool HasNumericElementType(Type t)
return sb.ToString();
}
- ///
- /// Parses a signature string into individual tokens.
- /// Single-char types produce one-char tokens; struct encodings produce multi-char tokens like
- /// "S8" or "A32", and a multi-slot parameter produces a two-char token like "l2" or "V4".
- /// The 'a' and 'p' suffixes are included as their own tokens.
- ///
- public static List ParseSignatureTokens(string signature)
- {
- var tokens = new List();
- int i = 0;
- while (i < signature.Length)
- {
- if (signature[i] is 'S' or 'A')
- {
- int start = i;
- i++; // skip 'S'/'A'
- while (i < signature.Length && char.IsDigit(signature[i]))
- i++;
- tokens.Add(signature.Substring(start, i - start));
- }
- else if (signature[i] is 'l' or 'V' && i + 1 < signature.Length && char.IsDigit(signature[i + 1]))
- {
- tokens.Add(signature.Substring(i, 2));
- i += 2;
- }
- else
- {
- tokens.Add(signature[i].ToString());
- i++;
- }
- }
-
- return tokens;
- }
-
- ///
- /// True for a token describing a type passed by value across several wasm parameters
- /// ("l2", "V2", "V4"). Interop signatures do not use these today.
- ///
- private static bool IsMultiSlotToken(string token)
- => token.Length == 2 && token[0] is 'l' or 'V' && char.IsDigit(token[1]);
-
- private static void RejectMultiSlotToken(string token)
- {
- if (IsMultiSlotToken(token))
- throw new NotSupportedException($"Multi-slot signature token '{token}' is not supported in interop thunks");
- }
-
- public static string TokenToNativeType(string token)
- {
- RejectMultiSlotToken(token);
- return token[0] switch
- {
- 'v' => "void",
- 'i' => "int32_t",
- 'l' => "int64_t",
- 'f' => "float",
- 'd' => "double",
- 'S' or 'A' => "int32_t",
- 'T' => "int32_t",
- 'p' => "PCODE",
- _ => throw new InvalidSignatureCharException(token[0])
- };
- }
-
- public static string TokenToNameType(string token)
- {
- RejectMultiSlotToken(token);
- return token[0] switch
- {
- 'v' => "Void",
- 'i' => "I32",
- 'l' => "I64",
- 'f' => "F32",
- 'd' => "F64",
- 'S' or 'A' => token,
- 'T' => "This",
- 'p' => "PE",
- _ => throw new InvalidSignatureCharException(token[0])
- };
- }
-
- public static string TokenToArgType(string token)
- {
- RejectMultiSlotToken(token);
- return token[0] switch
- {
- 'i' => "ARG_I32",
- 'l' => "ARG_I64",
- 'f' => "ARG_F32",
- 'd' => "ARG_F64",
- 'S' or 'A' => "ARG_IND",
- 'T' => "ARG_I32",
- _ => throw new InvalidSignatureCharException(token[0])
- };
- }
-
- ///
- /// Returns the number of INTERP_STACK_SLOT_SIZE slots consumed by a token.
- /// Struct tokens consume max((size + 7) / 8, 1) slots; all others consume 1.
- ///
- public static int TokenToSlotCount(string token)
- {
- if (token[0] is not ('S' or 'A') || token.Length < 2)
- return 1;
-
- int size = GetStructSize(token);
- return Math.Max((size + 7) / 8, 1);
- }
-
- internal static int GetStructSize(string token)
- {
- return int.Parse(token.Substring(1));
- }
-
- // Legacy single-char overloads — still used by consumers that don't encounter S tokens.
- public static string CharToNativeType(char c) => TokenToNativeType(c.ToString());
- public static string CharToNameType(char c) => TokenToNameType(c.ToString());
- public static string CharToArgType(char c) => TokenToArgType(c.ToString());
-
public static string TypeToNameType(Type t, LogAdapter log)
{
char? c = TypeToChar(t, log, out _);
@@ -390,13 +270,4 @@ public static string TypeToNameType(Type t, LogAdapter log)
return CharToNameType(c.Value);
}
-
- public static bool IsVoidSignature(string signature) => signature[0] == 'v';
-}
-
-internal sealed class InvalidSignatureCharException : Exception
-{
- public char Char { get; private set; }
-
- public InvalidSignatureCharException(char c) : base($"Can't handle signature '{c}'") => Char = c;
}
diff --git a/src/tests/readytorun/wasm/WasmInterpreterTransitions/WasmInterpreterTransitions.cs b/src/tests/readytorun/wasm/WasmInterpreterTransitions/WasmInterpreterTransitions.cs
new file mode 100644
index 00000000000000..b93ee83ed46229
--- /dev/null
+++ b/src/tests/readytorun/wasm/WasmInterpreterTransitions/WasmInterpreterTransitions.cs
@@ -0,0 +1,165 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime;
+using System.Runtime.CompilerServices;
+using Xunit;
+
+namespace System.Runtime
+{
+ [AttributeUsage(AttributeTargets.Method)]
+ internal sealed class BypassReadyToRunAttribute : Attribute
+ {
+ }
+}
+
+///
+/// Exercises the thunks that carry a call between R2R code and the interpreter on wasm. Methods
+/// marked are skipped by crossgen2 and so run interpreted,
+/// while the rest of the assembly is compiled, which puts a thunk on every call between the two.
+///
+/// Each case returns values chosen so that a wrong answer is visible. That matters more than usual
+/// here: the stack pointer, the hidden return buffer, 'this' and every by-reference argument are
+/// all i32, so a thunk whose parameters are in the wrong order still passes wasm's call_indirect
+/// type check. It does not trap — it writes through the wrong pointer, and the only symptom is
+/// data that quietly comes back wrong.
+///
+public class WasmInterpreterTransitions
+{
+ private const int A = 0x11223344;
+ private const int B = 0x55667788;
+ private const int C = 0x1234567;
+ private const long Wide = 0x1122334455667788;
+
+ public struct S8
+ {
+ public int A;
+ public int B;
+ }
+
+ public struct S12
+ {
+ public int A;
+ public int B;
+ public int C;
+ }
+
+ public struct S16
+ {
+ public long A;
+ public long B;
+ }
+
+ private readonly int _state = C;
+
+ [Fact]
+ public static void TestEntryPoint()
+ {
+ WasmInterpreterTransitions self = new();
+
+ // R2R -> interpreted, struct returns. The return buffer follows 'this' for an instance
+ // method and the stack pointer for a static one, which is where the two forms differ.
+ S8 s8 = self.InterpretedInstanceReturnsS8(A);
+ Assert.Equal(A, s8.A);
+ Assert.Equal(C, s8.B);
+
+ S8 staticS8 = InterpretedStaticReturnsS8(A);
+ Assert.Equal(A, staticS8.A);
+ Assert.Equal(B, staticS8.B);
+
+ S16 s16 = self.InterpretedInstanceReturnsS16();
+ Assert.Equal(Wide, s16.A);
+ Assert.Equal(C, s16.B);
+
+ S16 staticS16 = InterpretedStaticReturnsS16(Wide, A);
+ Assert.Equal(Wide, staticS16.A);
+ Assert.Equal(A, staticS16.B);
+
+ // A struct that is not a whole number of 8-byte slots, passed and returned.
+ S12 s12 = self.InterpretedInstanceRoundTripsS12(new S12 { A = A, B = B, C = C }, A);
+ Assert.Equal(B, s12.A);
+ Assert.Equal(C, s12.B);
+ Assert.Equal(A, s12.C);
+
+ // R2R -> interpreted, scalar and void shapes.
+ Assert.Equal(A + C, self.InterpretedInstanceReturnsI32(A));
+ Assert.Equal(Wide, InterpretedStaticReturnsI64(1.5));
+ Assert.Equal(A + B + C, InterpretedStaticSumsFour(A, B, C, 0));
+ Assert.Equal(A, self.InterpretedInstanceMixedScalars(1.5f, 2.5, Wide));
+
+ // A struct argument arrives as the address of its interpreter stack slot.
+ Assert.Equal(A + B, self.InterpretedInstanceTakesS8(new S8 { A = A, B = B }));
+
+ s_sideEffect = 0;
+ self.InterpretedInstanceTakesS8ReturnsVoid(new S8 { A = A, B = B });
+ Assert.Equal(A + B, s_sideEffect);
+
+ // interpreted -> R2R, the opposite direction over the same shapes.
+ Assert.Equal(A + C, self.InterpretedCallsBackIntoR2R());
+
+ S16 fromInterpreter = self.InterpretedCallsR2RReturningS16();
+ Assert.Equal(Wide, fromInterpreter.A);
+ Assert.Equal(C, fromInterpreter.B);
+ }
+
+ private static int s_sideEffect;
+
+ [BypassReadyToRun]
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private S8 InterpretedInstanceReturnsS8(int a) => new S8 { A = a, B = _state };
+
+ [BypassReadyToRun]
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static S8 InterpretedStaticReturnsS8(int a) => new S8 { A = a, B = B };
+
+ [BypassReadyToRun]
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private S16 InterpretedInstanceReturnsS16() => new S16 { A = Wide, B = _state };
+
+ [BypassReadyToRun]
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static S16 InterpretedStaticReturnsS16(long wide, int a) => new S16 { A = wide, B = a };
+
+ [BypassReadyToRun]
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private S12 InterpretedInstanceRoundTripsS12(S12 value, int a) => new S12 { A = value.B, B = value.C, C = a };
+
+ [BypassReadyToRun]
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private int InterpretedInstanceReturnsI32(int a) => a + _state;
+
+ [BypassReadyToRun]
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static long InterpretedStaticReturnsI64(double unused) => Wide;
+
+ [BypassReadyToRun]
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static int InterpretedStaticSumsFour(int a, int b, int c, int d) => a + b + c + d;
+
+ [BypassReadyToRun]
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private int InterpretedInstanceMixedScalars(float f, double d, long l) => l == Wide && f == 1.5f && d == 2.5 ? A : 0;
+
+ [BypassReadyToRun]
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private int InterpretedInstanceTakesS8(S8 value) => value.A + value.B;
+
+ [BypassReadyToRun]
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private void InterpretedInstanceTakesS8ReturnsVoid(S8 value) => s_sideEffect = value.A + value.B;
+
+ [BypassReadyToRun]
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private int InterpretedCallsBackIntoR2R() => R2RInstanceReturnsI32(A);
+
+ [BypassReadyToRun]
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private S16 InterpretedCallsR2RReturningS16() => R2RInstanceReturnsS16();
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private int R2RInstanceReturnsI32(int a) => a + _state;
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private S16 R2RInstanceReturnsS16() => new S16 { A = Wide, B = _state };
+}
diff --git a/src/tests/readytorun/wasm/WasmInterpreterTransitions/WasmInterpreterTransitions.csproj b/src/tests/readytorun/wasm/WasmInterpreterTransitions/WasmInterpreterTransitions.csproj
new file mode 100644
index 00000000000000..092b4f60c765b9
--- /dev/null
+++ b/src/tests/readytorun/wasm/WasmInterpreterTransitions/WasmInterpreterTransitions.csproj
@@ -0,0 +1,14 @@
+
+
+ true
+ true
+
+ true
+ true
+
+
+
+
+