Skip to content

Commit

Permalink
CURRENT TESTS PASSED
Browse files Browse the repository at this point in the history
pow.wasm read in browser but not linked ;)
  • Loading branch information
pannous committed Nov 23, 2024
1 parent 6664529 commit 6ad6282
Show file tree
Hide file tree
Showing 14 changed files with 135 additions and 51 deletions.
30 changes: 24 additions & 6 deletions docs/wasp.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ let WASP_COMPILER = 'wasp-hosted.wasm' // 4MB with tests and shortcuts
// let WASP_COMPILER = 'assets/wasp-hosted.wasm' // 4MB with tests and shortcuts
// let WASP_COMPILER = 'assets/wasp-debug.wasm' // 4MB with tests and shortcuts
// let WASP_RUNTIME = 'wasp-runtime.wasm'
let lib_folder_url = "https://pannous.github.io/wasp/lib/"
// let lib_folder_url = "https://pannous.github.io/wasp/lib/"
let lib_folder_url = "assets/lib/"

let runtime_bytes = null; // for reflection or linking
let needs_runtime = false;
Expand All @@ -33,16 +34,27 @@ let string_header_32 = 0x10000000
let array_header_32 = 0x40000000
let node_header_32 = 0x80000000

function binary_hack(binary_as_text) {
let binary = new Uint8Array(binary_as_text.length);
for (let i = 0; i < binary_as_text.length; i++) {
binary[i] = binary_as_text.charCodeAt(i);
}
return binary
}

function download(url, binary = false) {
if (typeof url != "string") url = chars(url)
// console.log("download", url)
let xhr = new XMLHttpRequest();
// if (binary) xhr.responseType = 'arraybuffer'; // not allowed for sync requests
if (binary) xhr.overrideMimeType('text/plain; charset=x-user-defined'); // Prevent UTF-8 decoding
xhr.open('GET', url, false);
xhr.send();
if (xhr.status === 200)
return binary ? bytes(new Uint8Array(xhr.response)) : chars(xhr.responseText.trim()) // to be used in WASM as string! use fetch() in JS
return binary ? bytes(binary_hack(xhr.response)) : chars(xhr.responseText.trim()) // to be used in WASM as string! use fetch() in JS
else
return null;
throw new Error(`Failed to download: ${xhr.status} ${xhr.statusText}`);
return null;
}

