Helpers for manipulating orca structs living in wasm memory:

- convert between wasm memory and native pointers, asserting on out-of-bounds
- oc_wasm_list helpers
- oc_wasm_str8 helpers
- pushing things to arenas in wasm memory
This commit is contained in:
Martin Fouilleul 2023-09-02 16:20:22 +02:00
parent 0205d90941
commit fbb03d27a3
14 changed files with 274 additions and 175 deletions

View File

@ -19,7 +19,7 @@ f32 minf(f32 a, f32 b);
ORCA_EXPORT void oc_on_init(void) ORCA_EXPORT void oc_on_init(void)
{ {
oc_runtime_window_set_title(OC_STR8("clock")); oc_window_set_title(OC_STR8("clock"));
oc_runtime_window_set_size((oc_vec2){ .x = 400, .y = 400 }); oc_runtime_window_set_size((oc_vec2){ .x = 400, .y = 400 });
surface = oc_surface_canvas(); surface = oc_surface_canvas();

View File

@ -615,7 +615,7 @@ ORCA_EXPORT void oc_on_init()
{ {
oc_log_info("Hello, world (from C)"); oc_log_info("Hello, world (from C)");
oc_runtime_window_set_title(OC_STR8("fluid")); oc_window_set_title(OC_STR8("fluid"));
surface = oc_surface_gles(); surface = oc_surface_gles();
oc_surface_select(surface); oc_surface_select(surface);

View File

@ -37,7 +37,7 @@ void compile_shader(GLuint shader, const char* source)
ORCA_EXPORT void oc_on_init(void) ORCA_EXPORT void oc_on_init(void)
{ {
oc_runtime_window_set_title(OC_STR8("triangle")); oc_window_set_title(OC_STR8("triangle"));
surface = oc_surface_gles(); surface = oc_surface_gles();
oc_surface_select(surface); oc_surface_select(surface);

View File

@ -69,7 +69,7 @@ oc_str8 loadFile(oc_arena* arena, oc_str8 filename)
ORCA_EXPORT void oc_on_init(void) ORCA_EXPORT void oc_on_init(void)
{ {
oc_runtime_window_set_title(OC_STR8("pong")); oc_window_set_title(OC_STR8("pong"));
surface = oc_surface_canvas(); surface = oc_surface_canvas();
canvas = oc_canvas_create(); canvas = oc_canvas_create();

View File

@ -10,7 +10,7 @@ oc_arena textArena = { 0 };
ORCA_EXPORT void oc_on_init(void) ORCA_EXPORT void oc_on_init(void)
{ {
oc_runtime_window_set_title(OC_STR8("ui")); oc_window_set_title(OC_STR8("ui"));
surface = oc_surface_canvas(); surface = oc_surface_canvas();
canvas = oc_canvas_create(); canvas = oc_canvas_create();

View File

@ -457,9 +457,10 @@ ORCA_API int oc_directory_create(oc_str8 path);
#else #else
void oc_window_set_title(oc_str8 title);
void oc_window_set_size(oc_vec2 size);
void ORCA_IMPORT(oc_request_quit)(void); void ORCA_IMPORT(oc_request_quit)(void);
void ORCA_IMPORT(oc_runtime_window_set_title)(oc_str8 title);
void ORCA_IMPORT(oc_runtime_window_set_size)(oc_vec2 size);
#endif // !defined(OC_PLATFORM_ORCA) || !(OC_PLATFORM_ORCA) #endif // !defined(OC_PLATFORM_ORCA) || !(OC_PLATFORM_ORCA)

View File

@ -49,7 +49,7 @@ typedef struct oc_log_output
static oc_log_output oc_logDefaultOutput = { .kind = ORCA_LOG_OUTPUT_CONSOLE }; static oc_log_output oc_logDefaultOutput = { .kind = ORCA_LOG_OUTPUT_CONSOLE };
oc_log_output* OC_LOG_DEFAULT_OUTPUT = &oc_logDefaultOutput; oc_log_output* OC_LOG_DEFAULT_OUTPUT = &oc_logDefaultOutput;
void ORCA_IMPORT(oc_runtime_log)(oc_log_level level, void ORCA_IMPORT(oc_bridge_log)(oc_log_level level,
int fileLen, int fileLen,
const char* file, const char* file,
int functionLen, int functionLen,
@ -77,7 +77,7 @@ void platform_log_push(oc_log_output* output,
oc_str8 string = oc_str8_list_join(scratch, ctx.list); oc_str8 string = oc_str8_list_join(scratch, ctx.list);
oc_runtime_log(level, strlen(file), file, strlen(function), function, line, oc_str8_ip(string)); oc_bridge_log(level, strlen(file), file, strlen(function), function, line, oc_str8_ip(string));
oc_arena_scope_end(tmp); oc_arena_scope_end(tmp);
} }
@ -86,8 +86,8 @@ void platform_log_push(oc_log_output* output,
// Assert/Abort // Assert/Abort
//---------------------------------------------------------------- //----------------------------------------------------------------
_Noreturn void ORCA_IMPORT(oc_runtime_abort_ext)(const char* file, const char* function, int line, const char* msg); _Noreturn void ORCA_IMPORT(oc_bridge_abort_ext)(const char* file, const char* function, int line, const char* msg);
_Noreturn void ORCA_IMPORT(oc_runtime_assert_fail)(const char* file, const char* function, int line, const char* src, const char* msg); _Noreturn void ORCA_IMPORT(oc_bridge_assert_fail)(const char* file, const char* function, int line, const char* src, const char* msg);
_Noreturn void oc_abort_ext(const char* file, const char* function, int line, const char* fmt, ...) _Noreturn void oc_abort_ext(const char* file, const char* function, int line, const char* fmt, ...)
{ {
@ -108,7 +108,7 @@ _Noreturn void oc_abort_ext(const char* file, const char* function, int line, co
oc_str8 msg = oc_str8_list_join(scratch.arena, ctx.list); oc_str8 msg = oc_str8_list_join(scratch.arena, ctx.list);
oc_runtime_abort_ext(file, function, line, msg.ptr); oc_bridge_abort_ext(file, function, line, msg.ptr);
oc_scratch_end(scratch); oc_scratch_end(scratch);
} }
@ -132,7 +132,7 @@ _Noreturn void oc_assert_fail(const char* file, const char* function, int line,
oc_str8 msg = oc_str8_list_join(scratch.arena, ctx.list); oc_str8 msg = oc_str8_list_join(scratch.arena, ctx.list);
oc_runtime_assert_fail(file, function, line, src, msg.ptr); oc_bridge_assert_fail(file, function, line, src, msg.ptr);
oc_scratch_end(scratch); oc_scratch_end(scratch);
} }

View File

@ -56,11 +56,20 @@ oc_runtime* oc_runtime_get()
return (&__orcaApp); return (&__orcaApp);
} }
oc_runtime_env* oc_runtime_env_get() oc_wasm_env* oc_runtime_get_env()
{ {
return (&__orcaApp.env); return (&__orcaApp.env);
} }
oc_str8 oc_runtime_get_wasm_memory()
{
oc_str8 mem = { 0 };
u32 size = 0;
mem.ptr = (char*)m3_GetMemory(__orcaApp.env.m3Runtime, &size, 0);
mem.len = size;
return (mem);
}
void orca_wasm3_abort(IM3Runtime runtime, M3Result res, const char* file, const char* function, int line, const char* msg) void orca_wasm3_abort(IM3Runtime runtime, M3Result res, const char* file, const char* function, int line, const char* msg)
{ {
M3ErrorInfo errInfo = { 0 }; M3ErrorInfo errInfo = { 0 };
@ -75,67 +84,21 @@ void orca_wasm3_abort(IM3Runtime runtime, M3Result res, const char* file, const
} }
} }
#define ORCA_WASM3_ABORT(runtime, err, msg) orca_wasm3_abort(runtime, err, __FILE__, __FUNCTION__, __LINE__, msg) void oc_bridge_window_set_title(oc_wasm_str8 title)
void* oc_runtime_env_ptr_to_native(oc_runtime_env* env, void* wasmPtr, u32 length)
{ {
// We can't use the runtime's memory pointer directly because wasm3 embeds a oc_str8 nativeTitle = oc_wasm_str8_to_native(title);
// header at the beginning of the block we give it. if(nativeTitle.ptr)
u64 bufferIndex = (u64)wasmPtr & 0xffffffff;
u32 memSize = 0;
char* memory = (char*)m3_GetMemory(env->m3Runtime, &memSize, 0);
if(bufferIndex + length < memSize)
{ {
char* nativePtr = memory + bufferIndex; oc_window_set_title(__orcaApp.window, nativeTitle);
return nativePtr;
}
//TODO directly abort here?
return NULL;
}
void* oc_runtime_ptr_to_native(oc_runtime* orca, void* wasmPtr, u32 length)
{
return (oc_runtime_env_ptr_to_native(&orca->env, wasmPtr, length));
}
void* oc_wasm_arena_push(oc_runtime_env* env, i32 arenaIndex, u64 size)
{
void* retValues[1] = { 0 };
const void* retPointers[1] = { &retValues[0] };
const void* args[2] = { &arenaIndex, &size };
M3Result res = m3_Call(env->exports[OC_EXPORT_ARENA_PUSH], 2, args);
if(res)
{
ORCA_WASM3_ABORT(env->m3Runtime, res, "Runtime error");
}
res = m3_GetResults(env->exports[OC_EXPORT_ARENA_PUSH], 1, retPointers);
if(res)
{
ORCA_WASM3_ABORT(env->m3Runtime, res, "Runtime error");
}
void* ptr = oc_runtime_env_ptr_to_native(env, retValues[0], size);
return (ptr);
}
void oc_runtime_window_set_title(oc_str8 title)
{
title.ptr = oc_runtime_ptr_to_native(oc_runtime_get(), title.ptr, title.len);
if(title.ptr)
{
oc_window_set_title(__orcaApp.window, title);
} }
} }
void oc_runtime_window_set_size(oc_vec2 size) void oc_bridge_window_set_size(oc_vec2 size)
{ {
oc_window_set_content_size(__orcaApp.window, size); oc_window_set_content_size(__orcaApp.window, size);
} }
void oc_runtime_log(oc_log_level level, void oc_bridge_log(oc_log_level level,
int fileLen, int fileLen,
char* file, char* file,
int functionLen, int functionLen,
@ -372,9 +335,9 @@ char m3_type_to_tag(M3ValueType type)
} }
} }
void oc_runtime_env_init(oc_runtime_env* runtime) void oc_wasm_env_init(oc_wasm_env* runtime)
{ {
memset(runtime, 0, sizeof(oc_runtime_env)); memset(runtime, 0, sizeof(oc_wasm_env));
oc_base_allocator* allocator = oc_base_allocator_default(); oc_base_allocator* allocator = oc_base_allocator_default();
runtime->wasmMemory.committed = 0; runtime->wasmMemory.committed = 0;
runtime->wasmMemory.reserved = 4ULL << 30; runtime->wasmMemory.reserved = 4ULL << 30;
@ -392,7 +355,7 @@ i32 orca_runloop(void* user)
{ {
oc_runtime* app = &__orcaApp; oc_runtime* app = &__orcaApp;
oc_runtime_env_init(&app->env); oc_wasm_env_init(&app->env);
//NOTE: loads wasm module //NOTE: loads wasm module
const char* bundleNameCString = "module"; const char* bundleNameCString = "module";
@ -418,7 +381,7 @@ i32 orca_runloop(void* user)
app->env.m3Runtime = m3_NewRuntime(app->env.m3Env, stackSize, NULL); app->env.m3Runtime = m3_NewRuntime(app->env.m3Env, stackSize, NULL);
//NOTE: host memory will be freed when runtime is freed. //NOTE: host memory will be freed when runtime is freed.
m3_RuntimeSetMemoryCallbacks(app->env.m3Runtime, wasm_memory_resize_callback, wasm_memory_free_callback, &app->env.wasmMemory); m3_RuntimeSetMemoryCallbacks(app->env.m3Runtime, oc_wasm_memory_resize_callback, oc_wasm_memory_free_callback, &app->env.wasmMemory);
M3Result res = m3_ParseModule(app->env.m3Env, &app->env.m3Module, (u8*)app->env.wasmBytecode.ptr, app->env.wasmBytecode.len); M3Result res = m3_ParseModule(app->env.m3Env, &app->env.m3Module, (u8*)app->env.wasmBytecode.ptr, app->env.wasmBytecode.len);
if(res) if(res)
@ -569,7 +532,7 @@ i32 orca_runloop(void* user)
if(exports[OC_EXPORT_RAW_EVENT]) if(exports[OC_EXPORT_RAW_EVENT])
{ {
#ifndef M3_BIG_ENDIAN #ifndef M3_BIG_ENDIAN
oc_event* eventPtr = (oc_event*)wasm_memory_offset_to_ptr(&app->env.wasmMemory, app->env.rawEventOffset); oc_event* eventPtr = (oc_event*)oc_wasm_address_to_ptr(app->env.rawEventOffset, sizeof(oc_event));
memcpy(eventPtr, event, sizeof(*event)); memcpy(eventPtr, event, sizeof(*event));
const void* args[1] = { &app->env.rawEventOffset }; const void* args[1] = { &app->env.rawEventOffset };

View File

@ -54,18 +54,18 @@ const oc_export_desc OC_EXPORT_DESC[] = {
#undef OC_STR8_LIT #undef OC_STR8_LIT
}; };
typedef struct wasm_memory typedef struct oc_wasm_memory
{ {
char* ptr; char* ptr;
u64 reserved; u64 reserved;
u64 committed; u64 committed;
} wasm_memory; } oc_wasm_memory;
typedef struct oc_runtime_env typedef struct oc_wasm_env
{ {
oc_str8 wasmBytecode; oc_str8 wasmBytecode;
wasm_memory wasmMemory; oc_wasm_memory wasmMemory;
// wasm3 data // wasm3 data
IM3Environment m3Env; IM3Environment m3Env;
@ -74,7 +74,7 @@ typedef struct oc_runtime_env
IM3Function exports[OC_EXPORT_COUNT]; IM3Function exports[OC_EXPORT_COUNT];
u32 rawEventOffset; u32 rawEventOffset;
} oc_runtime_env; } oc_wasm_env;
typedef struct log_entry typedef struct log_entry
{ {
@ -114,20 +114,20 @@ typedef struct oc_runtime
{ {
bool quit; bool quit;
oc_window window; oc_window window;
oc_debug_overlay debugOverlay;
oc_file_table fileTable; oc_file_table fileTable;
oc_file rootDir; oc_file rootDir;
oc_runtime_env env; oc_wasm_env env;
oc_debug_overlay debugOverlay;
} oc_runtime; } oc_runtime;
oc_runtime* oc_runtime_get(); oc_runtime* oc_runtime_get(void);
oc_runtime_env* oc_runtime_env_get(); oc_wasm_env* oc_runtime_get_env(void);
oc_str8 oc_runtime_get_wasm_memory(void);
void* oc_runtime_ptr_to_native(oc_runtime* runtime, void* wasmPtr, u32 length); void orca_wasm3_abort(IM3Runtime runtime, M3Result res, const char* file, const char* function, int line, const char* msg);
void* oc_wasm_arena_push(oc_runtime_env* env, i32 arenaIndex, u64 size); #define ORCA_WASM3_ABORT(runtime, err, msg) orca_wasm3_abort(runtime, err, __FILE__, __FUNCTION__, __LINE__, msg)
#endif //__RUNTIME_H_ #endif //__RUNTIME_H_

View File

@ -7,15 +7,17 @@
*****************************************************************/ *****************************************************************/
#include "platform/platform_io_internal.h" #include "platform/platform_io_internal.h"
#include "runtime.h" #include "runtime.h"
#include "runtime_memory.h"
oc_io_cmp oc_runtime_io_wait_single_req(oc_io_req* wasmReq) oc_io_cmp oc_bridge_io_single_rect(oc_io_req* wasmReq)
{ {
oc_runtime* orca = oc_runtime_get(); oc_runtime* orca = oc_runtime_get();
oc_io_cmp cmp = { 0 }; oc_io_cmp cmp = { 0 };
oc_io_req req = *wasmReq; oc_io_req req = *wasmReq;
void* buffer = oc_runtime_ptr_to_native(orca, req.buffer, req.size); //TODO have a separate oc_wasm_io_req struct
void* buffer = oc_wasm_address_to_ptr((oc_wasm_addr)(uintptr_t)req.buffer, req.size);
if(buffer) if(buffer)
{ {
@ -40,51 +42,20 @@ oc_io_cmp oc_runtime_io_wait_single_req(oc_io_req* wasmReq)
return (cmp); return (cmp);
} }
oc_file oc_file_open_with_request_bridge(oc_str8 path, oc_file_access rights, oc_file_open_flags flags) oc_file oc_file_open_with_request_bridge(oc_wasm_str8 path, oc_file_access rights, oc_file_open_flags flags)
{ {
oc_file file = oc_file_nil(); oc_file file = oc_file_nil();
oc_runtime* orca = oc_runtime_get(); oc_runtime* orca = oc_runtime_get();
path.ptr = oc_runtime_ptr_to_native(orca, path.ptr, path.len); oc_str8 nativePath = oc_wasm_str8_to_native(path);
if(path.ptr)
if(nativePath.ptr)
{ {
file = oc_file_open_with_request_for_table(path, rights, flags, &orca->fileTable); file = oc_file_open_with_request_for_table(nativePath, rights, flags, &orca->fileTable);
} }
return (file); return (file);
} }
typedef struct oc_wasm_list
{
u32 first;
u32 last;
} oc_wasm_list;
typedef struct oc_wasm_list_elt
{
u32 prev;
u32 next;
} oc_wasm_list_elt;
typedef struct oc_wasm_str8
{
u64 len;
u32 ptr;
} oc_wasm_str8;
typedef struct oc_wasm_str8_elt
{
oc_wasm_list_elt listElt;
oc_wasm_str8 string;
} oc_wasm_str8_elt;
typedef struct oc_wasm_str8_list
{
oc_wasm_list list;
u64 eltCount;
u64 len;
} oc_wasm_str8_list;
typedef struct oc_wasm_file_dialog_desc typedef struct oc_wasm_file_dialog_desc
{ {
oc_file_dialog_kind kind; oc_file_dialog_kind kind;
@ -111,7 +82,7 @@ typedef struct oc_wasm_file_open_with_dialog_result
} oc_wasm_file_open_with_dialog_result; } oc_wasm_file_open_with_dialog_result;
oc_wasm_file_open_with_dialog_result oc_file_open_with_dialog_bridge(i32 wasmArenaIndex, oc_wasm_file_open_with_dialog_result oc_file_open_with_dialog_bridge(oc_wasm_addr wasmArena,
oc_file_access rights, oc_file_access rights,
oc_file_open_flags flags, oc_file_open_flags flags,
oc_wasm_file_dialog_desc* desc) oc_wasm_file_dialog_desc* desc)
@ -124,10 +95,10 @@ oc_wasm_file_open_with_dialog_result oc_file_open_with_dialog_bridge(i32 wasmAre
.flags = desc->flags .flags = desc->flags
}; };
nativeDesc.title.ptr = oc_runtime_ptr_to_native(orca, (char*)(uintptr_t)desc->title.ptr, desc->title.len); nativeDesc.title.ptr = oc_wasm_address_to_ptr(desc->title.ptr, desc->title.len);
nativeDesc.title.len = desc->title.len; nativeDesc.title.len = desc->title.len;
nativeDesc.okLabel.ptr = oc_runtime_ptr_to_native(orca, (char*)(uintptr_t)desc->okLabel.ptr, desc->okLabel.len); nativeDesc.okLabel.ptr = oc_wasm_address_to_ptr(desc->okLabel.ptr, desc->okLabel.len);
nativeDesc.okLabel.len = desc->okLabel.len; nativeDesc.okLabel.len = desc->okLabel.len;
if(oc_file_is_nil(desc->startAt) && desc->startPath.len) if(oc_file_is_nil(desc->startAt) && desc->startPath.len)
@ -138,17 +109,14 @@ oc_wasm_file_open_with_dialog_result oc_file_open_with_dialog_bridge(i32 wasmAre
{ {
nativeDesc.startAt = desc->startAt; nativeDesc.startAt = desc->startAt;
} }
nativeDesc.startPath.ptr = oc_runtime_ptr_to_native(orca, (char*)(uintptr_t)desc->startPath.ptr, desc->startPath.len); nativeDesc.startPath.ptr = oc_wasm_address_to_ptr(desc->startPath.ptr, desc->startPath.len);
nativeDesc.startPath.len = desc->startPath.len; nativeDesc.startPath.len = desc->startPath.len;
u32 eltIndex = desc->filters.list.first; u32 eltIndex = desc->filters.list.first;
while(eltIndex) while(eltIndex)
{ {
oc_wasm_str8_elt* elt = oc_runtime_ptr_to_native(orca, (char*)(uintptr_t)eltIndex, sizeof(oc_wasm_str8_elt)); oc_wasm_str8_elt* elt = oc_wasm_address_to_ptr(eltIndex, sizeof(oc_wasm_str8_elt));
oc_str8 filter = oc_wasm_str8_to_native(elt->string);
oc_str8 filter = { 0 };
filter.ptr = oc_runtime_ptr_to_native(orca, (char*)(uintptr_t)elt->string.ptr, elt->string.len);
filter.len = elt->string.len;
oc_str8_list_push(scratch.arena, &nativeDesc.filters, filter); oc_str8_list_push(scratch.arena, &nativeDesc.filters, filter);
@ -164,31 +132,12 @@ oc_wasm_file_open_with_dialog_result oc_file_open_with_dialog_bridge(i32 wasmAre
.file = nativeResult.file .file = nativeResult.file
}; };
u32 memSize;
char* wasmMemory = (char*)m3_GetMemory(orca->env.m3Runtime, &memSize, 0);
oc_wasm_file_open_with_dialog_elt* lastElt = 0;
oc_list_for(&nativeResult.selection, elt, oc_file_open_with_dialog_elt, listElt) oc_list_for(&nativeResult.selection, elt, oc_file_open_with_dialog_elt, listElt)
{ {
oc_wasm_file_open_with_dialog_elt* wasmElt = oc_wasm_arena_push(&orca->env, wasmArenaIndex, sizeof(oc_wasm_file_open_with_dialog_elt)); oc_wasm_file_open_with_dialog_elt* wasmElt = oc_wasm_arena_push(wasmArena, sizeof(oc_wasm_file_open_with_dialog_elt));
wasmElt->file = elt->file; wasmElt->file = elt->file;
if(result.selection.last == 0) oc_wasm_list_push_back(&result.selection, &wasmElt->listElt);
{
result.selection.first = ((char*)wasmElt - wasmMemory);
result.selection.last = result.selection.first;
wasmElt->listElt.prev = 0;
wasmElt->listElt.next = 0;
}
else
{
wasmElt->listElt.prev = result.selection.last;
wasmElt->listElt.next = 0;
lastElt->listElt.next = ((char*)wasmElt - wasmMemory);
result.selection.last = ((char*)wasmElt - wasmMemory);
}
lastElt = wasmElt;
} }
oc_scratch_end(scratch); oc_scratch_end(scratch);

View File

@ -7,10 +7,11 @@
*****************************************************************/ *****************************************************************/
#include "runtime.h" #include "runtime.h"
#include "runtime_memory.h"
void* wasm_memory_resize_callback(void* p, unsigned long size, void* userData) void* oc_wasm_memory_resize_callback(void* p, unsigned long size, void* userData)
{ {
wasm_memory* memory = (wasm_memory*)userData; oc_wasm_memory* memory = (oc_wasm_memory*)userData;
if(memory->committed >= size) if(memory->committed >= size)
{ {
@ -32,35 +33,119 @@ void* wasm_memory_resize_callback(void* p, unsigned long size, void* userData)
} }
} }
void wasm_memory_free_callback(void* p, void* userData) void oc_wasm_memory_free_callback(void* p, void* userData)
{ {
wasm_memory* memory = (wasm_memory*)userData; oc_wasm_memory* memory = (oc_wasm_memory*)userData;
oc_base_allocator* allocator = oc_base_allocator_default(); oc_base_allocator* allocator = oc_base_allocator_default();
oc_base_release(allocator, memory->ptr, memory->reserved); oc_base_release(allocator, memory->ptr, memory->reserved);
memset(memory, 0, sizeof(wasm_memory)); memset(memory, 0, sizeof(oc_wasm_memory));
} }
extern u32 oc_mem_grow(u64 size) extern u32 oc_mem_grow(u64 size)
{ {
oc_runtime_env* runtime = oc_runtime_env_get(); oc_wasm_env* env = oc_runtime_get_env();
wasm_memory* memory = &runtime->wasmMemory; oc_wasm_memory* memory = &env->wasmMemory;
size = oc_align_up_pow2(size, d_m3MemPageSize); size = oc_align_up_pow2(size, d_m3MemPageSize);
u64 totalSize = size + m3_GetMemorySize(runtime->m3Runtime); u64 totalSize = size + m3_GetMemorySize(env->m3Runtime);
u32 addr = memory->committed; u32 addr = memory->committed;
//NOTE: call resize memory, which will call our custom resize callback... this is a bit involved because //NOTE: call resize memory, which will call our custom resize callback... this is a bit involved because
// wasm3 doesn't allow resizing the memory directly // wasm3 doesn't allow resizing the memory directly
M3Result res = ResizeMemory(runtime->m3Runtime, totalSize / d_m3MemPageSize); M3Result res = ResizeMemory(env->m3Runtime, totalSize / d_m3MemPageSize);
return (addr); return (addr);
} }
void* wasm_memory_offset_to_ptr(wasm_memory* memory, u32 offset) void* oc_wasm_address_to_ptr(oc_wasm_addr addr, oc_wasm_size size)
{ {
M3MemoryHeader* header = (M3MemoryHeader*)(memory->ptr); oc_str8 mem = oc_runtime_get_wasm_memory();
OC_DEBUG_ASSERT(offset < header->length, "Wasm offset exceeds memory length"); OC_ASSERT(addr + size < mem.len, "Object overflows wasm memory");
return memory->ptr + sizeof(M3MemoryHeader) + offset;
void* ptr = (addr == 0) ? 0 : mem.ptr + addr;
return (ptr);
}
oc_wasm_addr oc_wasm_address_from_ptr(void* ptr, oc_wasm_size size)
{
oc_wasm_addr addr = 0;
if(ptr != 0)
{
oc_str8 mem = oc_runtime_get_wasm_memory();
OC_ASSERT((char*)ptr > mem.ptr && (((char*)ptr - mem.ptr) + size < mem.len), "Object overflows wasm memory");
addr = (char*)ptr - mem.ptr;
}
return (addr);
}
//------------------------------------------------------------------------------------
// oc_wasm_list helpers
//------------------------------------------------------------------------------------
void oc_wasm_list_push(oc_wasm_list* list, oc_wasm_list_elt* elt)
{
elt->next = list->first;
elt->prev = 0;
oc_wasm_addr eltAddr = oc_wasm_address_from_ptr(elt, sizeof(oc_wasm_list_elt));
if(list->first)
{
oc_wasm_list_elt* first = oc_wasm_address_to_ptr(list->first, sizeof(oc_wasm_list_elt));
first->prev = eltAddr;
}
else
{
list->last = eltAddr;
}
list->first = eltAddr;
}
void oc_wasm_list_push_back(oc_wasm_list* list, oc_wasm_list_elt* elt)
{
elt->prev = list->last;
elt->next = 0;
oc_wasm_addr eltAddr = oc_wasm_address_from_ptr(elt, sizeof(oc_wasm_list_elt));
if(list->last)
{
oc_wasm_list_elt* last = oc_wasm_address_to_ptr(list->last, sizeof(oc_wasm_list_elt));
last->next = eltAddr;
}
else
{
list->first = eltAddr;
}
list->last = eltAddr;
}
//------------------------------------------------------------------------------------
// Wasm arenas helpers
//------------------------------------------------------------------------------------
void* oc_wasm_arena_push(oc_wasm_addr arena, u64 size)
{
oc_wasm_env* env = oc_runtime_get_env();
oc_wasm_addr retValues[1] = { 0 };
const void* retPointers[1] = { (void*)&retValues[0] };
const void* args[2] = { &arena, &size };
M3Result res = m3_Call(env->exports[OC_EXPORT_ARENA_PUSH], 2, args);
if(res)
{
ORCA_WASM3_ABORT(env->m3Runtime, res, "Runtime error");
}
res = m3_GetResults(env->exports[OC_EXPORT_ARENA_PUSH], 1, retPointers);
if(res)
{
ORCA_WASM3_ABORT(env->m3Runtime, res, "Runtime error");
}
void* ptr = oc_wasm_address_to_ptr(retValues[0], size);
return (ptr);
} }

101
src/runtime_memory.h Normal file
View File

@ -0,0 +1,101 @@
/************************************************************/ /**
*
* @file: runtime_memory.h
* @author: Martin Fouilleul
* @date: 02/09/2023
*
*****************************************************************/
#ifndef __RUNTIME_MEMORY_H_
#define __RUNTIME_MEMORY_H_
#include "runtime.h"
typedef u32 oc_wasm_addr;
typedef u32 oc_wasm_size;
void* oc_wasm_address_to_ptr(oc_wasm_addr addr, oc_wasm_size size);
oc_wasm_addr oc_wasm_address_from_ptr(void* ptr, oc_wasm_size size);
//------------------------------------------------------------------------------------
// oc_wasm_list helpers
//------------------------------------------------------------------------------------
typedef struct oc_wasm_list
{
u32 first;
u32 last;
} oc_wasm_list;
typedef struct oc_wasm_list_elt
{
u32 prev;
u32 next;
} oc_wasm_list_elt;
bool oc_wasm_list_empty(oc_wasm_list* list);
#define oc_wasm_list_begin(list) oc_wasm_address_to_ptr(list->first, sizeof(oc_wasm_list_elt))
#define oc_wasm_list_end(list) oc_wasm_address_to_ptr(list->last, sizeof(oc_wasm_list_elt))
#define oc_wasm_list_next(elt) oc_wasm_address_to_ptr((elt)->next, sizeof(oc_wasm_list_elt))
#define oc_wasm_list_prev(elt) oc_wasm_address_to_ptr((elt)->prev, sizeof(oc_wasm_list_elt))
#define oc_wasm_list_entry(ptr, type, member) \
oc_container_of(ptr, type, member)
#define oc_wasm_list_next_entry(list, elt, type, member) \
(((elt)->member.next != 0) ? oc_wasm_list_entry(oc_wasm_list_next((elt)->member), type, member) : 0)
#define oc_wasm_list_prev_entry(list, elt, type, member) \
(((elt)->member.prev != 0) ? oc_wasm_list_entry(oc_wasm_list_prev((elt)->member), type, member) : 0)
#define oc_wasm_list_checked_entry(elt, type, member) \
(((elt) != 0) ? oc_wasm_list_entry(elt, type, member) : 0)
#define oc_wasm_list_first_entry(list, type, member) \
(oc_wasm_list_checked_entry(oc_wasm_list_begin(list), type, member))
#define oc_wasm_list_last_entry(list, type, member) \
(oc_wasm_list_checked_entry(oc_wasm_list_last(list), type, member))
#define oc_wasm_list_for(list, elt, type, member) \
for(type* elt = oc_wasm_list_checked_entry(oc_wasm_list_begin(list), type, member); \
elt != 0; \
elt = oc_wasm_list_checked_entry(oc_wasm_list_next((elt)->member), type, member))
void oc_wasm_list_push(oc_wasm_list* list, oc_wasm_list_elt* elt);
void oc_wasm_list_push_back(oc_wasm_list* list, oc_wasm_list_elt* elt);
//------------------------------------------------------------------------------------
// oc_wasm_str8 helpers
//------------------------------------------------------------------------------------
typedef struct oc_wasm_str8
{
u64 len;
u32 ptr;
} oc_wasm_str8;
typedef struct oc_wasm_str8_elt
{
oc_wasm_list_elt listElt;
oc_wasm_str8 string;
} oc_wasm_str8_elt;
typedef struct oc_wasm_str8_list
{
oc_wasm_list list;
u64 eltCount;
u64 len;
} oc_wasm_str8_list;
#define oc_wasm_str8_to_native(wasmString) ((oc_str8){ .ptr = oc_wasm_address_to_ptr(wasmString.ptr, wasmString.len), .len = wasmString.len })
//------------------------------------------------------------------------------------
// Wasm arenas helpers
//------------------------------------------------------------------------------------
void* oc_wasm_arena_push(oc_wasm_addr arena, u64 size);
#endif //__RUNTIME_MEMORY_H_

View File

@ -1,7 +1,7 @@
[ [
{ {
"name": "oc_runtime_log", "name": "oc_bridge_log",
"cname": "oc_runtime_log", "cname": "oc_bridge_log",
"ret": {"name": "void", "tag": "v"}, "ret": {"name": "void", "tag": "v"},
"args": [ {"name": "level", "args": [ {"name": "level",
"type": {"name": "oc_log_level", "tag": "i"}}, "type": {"name": "oc_log_level", "tag": "i"}},
@ -29,7 +29,7 @@
"type": {"name": "u64", "tag": "I"}}] "type": {"name": "u64", "tag": "I"}}]
}, },
{ {
"name": "oc_runtime_assert_fail", "name": "oc_bridge_assert_fail",
"cname": "oc_assert_fail", "cname": "oc_assert_fail",
"ret": {"name": "void", "tag": "v"}, "ret": {"name": "void", "tag": "v"},
"args": [ {"name": "file", "args": [ {"name": "file",
@ -45,7 +45,7 @@
] ]
}, },
{ {
"name": "oc_runtime_abort_ext", "name": "oc_bridge_abort_ext",
"cname": "oc_abort_ext", "cname": "oc_abort_ext",
"ret": {"name": "void", "tag": "v"}, "ret": {"name": "void", "tag": "v"},
"args": [ {"name": "file", "args": [ {"name": "file",
@ -71,17 +71,17 @@
"args": [] "args": []
}, },
{ {
"name": "oc_runtime_window_set_title", "name": "oc_window_set_title",
"cname": "oc_runtime_window_set_title", "cname": "oc_bridge_window_set_title",
"ret": {"name": "void", "tag": "v"}, "ret": {"name": "void", "tag": "v"},
"args": [ "args": [
{ "name": "title", { "name": "title",
"type": {"name": "oc_str8", "tag": "S"}} "type": {"name": "oc_str8", "cname": "oc_wasm_str8", "tag": "S"}}
] ]
}, },
{ {
"name": "oc_runtime_window_set_size", "name": "oc_window_set_size",
"cname": "oc_runtime_window_set_size", "cname": "oc_bridge_window_set_size",
"ret": {"name": "void", "tag": "v"}, "ret": {"name": "void", "tag": "v"},
"args": [ "args": [
{ "name": "size", { "name": "size",

View File

@ -1,7 +1,7 @@
[ [
{ {
"name": "oc_io_wait_single_req", "name": "oc_io_wait_single_req",
"cname": "oc_runtime_io_wait_single_req", "cname": "oc_bridge_io_single_rect",
"ret": {"name": "oc_io_cmp", "tag": "S"}, "ret": {"name": "oc_io_cmp", "tag": "S"},
"args": [ {"name": "req", "args": [ {"name": "req",
"type": {"name": "oc_io_req*", "tag": "p"}}] "type": {"name": "oc_io_req*", "tag": "p"}}]
@ -12,7 +12,7 @@
"ret": {"name": "oc_file", "tag": "S"}, "ret": {"name": "oc_file", "tag": "S"},
"args": [ "args": [
{"name": "path", {"name": "path",
"type": {"name": "oc_str8", "tag": "S"}}, "type": {"name": "oc_str8", "cname": "oc_wasm_str8", "tag": "S"}},
{"name": "rights", {"name": "rights",
"type": {"name": "oc_file_access", "tag": "i"}}, "type": {"name": "oc_file_access", "tag": "i"}},
{"name": "flags", {"name": "flags",