// WASM-PROPOSAL Phase 0 — core module stub. // // Stands in for the future "core module" (uce_lib + libc compiled to wasm): // owns linear memory, the allocator, and libc/libc++ (statically linked, // per the §10 mitigation: avoid shared wasi-libc entirely). Built as a // non-PIC wasm32-wasi reactor with everything exported so unit modules can // import from it. // // Deliberately avoids WASI I/O (no printf-to-fd): output accumulates in a // buffer the host reads back, so the module can be instantiated through the // plain wasm-c-api without a WASI context if need be. #include #include #include #include static std::string g_output; extern "C" { // data symbol referenced from the unit module → must arrive there as a // GOT.mem import int core_counter = 7; void uce_print(const char* s, size_t len) { g_output.append(s, len); } // heap C++ object created in core, handed to the unit by pointer — // validates one-heap/one-allocator pointer semantics (§3.4) std::string* core_make_string(const char* s) { return(new std::string(s)); } void core_append_string(std::string* str, const char* s) { str->append(s); } // plain function pointer crossing: unit passes its own function, core calls // it back — validates the shared funcref table void core_invoke_callback(void (*cb)(int), int arg) { cb(arg); } // std::function allocated by unit code, executed here — validates fat // callable objects (lambdas) across module boundaries void core_invoke_function(std::function* f, int arg) { char buf[64]; snprintf(buf, sizeof(buf), "[fn:%d]", (*f)(arg)); g_output.append(buf); } // GOT.func resolution helper: taking the address here forces uce_print into // core's elem segment at link time, and on wasm a function pointer IS its // table index — so the loader can resolve GOT.func.uce_print with a plain // call instead of host-side funcref injection (which WAMR does not allow). // The production core will generalize this into a name → funcptr registry. intptr_t core_table_index_of_uce_print() { return(reinterpret_cast(uce_print)); } // host reads the result out of linear memory via these const char* core_output_data() { return(g_output.data()); } size_t core_output_size() { return(g_output.size()); } void core_output_clear() { g_output.clear(); } }