function format(object) {
Expand Down Expand Up @@ -86,6 +98,7 @@ const fd_write = function (fd, c_io_vector, iovs_count, nwritten) {

function getWasmFunclet(funclet_name, size_p) {
[pointer, bytes_size] = download(lib_folder_url + chars(funclet_name)+".wasm", binary = true)
console.log("getWasmFunclet", chars(funclet_name), pointer, bytes_size)
set_int(size_p, bytes_size)
return pointer
}
Expand Down Expand Up @@ -246,7 +259,11 @@ let imports = {
},

exit: terminate, // should be wasi.proc_exit!
pow: (x, y) => x ** y,
// pow: (x, y) => x ** y, // via pow.wasm funclet => never called here
pow: (x, y) => {
console.log("pow", x, y);
return x ** y
},
print: x => console.log(string(x)),
puti: x => console.log(x), // allows debugging of ints without format String allocation!
js_demangle: x => x,
Expand Down Expand Up @@ -352,10 +369,11 @@ function load_chars(pointer, length = -1, format = 'utf8', module_memory) {

function bytes(data) {
if (!data) return 0;// MAKE SURE!
buffer = new Uint8Array(memory.buffer, HEAP_END, data.length);
buffer.set(data, 0);
buffer = new Uint8Array(memory.buffer, HEAP_END, data.length); // wasm linear memory
buffer.set(data, 0); // copy data to wasm linear memory
let c = HEAP_END
HEAP_END += data.length;
// console.log("bytes", data.length, HEAP_END, buffer)
return [c, data.length]
}

Expand Down
28 changes: 16 additions & 12 deletions source/Angle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#endif
#endif


Module *module; // todo: use?
bool use_interpreter = false;
Node &result = *new Node();
Expand Down Expand Up @@ -1696,25 +1697,24 @@ void addLibraryFunctionAsImport(Function &func) {

// ⚠️ this function now lives inside Module AND as import inside "wasp_main" functions list, with different wasm_index!
bool function_known = functions.has(func.name);
//#if WASM
// Function& import=*new Function;
//#else
#if WASM
Function& import=*new Function();
if(function_known)
import = functions[func.name];
#else
Function & import=functions[func.name];// copy function info from library/runtime to main module
//#endif
// if(function_known)
// import = functions[func.name];
#endif
if (import.is_declared)return;
import.signature = func.signature;
import.signature.type_index = -1;
import.signature.parameters = func.signature.parameters;
import.is_runtime = false;// because here it is an import!
import.is_import = true;
import.is_used = true;

//#if WASM
// if(not function_known)
// functions.add(func.name, import);
//#endif
#if WASM
if(not function_known)
functions.add(func.name, import);
#endif
}

Function getWaspFunction(String name);
Expand All @@ -1740,7 +1740,8 @@ Function *findLibraryFunction(String name, bool searchAliases) {
Module &funclet_module = read_wasm(funclet_bytes, byte_count);
funclet_module.code.name = name;
funclet_module.name = name;
module_cache.add(name.hash(), &funclet_module);
if (not module_cache.has(name.hash()))
module_cache.add(name.hash(), &funclet_module);
#elif WASM
// todo("getWaspFunclet get library function signature from wasp");
warn("WASP function "s + name + " getWaspFunclet todo");
Expand All @@ -1749,10 +1750,13 @@ Function *findLibraryFunction(String name, bool searchAliases) {
return use_required(pFunction);
#else
// todo simplify by using read_wasm in MY_WASM?
print("loading funclet "s + name);
Module &funclet_module = read_wasm(findFile(name, "lib"));
// check(funclet_module.functions.has(name));
#endif
auto funclet = funclet_module.functions[name];
print("GOT funclet "s + name);
print(funclet.signature);
addLibrary(&funclet_module);
return use_required(&funclet);
}
Expand Down
5 changes: 5 additions & 0 deletions source/Angle.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
#include "Code.h"
#include "wasm_reader.h"

#if MY_WASM
static bool hosted = true; // special functions for wasm
#else
static bool hosted = false;
#endif

static float function_precedence = 1000;

Expand Down
4 changes: 1 addition & 3 deletions source/Code.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,11 @@ Code &signedLEB128(int64 value);

class Code {
public:


int header = array_header_32;// todo: code_header_32 if extra fields are needed beyond standard
int kind = byte_i8;
int length = 0;
bytes data = 0;
int64 start = 0;// internal reader pointer
int start = 0;// internal reader pointer
bool encoded = false;// first byte = size of vector
bool needs_relocate = true; // unless specified
mutable bool shared = true; // can be changed in const clone()
Expand Down
5 changes: 2 additions & 3 deletions source/Map.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ class Map {
// trace("Key known");
return values[position1];
}
if (leave_blank) { // leaves deep fields uninitialized.
if (leave_blank /*false*/) { // leaves deep fields uninitialized.
// Problematic for functions["exit"].signature.return_types …
trace("leave_blank");
keys[_size] = key;
Expand All @@ -208,9 +208,8 @@ class Map {
} else { // use default constructor
keys[_size] = key;
values[_size] = T();
_size++;
// insert_or_assign(key, T()); // creates intermediate stack value, or is c++ smart?
return last();
return values[_size++];
}
return last();
}
Expand Down
6 changes: 3 additions & 3 deletions source/String.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -769,9 +769,9 @@ void print(Signature& signature) {
}
void print(String s) {
put_chars(s.data, s.length);
#if not WASM
newline();
#endif
//#if not WASM
// newline();
//#endif
}

void println(String s) {
Expand Down
6 changes: 5 additions & 1 deletion source/Util.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,12 @@ static bool I_know_what_I_am_doing = false;
//static bool tracing = true;
static bool tracing = false; // todo
#else
static bool tracing = false;
#if MY_WASM and DEBUG
static bool tracing = true;
#else
//static bool tracing = true;
static bool tracing = false;
#endif
#endif

#if RELEASE
Expand Down
4 changes: 3 additions & 1 deletion source/tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3415,8 +3415,10 @@ void pleaseFix() {
// 2022-12-28 : 3 sec WITH runtime_emit, wasmedge on M1 WOW ALL TESTS PASSING
// ⚠️ CANNOT USE assert_emit in WASM! ONLY via void testRun();
void testCurrent() {
read_wasm("lib/pow.wasm");
// read_wasm("lib/stdio.wasm");
// assert_emit("a=√3^2", 3);// todo 2 due to int type guess
// exit(-42);
// exit(42);
assert_emit("π/2^2", pi / 4);
assert_emit("(π/2)^2", pi * pi / 4);
// assert_emit("√3^0", 0.971); // very rough power approximation
Expand Down
2 changes: 2 additions & 0 deletions source/wasm_emitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3534,6 +3534,8 @@ void add_imports_and_builtins() {
function.call_index = ++last_index;
call_indices[sig] = last_index;
info("using import "s + sig);
trace(function.name);
trace(function.signature.serialize());
import_count++;
}
}
Expand Down
1 change: 1 addition & 0 deletions source/wasm_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ void memcpy1(bytes dest, bytes source, int i);
// if MY_WASI make sure to IMPLEMENT THEM ALL via fd_write !!
// todo: alias all to print
extern "C" void put_chars(chars c, size_t len = 0);
//extern "C" void put_chars(char* c, size_t len = 0);

class String;

Expand Down
16 changes: 13 additions & 3 deletions source/wasm_helpers_host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,24 @@ double powd(double x, double y) {

extern "C" void put_chars(chars c, size_t len) {
#if MY_WASM // and …
printf("%s", c); // console.log adds newline
printf("%s", c); // console.log adds newline
#else
printf("%s\n", c);
if (len and c[len] and len > 0 and len < 1000) { // not null terminated! E.g. in shared String
char copy[1000];
strcpy2(copy, c);
char x = c[len];// bad access!
copy[len] = 0;
printf("%s\n", copy);
} else {
printf("%s\n", c);
}
#endif
#if WEBAPP
console_log(c); // log to browser console AND to app stdout
console_log(c); // log to browser console AND to app stdout
#endif
}


#if not WASM

//#if not WEBAPP // ??
Expand All @@ -135,6 +144,7 @@ void proc_exit(int x) {
exit(x);
#endif
}

#endif


Expand Down
45 changes: 32 additions & 13 deletions source/wasm_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@

#define POLYMORPH_function_index_marker -2
#if MY_WASM and not WEBAPP
bool build_module = false; // link via js
//bool build_module = false; // link via js
bool build_module = true; // for funclets … and wasm runtime merge?
#else
bool build_module = true;
#endif
Expand Down Expand Up @@ -109,8 +110,8 @@ Code vec(Code &data, bool consume = true) {
String &name(Code &wstring) {// Shared string view, so don't worry about trailing extra chars
int64 len = unsignedLEB128(wstring);
auto nam = (char *) wstring.data + wstring.start;
// while(nam[0]<=33)nam++;// WTH! hiding strange bug where there is a byte behind unsignedLEB128. NOT FULLY consumed
String *string = new String(nam, len, true);
// String *string = new String(nam, len, false);
wstring.start += len;// advance internally
// if (len > 40)put(string);
return *string;
Expand All @@ -123,20 +124,29 @@ void parseFunctionNames(Code &payload) {
// put(module->functionIndices);// what we got so far?
int function_count = unsignedLEB128(payload);
int call_index = -1;
printf("function count: %d\n", function_count);
Map<String, Function> &functions = module->functions;
for (int i = 0; i < function_count and payload.start < payload.length; ++i) {
call_index = unsignedLEB128(payload);
int code_index = call_index - module->import_count;
if (i != call_index)trace("i≠index => some functions not named (or other things named)");
if (call_index < 0 or call_index > 100000)
error("broken index"s + call_index);
String func = name(payload).clone();// needs to be 0-terminated now
Function &function = module->functions[func];
if (function.code_index >= 0 and function.code_index != code_index) {
trace("already has index: "s + func + " " + function.code_index + "" + code_index);
String &name1 = name(payload);
String func = name1.clone();// needs to be 0-terminated now
if (debug_reader)print("ƒ%d %s\n"s % call_index % func);
bool old = functions.contains(func);
if (old) {
trace("function already exists: "s + func);
Function &function = functions[func];
} else {
Function &function = *new Function();
if (function.code_index >= 0 and function.code_index != code_index)
trace("already has index: "s + func + " " + function.code_index + "" + code_index);
function.code_index = code_index;
function.name = func;
functions.add(func, function);
}
function.code_index = code_index;
function.name = func;
if (debug_reader)print("ƒ%d %s\n"s % call_index % func.data);
}
// (import "env" "log_chars" (func (;0;) $logs (type 0))) export / import names != internal names
// for (int i = function_count; i < module->total_func_count; i++)
Expand Down Expand Up @@ -258,18 +268,22 @@ void consumeGlobalSection() {

void consumeNameSection(Code &data) {
if (debug_reader)print("names: …\n");
module->name_data = data.clone();
module->name_data = data;//.clone();
// module->name_data = data.clone();
while (data.start < data.length) {
int type = unsignedLEB128(data);
Code payload = vec(data);// todo test!
print("name type: %d\n"s % type);
printf("length: %d\n", payload.length);
switch (type) {
case module_name: {
case module_name: {// 0
module->name = name(payload);// wrapped in vector why?
}
break;
case function_names:
case function_names:// 1
module->function_names = payload;
parseFunctionNames(payload.clone());
parseFunctionNames(payload);
// parseFunctionNames(payload.clone());
break;
case local_names:
module->local_names = payload;
Expand Down Expand Up @@ -334,6 +348,9 @@ void consumeCustomSection() {
Code customSectionDatas = vec();
String type = name(customSectionDatas);
Code payload = customSectionDatas.rest();
trace("custom section:");
trace(type);
// trace("custom section length: %d\n", payload.length);
if (type == "names" or type == "name") {
consumeNameSection(payload);
} else if (type == "target_features")
Expand Down Expand Up @@ -676,6 +693,8 @@ Module &read_wasm(String file) {
wasm.code.name = name;
wasm.name = name;
fclose(stream);
print("module->functions[pow]");
print(module->functions["pow"]);
module_cache.add(name.hash(), &wasm);
return wasm;
#endif
Expand Down
4 changes: 4 additions & 0 deletions source/wasm_reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,11 @@ class Module {
List<Signature> funcTypes;// = {1000};// c++ types from export name convention, implicit index
// List<Signature> wasmFuncTypes;// wasm types from funcTypes section implicit index
Map<String, Signature> signatures;// also implicit index->Signature 0,1,2… ! before merging!
#if MY_WASM
Map<String, Function> functions = {20}; // TODO DANGER funclets only
#else
Map<String, Function> functions = {1000};// contains imports, so index via call_index, not code_index
#endif
// int data_offset=0;// todo: read from data section! why not 0 ?
int data_offset_end = 0;

Expand Down
Loading

0 comments on commit 6ad6282

Please sign in to comment.