diff --git a/src/coreclr/vm/CMakeLists.txt b/src/coreclr/vm/CMakeLists.txt index 73755a194c7537..c7b9dc5f7bf721 100644 --- a/src/coreclr/vm/CMakeLists.txt +++ b/src/coreclr/vm/CMakeLists.txt @@ -920,7 +920,8 @@ elseif(CLR_CMAKE_TARGET_ARCH_WASM) ${ARCH_SOURCES_DIR}/calldescrworkerwasm.cpp ${ARCH_SOURCES_DIR}/profiler.cpp ${ARCH_SOURCES_DIR}/helpers.cpp - ${ARCH_SOURCES_DIR}/callhelpers.cpp + ${ARCH_SOURCES_DIR}/callhelpers-interp-to-managed.cpp + ${ARCH_SOURCES_DIR}/callhelpers-reverse.cpp exceptionhandling.cpp gcinfodecoder.cpp ) diff --git a/src/coreclr/vm/wasm/callhelpers.cpp b/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp similarity index 55% rename from src/coreclr/vm/wasm/callhelpers.cpp rename to src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp index c23d1e36473042..1e1a0ababe7505 100644 --- a/src/coreclr/vm/wasm/callhelpers.cpp +++ b/src/coreclr/vm/wasm/callhelpers-interp-to-managed.cpp @@ -19,624 +19,551 @@ namespace { - void CallFunc_F64_RetF64 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_Void_RetF64(PCODE pcode, int8_t* pArgs, int8_t* pRet) + { + double (*fptr)() = (double (*)())pcode; + *((double*)pRet) = (*fptr)(); + } + + static void CallFunc_F64_RetF64(PCODE pcode, int8_t* pArgs, int8_t* pRet) { double (*fptr)(double) = (double (*)(double))pcode; *((double*)pRet) = (*fptr)(ARG_F64(0)); } - void CallFunc_F64_F64_RetF64 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_F64_F64_RetF64(PCODE pcode, int8_t* pArgs, int8_t* pRet) { double (*fptr)(double, double) = (double (*)(double, double))pcode; *((double*)pRet) = (*fptr)(ARG_F64(0), ARG_F64(1)); } - void CallFunc_F64_F64_F64_RetF64 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_F64_F64_F64_RetF64(PCODE pcode, int8_t* pArgs, int8_t* pRet) { double (*fptr)(double, double, double) = (double (*)(double, double, double))pcode; *((double*)pRet) = (*fptr)(ARG_F64(0), ARG_F64(1), ARG_F64(2)); } - void CallFunc_F64_I32_RetF64 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_F64_I32_RetF64(PCODE pcode, int8_t* pArgs, int8_t* pRet) { double (*fptr)(double, int32_t) = (double (*)(double, int32_t))pcode; *((double*)pRet) = (*fptr)(ARG_F64(0), ARG_I32(1)); } - void CallFunc_I32_RetF64 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_RetF64(PCODE pcode, int8_t* pArgs, int8_t* pRet) { double (*fptr)(int32_t) = (double (*)(int32_t))pcode; *((double*)pRet) = (*fptr)(ARG_I32(0)); } - void CallFunc_F32_RetF32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_F32_RetF32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { float (*fptr)(float) = (float (*)(float))pcode; *((float*)pRet) = (*fptr)(ARG_F32(0)); } - void CallFunc_F32_F32_RetF32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_F32_F32_RetF32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { float (*fptr)(float, float) = (float (*)(float, float))pcode; *((float*)pRet) = (*fptr)(ARG_F32(0), ARG_F32(1)); } - void CallFunc_F32_F32_F32_RetF32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_F32_F32_F32_RetF32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { float (*fptr)(float, float, float) = (float (*)(float, float, float))pcode; *((float*)pRet) = (*fptr)(ARG_F32(0), ARG_F32(1), ARG_F32(2)); } - void CallFunc_F32_I32_RetF32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_F32_I32_RetF32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { float (*fptr)(float, int32_t) = (float (*)(float, int32_t))pcode; *((float*)pRet) = (*fptr)(ARG_F32(0), ARG_I32(1)); } - void CallFunc_Void_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_Void_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)() = (int32_t (*)())pcode; *((int32_t*)pRet) = (*fptr)(); } - void CallFunc_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_F64_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) + { + int32_t (*fptr)(double, int32_t) = (int32_t (*)(double, int32_t))pcode; + *((int32_t*)pRet) = (*fptr)(ARG_F64(0), ARG_I32(1)); + } + + static void CallFunc_F32_F32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) + { + int32_t (*fptr)(float, float) = (int32_t (*)(float, float))pcode; + *((int32_t*)pRet) = (*fptr)(ARG_F32(0), ARG_F32(1)); + } + + static void CallFunc_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t) = (int32_t (*)(int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_I32(0)); } - void CallFunc_I32_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_F64_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) + { + int32_t (*fptr)(int32_t, double) = (int32_t (*)(int32_t, double))pcode; + *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_F64(1)); + } + + static void CallFunc_I32_F32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) + { + int32_t (*fptr)(int32_t, float) = (int32_t (*)(int32_t, float))pcode; + *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_F32(1)); + } + + static void CallFunc_I32_F32_I32_I32_F32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) + { + int32_t (*fptr)(int32_t, float, int32_t, int32_t, float) = (int32_t (*)(int32_t, float, int32_t, int32_t, float))pcode; + *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_F32(1), ARG_I32(2), ARG_I32(3), ARG_F32(4)); + } + + 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; *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1)); } - void CallFunc_I32_I32_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I32_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2)); } - void CallFunc_I32_I32_I32_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I32_I32_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t, int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3)); } - void CallFunc_I32_I32_I32_I32_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I32_I32_I32_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t, int32_t, int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4)); } - void CallFunc_I32_I32_I32_I32_I32_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I32_I32_I32_I32_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5)); } - void CallFunc_I32_I32_I32_I32_I32_I32_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I32_I32_I32_I32_I32_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t))pcode; *((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)); } - void CallFunc_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t))pcode; *((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)); } - void CallFunc_I32_I32_I32_I32_I64_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { - int32_t (*fptr)(int32_t, int32_t, int32_t, int32_t, int64_t) = (int32_t (*)(int32_t, int32_t, int32_t, int32_t, int64_t))pcode; - *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I64(4)); + int32_t (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t))pcode; + *((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), ARG_I32(14), ARG_I32(15), ARG_I32(16)); } - void CallFunc_I32_I32_I32_I64_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I32_I32_I64_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int32_t, int64_t) = (int32_t (*)(int32_t, int32_t, int32_t, int64_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I64(3)); } - void CallFunc_I32_I32_I32_IND_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I32_I32_IND_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t, int32_t, int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_IND(3), ARG_I32(4)); } - void CallFunc_I32_I32_I64_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I32_I64_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int64_t) = (int32_t (*)(int32_t, int32_t, int64_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I64(2)); } - void CallFunc_I32_I32_I64_I32_I32_I64_I64_I32_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) - { - int32_t (*fptr)(int32_t, int32_t, int64_t, int32_t, int32_t, int64_t, int64_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int64_t, int32_t, int32_t, int64_t, int64_t, int32_t, int32_t))pcode; - *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I64(2), ARG_I32(3), ARG_I32(4), ARG_I64(5), ARG_I64(6), ARG_I32(7), ARG_I32(8)); - } - - void CallFunc_I32_I32_IND_I32_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I32_IND_I32_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t, int32_t, int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1), ARG_IND(2), ARG_I32(3), ARG_I32(4)); } - void CallFunc_I32_I32_IND_I32_I32_IND_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I32_IND_I32_I32_IND_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1), ARG_IND(2), ARG_I32(3), ARG_I32(4), ARG_IND(5)); } - void CallFunc_I32_I64_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I64_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int64_t) = (int32_t (*)(int32_t, int64_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I64(1)); } - void CallFunc_I32_I64_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I64_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int64_t, int32_t) = (int32_t (*)(int32_t, int64_t, int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I64(1), ARG_I32(2)); } - void CallFunc_I32_I64_I32_I32_I32_I64_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I64_I32_I32_I32_I64_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int64_t, int32_t, int32_t, int32_t, int64_t) = (int32_t (*)(int32_t, int64_t, int32_t, int32_t, int32_t, int64_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I64(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I64(5)); } - void CallFunc_I32_I64_I64_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I64_I64_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int64_t, int64_t) = (int32_t (*)(int32_t, int64_t, int64_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I64(1), ARG_I64(2)); } - void CallFunc_I32_I64_I64_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I64_I64_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int64_t, int64_t, int32_t) = (int32_t (*)(int32_t, int64_t, int64_t, int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I64(1), ARG_I64(2), ARG_I32(3)); } - void CallFunc_I32_IND_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_IND_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) + { + int32_t (*fptr)(int32_t, int32_t) = (int32_t (*)(int32_t, int32_t))pcode; + *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_IND(1)); + } + + static void CallFunc_I32_IND_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_IND(1), ARG_I32(2)); } - void CallFunc_I32_IND_I32_I32_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_IND_I32_I32_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t, int32_t, int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_IND(1), ARG_I32(2), ARG_I32(3), ARG_I32(4)); } - void CallFunc_I32_IND_I32_IND_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_IND_I32_IND_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t, int32_t, int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_IND(1), ARG_I32(2), ARG_IND(3), ARG_I32(4)); } - void CallFunc_I64_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) - { - int32_t (*fptr)(int64_t) = (int32_t (*)(int64_t))pcode; - *((int32_t*)pRet) = (*fptr)(ARG_I64(0)); - } - - void CallFunc_I64_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_IND_IND_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { - int32_t (*fptr)(int64_t, int32_t) = (int32_t (*)(int64_t, int32_t))pcode; - *((int32_t*)pRet) = (*fptr)(ARG_I64(0), ARG_I32(1)); - } - - void CallFunc_I64_I32_I32_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) - { - int32_t (*fptr)(int64_t, int32_t, int32_t, int32_t) = (int32_t (*)(int64_t, int32_t, int32_t, int32_t))pcode; - *((int32_t*)pRet) = (*fptr)(ARG_I64(0), ARG_I32(1), ARG_I32(2), ARG_I32(3)); - } - - void CallFunc_I64_I32_I32_I32_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) - { - int32_t (*fptr)(int64_t, int32_t, int32_t, int32_t, int32_t) = (int32_t (*)(int64_t, int32_t, int32_t, int32_t, int32_t))pcode; - *((int32_t*)pRet) = (*fptr)(ARG_I64(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4)); - } - - void CallFunc_I64_I32_I32_I32_I64_I64_I32_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) - { - int32_t (*fptr)(int64_t, int32_t, int32_t, int32_t, int64_t, int64_t, int32_t, int32_t) = (int32_t (*)(int64_t, int32_t, int32_t, int32_t, int64_t, int64_t, int32_t, int32_t))pcode; - *((int32_t*)pRet) = (*fptr)(ARG_I64(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I64(4), ARG_I64(5), ARG_I32(6), ARG_I32(7)); + int32_t (*fptr)(int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t))pcode; + *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_IND(1), ARG_IND(2)); } - void CallFunc_I64_I32_I64_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I64_I32_I64_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int64_t, int32_t, int64_t, int32_t) = (int32_t (*)(int64_t, int32_t, int64_t, int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_I64(0), ARG_I32(1), ARG_I64(2), ARG_I32(3)); } - void CallFunc_IND_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_IND_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t) = (int32_t (*)(int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_IND(0)); } - void CallFunc_IND_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_IND_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t) = (int32_t (*)(int32_t, int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_IND(0), ARG_I32(1)); } - void CallFunc_IND_I32_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_IND_I32_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_IND(0), ARG_I32(1), ARG_I32(2)); } - void CallFunc_IND_I32_I32_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_IND_I32_I32_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t, int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_IND(0), ARG_I32(1), ARG_I32(2), ARG_I32(3)); } - void CallFunc_IND_I32_I32_I32_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_IND_I32_I32_I32_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t, int32_t, int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_IND(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4)); } - void CallFunc_IND_I32_I32_I32_I32_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_IND_I32_I32_I32_I32_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_IND(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5)); } - void CallFunc_IND_I32_IND_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_IND_I32_IND_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t, int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_IND(0), ARG_I32(1), ARG_IND(2), ARG_I32(3)); } - void CallFunc_IND_I32_IND_IND_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_IND_I32_IND_IND_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t, int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_IND(0), ARG_I32(1), ARG_IND(2), ARG_IND(3)); } - void CallFunc_IND_IND_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) - { - int32_t (*fptr)(int32_t, int32_t) = (int32_t (*)(int32_t, int32_t))pcode; - *((int32_t*)pRet) = (*fptr)(ARG_IND(0), ARG_IND(1)); - } - - void CallFunc_IND_IND_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_IND_IND_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_IND(0), ARG_IND(1), ARG_I32(2)); } - void CallFunc_IND_IND_I32_I32_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_IND_IND_I32_I32_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t, int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_IND(0), ARG_IND(1), ARG_I32(2), ARG_I32(3)); } - void CallFunc_IND_IND_I32_IND_RetI32 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_IND_IND_I32_IND_RetI32(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t, int32_t, int32_t) = (int32_t (*)(int32_t, int32_t, int32_t, int32_t))pcode; *((int32_t*)pRet) = (*fptr)(ARG_IND(0), ARG_IND(1), ARG_I32(2), ARG_IND(3)); } - void CallFunc_Void_RetI64 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_Void_RetI64(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int64_t (*fptr)() = (int64_t (*)())pcode; *((int64_t*)pRet) = (*fptr)(); } - void CallFunc_I32_RetI64 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_RetI64(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int64_t (*fptr)(int32_t) = (int64_t (*)(int32_t))pcode; *((int64_t*)pRet) = (*fptr)(ARG_I32(0)); } - void CallFunc_I32_I32_RetI64 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I32_RetI64(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int64_t (*fptr)(int32_t, int32_t) = (int64_t (*)(int32_t, int32_t))pcode; *((int64_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1)); } - void CallFunc_I32_I32_I32_I64_RetI64 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I32_I32_I64_RetI64(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int64_t (*fptr)(int32_t, int32_t, int32_t, int64_t) = (int64_t (*)(int32_t, int32_t, int32_t, int64_t))pcode; *((int64_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I64(3)); } - void CallFunc_I32_I64_RetI64 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I64_RetI64(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int64_t (*fptr)(int32_t, int64_t) = (int64_t (*)(int32_t, int64_t))pcode; *((int64_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I64(1)); } - void CallFunc_I32_I64_I32_RetI64 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I64_I32_RetI64(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int64_t (*fptr)(int32_t, int64_t, int32_t) = (int64_t (*)(int32_t, int64_t, int32_t))pcode; *((int64_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I64(1), ARG_I32(2)); } - void CallFunc_I32_I64_I64_RetI64 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I64_I64_RetI64(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int64_t (*fptr)(int32_t, int64_t, int64_t) = (int64_t (*)(int32_t, int64_t, int64_t))pcode; *((int64_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I64(1), ARG_I64(2)); } - void CallFunc_I64_I64_RetI64 (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I64_I64_RetI64(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int64_t (*fptr)(int64_t, int64_t) = (int64_t (*)(int64_t, int64_t))pcode; *((int64_t*)pRet) = (*fptr)(ARG_I64(0), ARG_I64(1)); } - void CallFunc_Void_RetIND (PCODE pcode, int8_t *pArgs, int8_t *pRet) - { - int32_t (*fptr)() = (int32_t (*)())pcode; - PORTABILITY_ASSERT("Indirect struct return is not yet implemented."); - *((int32_t*)pRet) = (*fptr)(); - } - - void CallFunc_I32_RetIND (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_RetIND(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t) = (int32_t (*)(int32_t))pcode; PORTABILITY_ASSERT("Indirect struct return is not yet implemented."); *((int32_t*)pRet) = (*fptr)(ARG_I32(0)); } - void CallFunc_I32_I32_RetIND (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I32_RetIND(PCODE pcode, int8_t* pArgs, int8_t* pRet) { int32_t (*fptr)(int32_t, int32_t) = (int32_t (*)(int32_t, int32_t))pcode; PORTABILITY_ASSERT("Indirect struct return is not yet implemented."); *((int32_t*)pRet) = (*fptr)(ARG_I32(0), ARG_I32(1)); } - void CallFunc_Void_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_Void_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)() = (void (*)())pcode; (*fptr)(); } - void CallFunc_F64_I32_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_F64_I32_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(double, int32_t, int32_t) = (void (*)(double, int32_t, int32_t))pcode; (*fptr)(ARG_F64(0), ARG_I32(1), ARG_I32(2)); } - void CallFunc_F32_I32_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_F32_I32_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(float, int32_t, int32_t) = (void (*)(float, int32_t, int32_t))pcode; (*fptr)(ARG_F32(0), ARG_I32(1), ARG_I32(2)); } - void CallFunc_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t) = (void (*)(int32_t))pcode; (*fptr)(ARG_I32(0)); } - void CallFunc_I32_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t) = (void (*)(int32_t, int32_t))pcode; (*fptr)(ARG_I32(0), ARG_I32(1)); } - void CallFunc_I32_I32_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I32_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t))pcode; (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2)); } - void CallFunc_I32_I32_I32_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I32_I32_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t, int32_t))pcode; (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3)); } - void CallFunc_I32_I32_I32_I32_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I32_I32_I32_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t, int32_t, int32_t))pcode; (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4)); } - void CallFunc_I32_I32_I32_I32_I32_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I32_I32_I32_I32_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t))pcode; (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5)); } - void CallFunc_I32_I32_I32_I32_I32_I32_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) - { - void (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t))pcode; - (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5), ARG_I32(6)); - } - - void CallFunc_I32_I32_I32_I32_I32_I32_I32_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) - { - void (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t))pcode; - (*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)); - } - - void CallFunc_I32_I32_I32_I32_I64_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) - { - void (*fptr)(int32_t, int32_t, int32_t, int32_t, int64_t, int32_t) = (void (*)(int32_t, int32_t, int32_t, int32_t, int64_t, int32_t))pcode; - (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I64(4), ARG_I32(5)); - } - - void CallFunc_I32_I32_I32_I64_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) - { - void (*fptr)(int32_t, int32_t, int32_t, int64_t, int32_t) = (void (*)(int32_t, int32_t, int32_t, int64_t, int32_t))pcode; - (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_I64(3), ARG_I32(4)); - } - - void CallFunc_I32_I32_I32_IND_IND_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I32_I32_IND_IND_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t, int32_t, int32_t))pcode; (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_IND(3), ARG_IND(4)); } - void CallFunc_I32_I32_I32_IND_IND_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I32_I32_IND_IND_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t))pcode; (*fptr)(ARG_I32(0), ARG_I32(1), ARG_I32(2), ARG_IND(3), ARG_IND(4), ARG_I32(5)); } - void CallFunc_I32_I32_IND_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I32_IND_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t))pcode; (*fptr)(ARG_I32(0), ARG_I32(1), ARG_IND(2)); } - void CallFunc_I32_I32_IND_IND_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I32_IND_IND_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t, int32_t, int32_t))pcode; (*fptr)(ARG_I32(0), ARG_I32(1), ARG_IND(2), ARG_IND(3), ARG_I32(4)); } - void CallFunc_I32_I32_IND_IND_I32_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_I32_IND_IND_I32_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t))pcode; (*fptr)(ARG_I32(0), ARG_I32(1), ARG_IND(2), ARG_IND(3), ARG_I32(4), ARG_I32(5)); } - void CallFunc_I32_I64_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) - { - void (*fptr)(int32_t, int64_t) = (void (*)(int32_t, int64_t))pcode; - (*fptr)(ARG_I32(0), ARG_I64(1)); - } - - void CallFunc_I32_I64_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) - { - void (*fptr)(int32_t, int64_t, int32_t) = (void (*)(int32_t, int64_t, int32_t))pcode; - (*fptr)(ARG_I32(0), ARG_I64(1), ARG_I32(2)); - } - - void CallFunc_I32_I64_I32_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) - { - void (*fptr)(int32_t, int64_t, int32_t, int32_t) = (void (*)(int32_t, int64_t, int32_t, int32_t))pcode; - (*fptr)(ARG_I32(0), ARG_I64(1), ARG_I32(2), ARG_I32(3)); - } - - void CallFunc_I32_I64_I32_I32_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_IND_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { - void (*fptr)(int32_t, int64_t, int32_t, int32_t, int32_t) = (void (*)(int32_t, int64_t, int32_t, int32_t, int32_t))pcode; - (*fptr)(ARG_I32(0), ARG_I64(1), ARG_I32(2), ARG_I32(3), ARG_I32(4)); + void (*fptr)(int32_t, int32_t) = (void (*)(int32_t, int32_t))pcode; + (*fptr)(ARG_I32(0), ARG_IND(1)); } - void CallFunc_I32_IND_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_IND_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t))pcode; (*fptr)(ARG_I32(0), ARG_IND(1), ARG_I32(2)); } - void CallFunc_I32_IND_IND_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I32_IND_IND_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t, int32_t))pcode; (*fptr)(ARG_I32(0), ARG_IND(1), ARG_IND(2), ARG_I32(3)); } - void CallFunc_I64_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_I64_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int64_t) = (void (*)(int64_t))pcode; (*fptr)(ARG_I64(0)); } - void CallFunc_I64_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) - { - void (*fptr)(int64_t, int32_t) = (void (*)(int64_t, int32_t))pcode; - (*fptr)(ARG_I64(0), ARG_I32(1)); - } - - void CallFunc_I64_I32_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) - { - void (*fptr)(int64_t, int32_t, int32_t) = (void (*)(int64_t, int32_t, int32_t))pcode; - (*fptr)(ARG_I64(0), ARG_I32(1), ARG_I32(2)); - } - - void CallFunc_I64_I32_I32_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) - { - void (*fptr)(int64_t, int32_t, int32_t, int32_t) = (void (*)(int64_t, int32_t, int32_t, int32_t))pcode; - (*fptr)(ARG_I64(0), ARG_I32(1), ARG_I32(2), ARG_I32(3)); - } - - void CallFunc_I64_I32_I32_I32_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) - { - void (*fptr)(int64_t, int32_t, int32_t, int32_t, int32_t) = (void (*)(int64_t, int32_t, int32_t, int32_t, int32_t))pcode; - (*fptr)(ARG_I64(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4)); - } - - void CallFunc_I64_I64_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) - { - void (*fptr)(int64_t, int64_t, int32_t) = (void (*)(int64_t, int64_t, int32_t))pcode; - (*fptr)(ARG_I64(0), ARG_I64(1), ARG_I32(2)); - } - - void CallFunc_IND_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_IND_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t) = (void (*)(int32_t))pcode; (*fptr)(ARG_IND(0)); } - void CallFunc_IND_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_IND_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t) = (void (*)(int32_t, int32_t))pcode; (*fptr)(ARG_IND(0), ARG_I32(1)); } - void CallFunc_IND_I32_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_IND_I32_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t))pcode; (*fptr)(ARG_IND(0), ARG_I32(1), ARG_I32(2)); } - void CallFunc_IND_I32_I32_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_IND_I32_I32_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t, int32_t))pcode; (*fptr)(ARG_IND(0), ARG_I32(1), ARG_I32(2), ARG_I32(3)); } - void CallFunc_IND_I32_I32_I32_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_IND_I32_I32_I32_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t, int32_t, int32_t))pcode; (*fptr)(ARG_IND(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4)); } - void CallFunc_IND_I32_I32_I32_I32_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_IND_I32_I32_I32_I32_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t))pcode; (*fptr)(ARG_IND(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5)); } - void CallFunc_IND_I32_I32_I32_I32_I32_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_IND_I32_I32_I32_I32_I32_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t))pcode; (*fptr)(ARG_IND(0), ARG_I32(1), ARG_I32(2), ARG_I32(3), ARG_I32(4), ARG_I32(5), ARG_I32(6)); } - void CallFunc_IND_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_IND_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t, int32_t))pcode; (*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)); } - void CallFunc_IND_IND_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_IND_IND_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t) = (void (*)(int32_t, int32_t))pcode; (*fptr)(ARG_IND(0), ARG_IND(1)); } - void CallFunc_IND_IND_I32_I32_I32_RetVoid (PCODE pcode, int8_t *pArgs, int8_t *pRet) + static void CallFunc_IND_IND_I32_I32_I32_RetVoid(PCODE pcode, int8_t* pArgs, int8_t* pRet) { void (*fptr)(int32_t, int32_t, int32_t, int32_t, int32_t) = (void (*)(int32_t, int32_t, int32_t, int32_t, int32_t))pcode; (*fptr)(ARG_IND(0), ARG_IND(1), ARG_I32(2), ARG_I32(3), ARG_I32(4)); } - } const StringToWasmSigThunk g_wasmThunks[] = { + { "d", (void*)&CallFunc_Void_RetF64 }, { "dd", (void*)&CallFunc_F64_RetF64 }, { "ddd", (void*)&CallFunc_F64_F64_RetF64 }, { "dddd", (void*)&CallFunc_F64_F64_F64_RetF64 }, @@ -647,7 +574,12 @@ const StringToWasmSigThunk g_wasmThunks[] = { { "ffff", (void*)&CallFunc_F32_F32_F32_RetF32 }, { "ffi", (void*)&CallFunc_F32_I32_RetF32 }, { "i", (void*)&CallFunc_Void_RetI32 }, + { "idi", (void*)&CallFunc_F64_I32_RetI32 }, + { "iff", (void*)&CallFunc_F32_F32_RetI32 }, { "ii", (void*)&CallFunc_I32_RetI32 }, + { "iid", (void*)&CallFunc_I32_F64_RetI32 }, + { "iif", (void*)&CallFunc_I32_F32_RetI32 }, + { "iifiif", (void*)&CallFunc_I32_F32_I32_I32_F32_RetI32 }, { "iii", (void*)&CallFunc_I32_I32_RetI32 }, { "iiii", (void*)&CallFunc_I32_I32_I32_RetI32 }, { "iiiii", (void*)&CallFunc_I32_I32_I32_I32_RetI32 }, @@ -655,11 +587,10 @@ const StringToWasmSigThunk g_wasmThunks[] = { { "iiiiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_RetI32 }, { "iiiiiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_I32_RetI32 }, { "iiiiiiiiiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_RetI32 }, - { "iiiiil", (void*)&CallFunc_I32_I32_I32_I32_I64_RetI32 }, + { "iiiiiiiiiiiiiiiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_I32_RetI32 }, { "iiiil", (void*)&CallFunc_I32_I32_I32_I64_RetI32 }, { "iiiini", (void*)&CallFunc_I32_I32_I32_IND_I32_RetI32 }, { "iiil", (void*)&CallFunc_I32_I32_I64_RetI32 }, - { "iiiliillii", (void*)&CallFunc_I32_I32_I64_I32_I32_I64_I64_I32_I32_RetI32 }, { "iiinii", (void*)&CallFunc_I32_I32_IND_I32_I32_RetI32 }, { "iiiniin", (void*)&CallFunc_I32_I32_IND_I32_I32_IND_RetI32 }, { "iil", (void*)&CallFunc_I32_I64_RetI32 }, @@ -667,14 +598,11 @@ const StringToWasmSigThunk g_wasmThunks[] = { { "iiliiil", (void*)&CallFunc_I32_I64_I32_I32_I32_I64_RetI32 }, { "iill", (void*)&CallFunc_I32_I64_I64_RetI32 }, { "iilli", (void*)&CallFunc_I32_I64_I64_I32_RetI32 }, + { "iin", (void*)&CallFunc_I32_IND_RetI32 }, { "iini", (void*)&CallFunc_I32_IND_I32_RetI32 }, { "iiniii", (void*)&CallFunc_I32_IND_I32_I32_I32_RetI32 }, { "iinini", (void*)&CallFunc_I32_IND_I32_IND_I32_RetI32 }, - { "il", (void*)&CallFunc_I64_RetI32 }, - { "ili", (void*)&CallFunc_I64_I32_RetI32 }, - { "iliii", (void*)&CallFunc_I64_I32_I32_I32_RetI32 }, - { "iliiii", (void*)&CallFunc_I64_I32_I32_I32_I32_RetI32 }, - { "iliiillii", (void*)&CallFunc_I64_I32_I32_I32_I64_I64_I32_I32_RetI32 }, + { "iinn", (void*)&CallFunc_I32_IND_IND_RetI32 }, { "ilili", (void*)&CallFunc_I64_I32_I64_I32_RetI32 }, { "in", (void*)&CallFunc_IND_RetI32 }, { "ini", (void*)&CallFunc_IND_I32_RetI32 }, @@ -684,7 +612,6 @@ const StringToWasmSigThunk g_wasmThunks[] = { { "iniiiii", (void*)&CallFunc_IND_I32_I32_I32_I32_I32_RetI32 }, { "inini", (void*)&CallFunc_IND_I32_IND_I32_RetI32 }, { "ininn", (void*)&CallFunc_IND_I32_IND_IND_RetI32 }, - { "inn", (void*)&CallFunc_IND_IND_RetI32 }, { "inni", (void*)&CallFunc_IND_IND_I32_RetI32 }, { "innii", (void*)&CallFunc_IND_IND_I32_I32_RetI32 }, { "innin", (void*)&CallFunc_IND_IND_I32_IND_RetI32 }, @@ -696,7 +623,6 @@ const StringToWasmSigThunk g_wasmThunks[] = { { "lili", (void*)&CallFunc_I32_I64_I32_RetI64 }, { "lill", (void*)&CallFunc_I32_I64_I64_RetI64 }, { "lll", (void*)&CallFunc_I64_I64_RetI64 }, - { "n", (void*)&CallFunc_Void_RetIND }, { "ni", (void*)&CallFunc_I32_RetIND }, { "nii", (void*)&CallFunc_I32_I32_RetIND }, { "v", (void*)&CallFunc_Void_RetVoid }, @@ -708,27 +634,16 @@ const StringToWasmSigThunk g_wasmThunks[] = { { "viiii", (void*)&CallFunc_I32_I32_I32_I32_RetVoid }, { "viiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_RetVoid }, { "viiiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_RetVoid }, - { "viiiiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_I32_RetVoid }, - { "viiiiiiii", (void*)&CallFunc_I32_I32_I32_I32_I32_I32_I32_I32_RetVoid }, - { "viiiili", (void*)&CallFunc_I32_I32_I32_I32_I64_I32_RetVoid }, - { "viiili", (void*)&CallFunc_I32_I32_I32_I64_I32_RetVoid }, { "viiinn", (void*)&CallFunc_I32_I32_I32_IND_IND_RetVoid }, { "viiinni", (void*)&CallFunc_I32_I32_I32_IND_IND_I32_RetVoid }, + { "viin", (void*)&CallFunc_I32_I32_IND_RetVoid }, { "viinni", (void*)&CallFunc_I32_I32_IND_IND_I32_RetVoid }, { "viin", (void*)&CallFunc_I32_I32_IND_RetVoid }, { "viinnii", (void*)&CallFunc_I32_I32_IND_IND_I32_I32_RetVoid }, - { "vil", (void*)&CallFunc_I32_I64_RetVoid }, - { "vili", (void*)&CallFunc_I32_I64_I32_RetVoid }, - { "vilii", (void*)&CallFunc_I32_I64_I32_I32_RetVoid }, - { "viliii", (void*)&CallFunc_I32_I64_I32_I32_I32_RetVoid }, + { "vin", (void*)&CallFunc_I32_IND_RetVoid }, { "vini", (void*)&CallFunc_I32_IND_I32_RetVoid }, { "vinni", (void*)&CallFunc_I32_IND_IND_I32_RetVoid }, { "vl", (void*)&CallFunc_I64_RetVoid }, - { "vli", (void*)&CallFunc_I64_I32_RetVoid }, - { "vlii", (void*)&CallFunc_I64_I32_I32_RetVoid }, - { "vliii", (void*)&CallFunc_I64_I32_I32_I32_RetVoid }, - { "vliiii", (void*)&CallFunc_I64_I32_I32_I32_I32_RetVoid }, - { "vlli", (void*)&CallFunc_I64_I64_I32_RetVoid }, { "vn", (void*)&CallFunc_IND_RetVoid }, { "vni", (void*)&CallFunc_IND_I32_RetVoid }, { "vnii", (void*)&CallFunc_IND_I32_I32_RetVoid }, @@ -742,53 +657,3 @@ const StringToWasmSigThunk g_wasmThunks[] = { }; const size_t g_wasmThunksCount = sizeof(g_wasmThunks) / sizeof(g_wasmThunks[0]); - -// Define reverse thunks here - -// Entry point for interpreted method execution from unmanaged code -class MethodDesc; - -// WASM-TODO: The method lookup would ideally be fully qualified assembly and then methodDef token. -// The current approach has limitations with overloaded methods. -extern "C" void LookupMethodByName(const char* fullQualifiedTypeName, const char* methodName, MethodDesc** ppMD); -extern "C" void ExecuteInterpretedMethodFromUnmanaged(MethodDesc* pMD, int8_t* args, size_t argSize, int8_t* ret); - -static MethodDesc* MD_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler_Void_RetVoid = nullptr; -static void Call_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler() -{ - // Lazy lookup of MethodDesc for the function export scenario. - if (!MD_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler_Void_RetVoid) - { - LookupMethodByName("System.Threading.ThreadPool, System.Private.CoreLib", "BackgroundJobHandler", &MD_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler_Void_RetVoid); - } - ExecuteInterpretedMethodFromUnmanaged(MD_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler_Void_RetVoid, nullptr, 0, nullptr); -} - -extern "C" void SystemJS_ExecuteBackgroundJobCallback() -{ - Call_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler(); -} - -static MethodDesc* MD_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler_Void_RetVoid = nullptr; -static void Call_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler() -{ - // Lazy lookup of MethodDesc for the function export scenario. - if (!MD_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler_Void_RetVoid) - { - LookupMethodByName("System.Threading.TimerQueue, System.Private.CoreLib", "TimerHandler", &MD_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler_Void_RetVoid); - } - ExecuteInterpretedMethodFromUnmanaged(MD_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler_Void_RetVoid, nullptr, 0, nullptr); -} - -extern "C" void SystemJS_ExecuteTimerCallback() -{ - Call_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler(); -} - -extern const ReverseThunkMapEntry g_ReverseThunks[] = -{ - { 100678287, { &MD_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler_Void_RetVoid, (void*)&Call_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler } }, - { 100678363, { &MD_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler_Void_RetVoid, (void*)&Call_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler } }, -}; - -const size_t g_ReverseThunksCount = sizeof(g_ReverseThunks) / sizeof(g_ReverseThunks[0]); diff --git a/src/coreclr/vm/wasm/callhelpers-reverse.cpp b/src/coreclr/vm/wasm/callhelpers-reverse.cpp new file mode 100644 index 00000000000000..2be9ba25e1b18e --- /dev/null +++ b/src/coreclr/vm/wasm/callhelpers-reverse.cpp @@ -0,0 +1,55 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// + +#include + +// Define reverse thunks here + +// Entry point for interpreted method execution from unmanaged code +class MethodDesc; + +// WASM-TODO: The method lookup would ideally be fully qualified assembly and then methodDef token. +// The current approach has limitations with overloaded methods. +extern "C" void LookupMethodByName(const char* fullQualifiedTypeName, const char* methodName, MethodDesc** ppMD); +extern "C" void ExecuteInterpretedMethodFromUnmanaged(MethodDesc* pMD, int8_t* args, size_t argSize, int8_t* ret); + +static MethodDesc* MD_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler_Void_RetVoid = nullptr; +static void Call_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler() +{ + // Lazy lookup of MethodDesc for the function export scenario. + if (!MD_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler_Void_RetVoid) + { + LookupMethodByName("System.Threading.ThreadPool, System.Private.CoreLib", "BackgroundJobHandler", &MD_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler_Void_RetVoid); + } + ExecuteInterpretedMethodFromUnmanaged(MD_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler_Void_RetVoid, nullptr, 0, nullptr); +} + +extern "C" void SystemJS_ExecuteBackgroundJobCallback() +{ + Call_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler(); +} + +static MethodDesc* MD_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler_Void_RetVoid = nullptr; +static void Call_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler() +{ + // Lazy lookup of MethodDesc for the function export scenario. + if (!MD_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler_Void_RetVoid) + { + LookupMethodByName("System.Threading.TimerQueue, System.Private.CoreLib", "TimerHandler", &MD_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler_Void_RetVoid); + } + ExecuteInterpretedMethodFromUnmanaged(MD_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler_Void_RetVoid, nullptr, 0, nullptr); +} + +extern "C" void SystemJS_ExecuteTimerCallback() +{ + Call_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler(); +} + +extern const ReverseThunkMapEntry g_ReverseThunks[] = +{ + { 100678287, { &MD_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler_Void_RetVoid, (void*)&Call_System_Private_CoreLib_System_Threading_ThreadPool_BackgroundJobHandler } }, + { 100678363, { &MD_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler_Void_RetVoid, (void*)&Call_System_Private_CoreLib_System_Threading_TimerQueue_TimerHandler } }, +}; + +const size_t g_ReverseThunksCount = sizeof(g_ReverseThunks) / sizeof(g_ReverseThunks[0]); diff --git a/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj b/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj index 77bdf6cafb6789..3fc33e370b1558 100644 --- a/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj +++ b/src/tasks/WasmAppBuilder/WasmAppBuilder.csproj @@ -16,6 +16,14 @@ + + + + + + + + @@ -50,4 +58,24 @@ + + + + + + + + + + + + + + + + diff --git a/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs b/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs new file mode 100644 index 00000000000000..6bf40b396ec20b --- /dev/null +++ b/src/tasks/WasmAppBuilder/coreclr/InterpToNativeGenerator.cs @@ -0,0 +1,135 @@ +// 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.IO; +using System.Linq; +using System.Text; +using System.Collections.Generic; +using System.Globalization; +using Microsoft.Build.Utilities; +using Microsoft.Build.Framework; +using System.Diagnostics.CodeAnalysis; +using WasmAppBuilder; + +using JoinedString; +// +// This class generates the g_wasmThunks array and CallFunc_* functions used by the CoreCLR interpreter to call native code on WASM. +// The generated code should be kept in sync with the corresponding CoreCLR runtime code that consumes these thunks and call functions. +// + +#nullable enable + +internal sealed class InterpToNativeGenerator +{ + private LogAdapter Log { get; set; } + + public InterpToNativeGenerator(LogAdapter log) => Log = log; + + public void Generate(IEnumerable cookies, string outputPath) + { + using TempFileName tmpFileName = new(); + using (var w = File.CreateText(tmpFileName.Path)) + { + Emit(w, cookies); + } + + if (Utils.CopyIfDifferent(tmpFileName.Path, outputPath, useHash: false)) + Log.LogMessage(MessageImportance.Low, $"Generating managed2native table to '{outputPath}'."); + else + Log.LogMessage(MessageImportance.Low, $"Managed2native table in {outputPath} is unchanged."); + } + + private static string SignatureToArguments(string signature) + { + if (signature.Length <= 1) + return "void"; + + return string.Join(", ", signature.Skip(1).Select(static c => SignatureMapper.CharToNativeType(c))); + } + + private static string CallFuncName(IEnumerable args, string result) + { + var paramTypes = args.Any() ? args.Join("_", (p, i) => SignatureMapper.CharToNameType(p)).ToString() : "Void"; + + return $"CallFunc_{paramTypes}_Ret{result}"; + } + + private static void Emit(StreamWriter w, IEnumerable cookies) + { + // Use OrderBy because Order() is not available on .NET Framework + var signatures = cookies.OrderBy(c => c).Distinct().ToArray(); + Array.Sort(signatures, StringComparer.Ordinal); + + 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 + + // Arguments are passed on the stack with each argument aligned to INTERP_STACK_SLOT_SIZE. + #define ARG_ADDR(i) (pArgs + (i * INTERP_STACK_SLOT_SIZE)) + #define ARG_IND(i) ((int32_t)((int32_t*)ARG_ADDR(i))) + #define ARG_I32(i) (*(int32_t*)ARG_ADDR(i)) + #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)) + + namespace + { + """); + + foreach (var signature in signatures) + { + try + { + var result = Result(signature); + var args = Args(signature); + var portabilityAssert = signature[0] == 'n' ? "PORTABILITY_ASSERT(\"Indirect struct return is not yet implemented.\");\n " : ""; + w.Write( + $$""" + + static void {{CallFuncName(args, SignatureMapper.CharToNameType(signature[0]))}}(PCODE pcode, int8_t* pArgs, int8_t* pRet) + { + {{result.nativeType}} (*fptr)({{args.Join(", ", (p, i) => SignatureMapper.CharToNativeType(p))}}) = ({{result.nativeType}} (*)({{args.Join(", ", (p, i) => SignatureMapper.CharToNativeType(p))}}))pcode; + {{portabilityAssert}}{{(result.isVoid ? "" : "*" + "((" + result.nativeType + "*)pRet) = ")}}(*fptr)({{args.Join(", ", (p, i) => $"{SignatureMapper.CharToArgType(p)}({i})")}}); + } + + """); + } + catch (InvalidSignatureCharException e) + { + throw new LogAsErrorException($"Element '{e.Char}' of signature '{signature}' can't be handled by managed2native generator"); + } + } + + w.Write( + $$""" + } + + const StringToWasmSigThunk g_wasmThunks[] = { + {{signatures.Join($",{w.NewLine}", signature => + $" {{ \"{signature}\", (void*)&{CallFuncName(Args(signature), SignatureMapper.CharToNameType(signature[0]))} }}")}} + }; + + const size_t g_wasmThunksCount = sizeof(g_wasmThunks) / sizeof(g_wasmThunks[0]); + + """); + + static IEnumerable Args(string signature) + { + for (int i = 1; i < signature.Length; ++i) + yield return signature[i]; + } + + static (bool isVoid, string nativeType) Result(string signature) + => new(SignatureMapper.IsVoidSignature(signature), SignatureMapper.CharToNativeType(signature[0])); + } +} diff --git a/src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs b/src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs new file mode 100644 index 00000000000000..eee06a7eaeecce --- /dev/null +++ b/src/tasks/WasmAppBuilder/coreclr/ManagedToNativeGenerator.cs @@ -0,0 +1,166 @@ +// 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; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using WasmAppBuilder; + +namespace Microsoft.WebAssembly.Build.Tasks; + +public class ManagedToNativeGenerator : Task +{ + [Required] + public string[] Assemblies { get; set; } = Array.Empty(); + + public string? RuntimeIcallTableFile { get; set; } + + public string? IcallOutputPath { get; set; } + + [Required, NotNull] + public string[]? PInvokeModules { get; set; } + + [Required, NotNull] + public string? PInvokeOutputPath { get; set; } + + [Required, NotNull] + public string? InterpToNativeOutputPath { get; set; } + public string? CacheFilePath { get; set; } + + public bool IsLibraryMode { get; set; } + + [Output] + public string[]? FileWrites { get; private set; } + + public override bool Execute() + { + if (Assemblies!.Length == 0) + { + Log.LogError($"{nameof(ManagedToNativeGenerator)}.{nameof(Assemblies)} cannot be empty"); + return false; + } + + if (PInvokeModules!.Length == 0) + { + Log.LogError($"{nameof(ManagedToNativeGenerator)}.{nameof(PInvokeModules)} cannot be empty"); + return false; + } + + try + { + var logAdapter = new LogAdapter(Log); + ExecuteInternal(logAdapter); + return !Log.HasLoggedErrors; + } + catch (LogAsErrorException e) + { + Log.LogError(e.Message); + return false; + } + } + + // WASM-TODO: + // add missing signatures temporarily + // part is for runtime tests and delegates + // active issue https://github.com/dotnet/runtime/issues/121222 + private static readonly string[] missingCookies = + [ + "d", + "idi", + "iff", + "iid", + "iif", + "iifiif", + "iiiiiiiiiiiiiiiiii", + "iin", + "iinn", + "lii", + "ni", + "nii", + "viin", + "vin", + "vinni", + "iinini", + ]; + + private void ExecuteInternal(LogAdapter log) + { + Dictionary _symbolNameFixups = new(); + List managedAssemblies = FilterOutUnmanagedBinaries(Assemblies); + var pinvoke = new PInvokeTableGenerator(FixupSymbolName, log, IsLibraryMode); + var icall = new IcallTableGenerator(RuntimeIcallTableFile, FixupSymbolName, log); + + var resolver = new PathAssemblyResolver(managedAssemblies); + using var mlc = new MetadataLoadContext(resolver, "System.Private.CoreLib"); + foreach (string asmPath in managedAssemblies) + { + log.LogMessage(MessageImportance.Low, $"Loading {asmPath} to scan for pinvokes, and icalls"); + Assembly asm = mlc.LoadFromAssemblyPath(asmPath); + pinvoke.ScanAssembly(asm); + icall.ScanAssembly(asm); + } + + IEnumerable cookies = Enumerable.Concat( + pinvoke.Generate(PInvokeModules, PInvokeOutputPath), + Enumerable.Concat(icall.Generate(IcallOutputPath), + missingCookies)); + + var m2n = new InterpToNativeGenerator(log); + m2n.Generate(cookies, InterpToNativeOutputPath); + + if (!string.IsNullOrEmpty(CacheFilePath)) + File.WriteAllLines(CacheFilePath, PInvokeModules); + + List fileWritesList = new() { PInvokeOutputPath, InterpToNativeOutputPath }; + if (!string.IsNullOrEmpty(IcallOutputPath)) + fileWritesList.Add(IcallOutputPath); + if (!string.IsNullOrEmpty(CacheFilePath)) + fileWritesList.Add(CacheFilePath); + + FileWrites = fileWritesList.ToArray(); + + string FixupSymbolName(string name) + { + if (_symbolNameFixups.TryGetValue(name, out string? fixedName)) + return fixedName; + + fixedName = Utils.FixupSymbolName(name); + _symbolNameFixups[name] = fixedName; + return fixedName; + } + } + + private List FilterOutUnmanagedBinaries(string[] assemblies) + { + List managedAssemblies = new(assemblies.Length); + foreach (string asmPath in Assemblies) + { + if (!File.Exists(asmPath)) + throw new LogAsErrorException($"Cannot find assembly {asmPath}"); + + try + { + if (!Utils.IsManagedAssembly(asmPath)) + { + Log.LogMessage(MessageImportance.Low, $"Skipping unmanaged {asmPath}."); + continue; + } + } + catch (Exception ex) + { + Log.LogMessage(MessageImportance.Low, $"Failed to read assembly {asmPath}: {ex}"); + throw new LogAsErrorException($"Failed to read assembly {asmPath}: {ex.Message}"); + } + + managedAssemblies.Add(asmPath); + } + + return managedAssemblies; + } +} diff --git a/src/tasks/WasmAppBuilder/coreclr/SignatureMapper.cs b/src/tasks/WasmAppBuilder/coreclr/SignatureMapper.cs new file mode 100644 index 00000000000000..21b47c309f1429 --- /dev/null +++ b/src/tasks/WasmAppBuilder/coreclr/SignatureMapper.cs @@ -0,0 +1,154 @@ +// 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; +using System.Linq; +using System.Reflection; +using System.Text; +using WasmAppBuilder; + +internal static class SignatureMapper +{ + internal static char? TypeToChar(Type t, LogAdapter log, out bool isByRefStruct, int depth = 0) + { + isByRefStruct = false; + + if (depth > 5) { + log.Warning("WASM0064", $"Unbounded recursion detected through parameter type '{t.Name}'"); + return null; + } + + // See https://github.com/WebAssembly/tool-conventions/blob/main/BasicCABI.md + char? c = null; + if (t.Namespace == "System") + { + c = t.Name switch + { + nameof(String) => 'i', + nameof(Boolean) => 'i', + nameof(Char) => 'i', + nameof(SByte) => 'i', + nameof(Byte) => 'i', + nameof(Int16) => 'i', + nameof(UInt16) => 'i', + nameof(Int32) => 'i', + nameof(UInt32) => 'i', + nameof(Int64) => 'l', + nameof(UInt64) => 'l', + nameof(Single) => 'f', + nameof(Double) => 'd', + // FIXME: These will need to be L for wasm64 + nameof(IntPtr) => 'i', + nameof(UIntPtr) => 'i', + "Void" => 'v', + _ => null + }; + } + + if (c != null) + return c; + + // FIXME: Most of these need to be L for wasm64 + if (t.IsByRef) + c = 'i'; + else if (t.IsClass) + c = 'i'; + else if (t.IsInterface) + c = 'i'; + else if (t.IsEnum) + { + Type underlyingType = t.GetEnumUnderlyingType(); + c = TypeToChar(underlyingType, log, out _, ++depth); + } + else if (t.IsPointer) + c = 'i'; + else if (PInvokeTableGenerator.IsFunctionPointer(t)) + c = 'i'; + else if (t.IsValueType) + { + var fields = t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + if (fields.Length == 1) + { + Type fieldType = fields[0].FieldType; + return TypeToChar(fieldType, log, out isByRefStruct, ++depth); + } + else if (PInvokeTableGenerator.IsBlittable(t, log)) + c = 'n'; + + isByRefStruct = true; + } + else + log.Warning("WASM0065", $"Unsupported parameter type '{t.Name}'"); + + return c; + } + + public static string? MethodToSignature(MethodInfo method, LogAdapter log) + { + string? result = TypeToChar(method.ReturnType, log, out bool resultIsByRef)?.ToString(); + if (result == null) + { + return null; + } + + if (resultIsByRef) + { + result = "n"; + } + + foreach (var parameter in method.GetParameters()) + { + char? parameterChar = TypeToChar(parameter.ParameterType, log, out _); + if (parameterChar == null) + { + return null; + } + + result += parameterChar; + } + + return result; + } + + public static string CharToNativeType(char c) => c switch + { + 'v' => "void", + 'i' => "int32_t", + 'l' => "int64_t", + 'f' => "float", + 'd' => "double", + 'n' => "int32_t", + _ => throw new InvalidSignatureCharException(c) + }; + + public static string CharToNameType(char c) => c switch + { + 'v' => "Void", + 'i' => "I32", + 'l' => "I64", + 'f' => "F32", + 'd' => "F64", + 'n' => "IND", + _ => throw new InvalidSignatureCharException(c) + }; + + public static string CharToArgType(char c) => c switch + { + 'i' => "ARG_I32", + 'l' => "ARG_I64", + 'f' => "ARG_F32", + 'd' => "ARG_F64", + 'n' => "ARG_IND", + _ => throw new InvalidSignatureCharException(c) + }; + + 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/InterpToNativeGenerator.cs b/src/tasks/WasmAppBuilder/mono/InterpToNativeGenerator.cs similarity index 100% rename from src/tasks/WasmAppBuilder/InterpToNativeGenerator.cs rename to src/tasks/WasmAppBuilder/mono/InterpToNativeGenerator.cs diff --git a/src/tasks/WasmAppBuilder/ManagedToNativeGenerator.cs b/src/tasks/WasmAppBuilder/mono/ManagedToNativeGenerator.cs similarity index 100% rename from src/tasks/WasmAppBuilder/ManagedToNativeGenerator.cs rename to src/tasks/WasmAppBuilder/mono/ManagedToNativeGenerator.cs diff --git a/src/tasks/WasmAppBuilder/SignatureMapper.cs b/src/tasks/WasmAppBuilder/mono/SignatureMapper.cs similarity index 100% rename from src/tasks/WasmAppBuilder/SignatureMapper.cs rename to src/tasks/WasmAppBuilder/mono/SignatureMapper.cs