Skip to content
8 changes: 7 additions & 1 deletion src/coreclr/hosts/corerun/corerun.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#endif
#endif // TARGET_WASM


int result;
result = coreclr_init_func(
exe_path_utf8.c_str(),
"corerun",
Expand Down
85 changes: 85 additions & 0 deletions src/coreclr/hosts/corerun/corerun.wasm.cpp
Original file line number Diff line number Diff line change
@@ -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 <malloc.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>

#define _In_z_
#define _In_
Expand All @@ -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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
static char* _wasm_get_icu_dat_file_path(const char* assemblyPath)
static char* wasm_get_icu_dat_file_path(const char* assemblyPath)

{
if (!assemblyPath || !*assemblyPath)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When will this be NULL?

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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
size_t fileNameLen = sizeof(icuFileName) - 1;
size_t fileNameLen = ARRAY_SIZE(icuFileName) - 1;

Using sizeof is too easy to do wrong. All someone needs to do is change that to const char icuFileName* and it will compile and be wrong.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the -1 and then you can remove the +1 and icuPath[dirLen + fileNameLen] = '\0';. Doing that and making a comment is all that is needed.


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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize this is probably copied from somewhere, but it is using very low leve APIs. For example, open vs fopen. Can we instead clean this up to be as C++ as possible?

{
char* icuFile = _wasm_get_icu_dat_file_path(assemblyPath);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
char* icuFile = _wasm_get_icu_dat_file_path(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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
struct stat st;
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<size_t>(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<char*>(buffer) + total, size - total);
if (n <= 0) {
free(buffer);
close(fd);
return 0;
}
total += static_cast<size_t>(n);
}
close(fd);

return mono_wasm_load_icu_data(buffer);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this returns failure, we should clean things up.

}
1 change: 1 addition & 0 deletions src/coreclr/hosts/corerun/corerun.wasm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
#define __CORERUN_WASM_HPP__

void wasm_add_pinvoke_override();
int32_t wasm_load_icu_data(const char* assemblyPath);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update this to be bool instead of int32_t.


#endif // __CORERUN_WASM_HPP__
12 changes: 11 additions & 1 deletion src/coreclr/hosts/corewasmrun/corewasmrun.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
11 changes: 6 additions & 5 deletions src/coreclr/vm/wasm/cgencpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Comment on lines +35 to +36
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are we getting here? Can you share a callstack? I would prefer us to nicely ifdef out the caller in an intelligent way.

return nullptr;
}

Expand Down Expand Up @@ -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");
}
};

Expand Down Expand Up @@ -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;
}

Expand Down
7 changes: 7 additions & 0 deletions src/coreclr/vm/wasm/helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
Loading