diff --git a/src/coreclr/hosts/corerun/corerun.cpp b/src/coreclr/hosts/corerun/corerun.cpp index 2b8105f3b3081a..a85649c0253bb1 100644 --- a/src/coreclr/hosts/corerun/corerun.cpp +++ b/src/coreclr/hosts/corerun/corerun.cpp @@ -490,12 +490,18 @@ static int run(const configuration& config) coreclr_set_error_writer_func(log_error_info); } + int result; #ifdef TARGET_WASM // install the pinvoke override callback to resolve p/invokes to statically linked libraries wasm_add_pinvoke_override(); + result = wasm_load_icu_data(entry_assembly_utf8.c_str()); + if (result != 1) + { + std::fprintf(stderr, "Failed to load the ICU data\n"); + return -1; + } #endif - int result; result = coreclr_init_func( exe_path_utf8.c_str(), "corerun", diff --git a/src/coreclr/hosts/corerun/corerun.wasm.cpp b/src/coreclr/hosts/corerun/corerun.wasm.cpp index 6e383db9206a12..795113631367f0 100644 --- a/src/coreclr/hosts/corerun/corerun.wasm.cpp +++ b/src/coreclr/hosts/corerun/corerun.wasm.cpp @@ -1,7 +1,11 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#include #include +#include +#include +#include #define _In_z_ #define _In_ @@ -27,3 +31,84 @@ void wasm_add_pinvoke_override() { PInvokeOverride::SetPInvokeOverride(pinvoke_override, PInvokeOverride::Source::RuntimeConfiguration); } + +extern "C" int32_t mono_wasm_load_icu_data(const void* pData); + +static char* _wasm_get_icu_dat_file_path(const char* assemblyPath) +{ + if (!assemblyPath || !*assemblyPath) + return nullptr; + + const char* lastSlash = strrchr(assemblyPath, '/'); + const char* lastBackslash = strrchr(assemblyPath, '\\'); + + const char* lastSeparator = nullptr; + if (lastSlash && lastBackslash) + lastSeparator = (lastSlash > lastBackslash) ? lastSlash : lastBackslash; + else if (lastSlash) + lastSeparator = lastSlash; + else if (lastBackslash) + lastSeparator = lastBackslash; + + const char icuFileName[] = "icudt.dat"; + + if (!lastSeparator) + return strdup(icuFileName); + + size_t dirLen = (size_t)(lastSeparator - assemblyPath) + 1; // include separator + size_t fileNameLen = sizeof(icuFileName) - 1; + + char* icuPath = (char*)malloc(dirLen + fileNameLen + 1); + if (!icuPath) + return nullptr; + + memcpy(icuPath, assemblyPath, dirLen); + memcpy(icuPath + dirLen, icuFileName, fileNameLen); + icuPath[dirLen + fileNameLen] = '\0'; + + return icuPath; +} + +int32_t wasm_load_icu_data(const char* assemblyPath) +{ + char* icuFile = _wasm_get_icu_dat_file_path(assemblyPath); + if (!icuFile) { + return 0; + } + + int fd = open(icuFile, O_RDONLY); + if (fd < 0) { + free(icuFile); + return 0; + } + + struct stat st; + if (stat(icuFile, &st) != 0 || !S_ISREG(st.st_mode) || st.st_size <= 0) { + close(fd); + free(icuFile); + return 0; + } + + free(icuFile); + + size_t size = static_cast(st.st_size); + void* buffer = malloc(size); + if (!buffer) { + close(fd); + return 0; + } + + size_t total = 0; + while (total < size) { + ssize_t n = read(fd, static_cast(buffer) + total, size - total); + if (n <= 0) { + free(buffer); + close(fd); + return 0; + } + total += static_cast(n); + } + close(fd); + + return mono_wasm_load_icu_data(buffer); +} diff --git a/src/coreclr/hosts/corerun/corerun.wasm.hpp b/src/coreclr/hosts/corerun/corerun.wasm.hpp index 302ef58542ac83..8cf6af48a1af3c 100644 --- a/src/coreclr/hosts/corerun/corerun.wasm.hpp +++ b/src/coreclr/hosts/corerun/corerun.wasm.hpp @@ -5,5 +5,6 @@ #define __CORERUN_WASM_HPP__ void wasm_add_pinvoke_override(); +int32_t wasm_load_icu_data(const char* assemblyPath); #endif // __CORERUN_WASM_HPP__ diff --git a/src/coreclr/hosts/corewasmrun/corewasmrun.cpp b/src/coreclr/hosts/corewasmrun/corewasmrun.cpp index 02ba088cfd5996..a0db7b5f2256f1 100644 --- a/src/coreclr/hosts/corewasmrun/corewasmrun.cpp +++ b/src/coreclr/hosts/corewasmrun/corewasmrun.cpp @@ -35,8 +35,18 @@ static int run() wasm_add_pinvoke_override(); + printf("BEGIN: call wasm_load_icu_data\n"); + int retval = wasm_load_icu_data("/"); + printf("END: call wasm_load_icu_data\n"); + + if (retval == 0) + { + std::fprintf(stderr, "Failed to load the ICU data\n"); + return -1; + } + printf("BEGIN: call coreclr_initialize\n"); - int retval = coreclr_initialize(exe_path, app_domain_name, (int)propertyKeys.size(), propertyKeys.data(), propertyValues.data(), &CurrentClrInstance, &CurrentAppDomainId); + retval = coreclr_initialize(exe_path, app_domain_name, (int)propertyKeys.size(), propertyKeys.data(), propertyValues.data(), &CurrentClrInstance, &CurrentAppDomainId); printf("END: call coreclr_initialize\n"); if (retval < 0) diff --git a/src/coreclr/vm/wasm/cgencpu.h b/src/coreclr/vm/wasm/cgencpu.h index 0472cd2c2e937e..868c43244078e4 100644 --- a/src/coreclr/vm/wasm/cgencpu.h +++ b/src/coreclr/vm/wasm/cgencpu.h @@ -32,7 +32,8 @@ struct HijackArgs inline LPVOID STDCALL GetCurrentSP() { - _ASSERTE("The function is not implemented on wasm, it lacks registers"); + // WASM-TODO: check where we reach that, return nullptr for now to not break runtime initialization + //PORTABILITY_ASSERT("The function is not implemented on wasm, it lacks registers"); return nullptr; } @@ -75,10 +76,10 @@ class StubLinkerCPU : public StubLinker public: static void Init() { /* no-op on wasm */ } inline void EmitShuffleThunk(struct ShuffleEntry *pShuffleEntryArray) { - _ASSERTE("The EmitShuffleThunk is not implemented on wasm"); + PORTABILITY_ASSERT("The EmitShuffleThunk is not implemented on wasm"); } inline VOID EmitComputedInstantiatingMethodStub(MethodDesc* pSharedMD, struct ShuffleEntry *pShuffleEntryArray, void* extraArg) { - _ASSERTE("The EmitComputedInstantiatingMethodStub is not implemented on wasm"); + PORTABILITY_ASSERT("The EmitComputedInstantiatingMethodStub is not implemented on wasm"); } }; @@ -144,13 +145,13 @@ inline BOOL ClrFlushInstructionCache(LPCVOID pCodeAddr, size_t sizeOfCode, bool //------------------------------------------------------------------------ inline void emitBackToBackJump(LPBYTE pBufferRX, LPBYTE pBufferRW, LPVOID target) { - _ASSERTE("emitBackToBackJump is not implemented on wasm"); + PORTABILITY_ASSERT("emitBackToBackJump is not implemented on wasm"); } //------------------------------------------------------------------------ inline PCODE decodeBackToBackJump(PCODE pBuffer) { - _ASSERTE("decodeBackToBackJump is not implemented on wasm"); + PORTABILITY_ASSERT("decodeBackToBackJump is not implemented on wasm"); return 0; } diff --git a/src/coreclr/vm/wasm/helpers.cpp b/src/coreclr/vm/wasm/helpers.cpp index 3208a2c16b1c56..3142d8a2885683 100644 --- a/src/coreclr/vm/wasm/helpers.cpp +++ b/src/coreclr/vm/wasm/helpers.cpp @@ -520,6 +520,12 @@ namespace *(int32_t*)pRet = (*fptr)(ARG(0), ARG(1), ARG(2), ARG(3)); } + 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(0), ARG(1), ARG(2), ARG(3), ARG(4)); + } + // Special thunks for signatures with indirect arguments. void CallFunc_I32IND_RetVoid(PCODE pcode, int8_t *pArgs, int8_t *pRet) @@ -579,6 +585,7 @@ namespace (void*)&CallFunc_I32_I32_RetI32, (void*)&CallFunc_I32_I32_I32_RetI32, (void*)&CallFunc_I32_I32_I32_I32_RetI32, + (void*)&CallFunc_I32_I32_I32_I32_I32_RetI32, }; enum class ConvertType