mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 07:08:48 +00:00
wasm: fix runtime.js even more for wasm64p32
- make the int size configurable in the `runWasm` call, no more constants to hunt down and change - make storeU64 and storeI64 handle bigints, this is needed in the odin_dom library - fix alignment issues within init_event_raw
This commit is contained in:
Vendored
+64
-30
@@ -13,14 +13,18 @@ function stripNewline(str) {
|
|||||||
return str.replace(/\n/, ' ')
|
return str.replace(/\n/, ' ')
|
||||||
}
|
}
|
||||||
|
|
||||||
const INT_SIZE = 4; // NOTE: set to `8` if the target has 64 bit ints (`wasm64p32` for example).
|
|
||||||
const STRING_SIZE = 2*INT_SIZE;
|
|
||||||
|
|
||||||
class WasmMemoryInterface {
|
class WasmMemoryInterface {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.memory = null;
|
this.memory = null;
|
||||||
this.exports = null;
|
this.exports = null;
|
||||||
this.listenerMap = {};
|
this.listenerMap = {};
|
||||||
|
|
||||||
|
// Size (in bytes) of the integer type, should be 4 on `js_wasm32` and 8 on `js_wasm64p32`
|
||||||
|
this.intSize = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
setIntSize(size) {
|
||||||
|
this.intSize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
setMemory(memory) {
|
setMemory(memory) {
|
||||||
@@ -73,21 +77,21 @@ class WasmMemoryInterface {
|
|||||||
loadF32(addr) { return this.mem.getFloat32(addr, true); }
|
loadF32(addr) { return this.mem.getFloat32(addr, true); }
|
||||||
loadF64(addr) { return this.mem.getFloat64(addr, true); }
|
loadF64(addr) { return this.mem.getFloat64(addr, true); }
|
||||||
loadInt(addr) {
|
loadInt(addr) {
|
||||||
if (INT_SIZE == 8) {
|
if (this.intSize == 8) {
|
||||||
return this.loadI64(addr);
|
return this.loadI64(addr);
|
||||||
} else if (INT_SIZE == 4) {
|
} else if (this.intSize == 4) {
|
||||||
return this.loadI32(addr);
|
return this.loadI32(addr);
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Unhandled `INT_SIZE`, expected `4` or `8`');
|
throw new Error('Unhandled `intSize`, expected `4` or `8`');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
loadUint(addr) {
|
loadUint(addr) {
|
||||||
if (INT_SIZE == 8) {
|
if (this.intSize == 8) {
|
||||||
return this.loadU64(addr);
|
return this.loadU64(addr);
|
||||||
} else if (INT_SIZE == 4) {
|
} else if (this.intSize == 4) {
|
||||||
return this.loadU32(addr);
|
return this.loadU32(addr);
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Unhandled `INT_SIZE`, expected `4` or `8`');
|
throw new Error('Unhandled `intSize`, expected `4` or `8`');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
loadPtr(addr) { return this.loadU32(addr); }
|
loadPtr(addr) { return this.loadU32(addr); }
|
||||||
@@ -108,31 +112,43 @@ class WasmMemoryInterface {
|
|||||||
storeU32(addr, value) { this.mem.setUint32 (addr, value, true); }
|
storeU32(addr, value) { this.mem.setUint32 (addr, value, true); }
|
||||||
storeI32(addr, value) { this.mem.setInt32 (addr, value, true); }
|
storeI32(addr, value) { this.mem.setInt32 (addr, value, true); }
|
||||||
storeU64(addr, value) {
|
storeU64(addr, value) {
|
||||||
this.mem.setUint32(addr + 0, value, true);
|
this.mem.setUint32(addr + 0, Number(value), true);
|
||||||
this.mem.setUint32(addr + 4, Math.floor(value / 4294967296), true);
|
|
||||||
|
let div = 4294967296;
|
||||||
|
if (typeof value == 'bigint') {
|
||||||
|
div = BigInt(div);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mem.setUint32(addr + 4, Math.floor(Number(value / div)), true);
|
||||||
}
|
}
|
||||||
storeI64(addr, value) {
|
storeI64(addr, value) {
|
||||||
this.mem.setUint32(addr + 0, value, true);
|
this.mem.setUint32(addr + 0, Number(value), true);
|
||||||
this.mem.setInt32 (addr + 4, Math.floor(value / 4294967296), true);
|
|
||||||
|
let div = 4294967296;
|
||||||
|
if (typeof value == 'bigint') {
|
||||||
|
div = BigInt(div);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mem.setInt32(addr + 4, Math.floor(Number(value / div)), true);
|
||||||
}
|
}
|
||||||
storeF32(addr, value) { this.mem.setFloat32(addr, value, true); }
|
storeF32(addr, value) { this.mem.setFloat32(addr, value, true); }
|
||||||
storeF64(addr, value) { this.mem.setFloat64(addr, value, true); }
|
storeF64(addr, value) { this.mem.setFloat64(addr, value, true); }
|
||||||
storeInt(addr, value) {
|
storeInt(addr, value) {
|
||||||
if (INT_SIZE == 8) {
|
if (this.intSize == 8) {
|
||||||
this.storeI64(addr, value);
|
this.storeI64(addr, value);
|
||||||
} else if (INT_SIZE == 4) {
|
} else if (this.intSize == 4) {
|
||||||
this.storeI32(addr, value);
|
this.storeI32(addr, value);
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Unhandled `INT_SIZE`, expected `4` or `8`');
|
throw new Error('Unhandled `intSize`, expected `4` or `8`');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
storeUint(addr, value) {
|
storeUint(addr, value) {
|
||||||
if (INT_SIZE == 8) {
|
if (this.intSize == 8) {
|
||||||
this.storeU64(addr, value);
|
this.storeU64(addr, value);
|
||||||
} else if (INT_SIZE == 4) {
|
} else if (this.intSize == 4) {
|
||||||
this.storeU32(addr, value);
|
this.storeU32(addr, value);
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Unhandled `INT_SIZE`, expected `4` or `8`');
|
throw new Error('Unhandled `intSize`, expected `4` or `8`');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,10 +257,11 @@ class WebGLInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
getSource(shader, strings_ptr, strings_length) {
|
getSource(shader, strings_ptr, strings_length) {
|
||||||
|
const stringSize = this.mem.intSize*2;
|
||||||
let source = "";
|
let source = "";
|
||||||
for (let i = 0; i < strings_length; i++) {
|
for (let i = 0; i < strings_length; i++) {
|
||||||
let ptr = this.mem.loadPtr(strings_ptr + i*STRING_SIZE);
|
let ptr = this.mem.loadPtr(strings_ptr + i*stringSize);
|
||||||
let len = this.mem.loadPtr(strings_ptr + i*STRING_SIZE + 4);
|
let len = this.mem.loadPtr(strings_ptr + i*stringSize + 4);
|
||||||
let str = this.mem.loadString(ptr, len);
|
let str = this.mem.loadString(ptr, len);
|
||||||
source += str;
|
source += str;
|
||||||
}
|
}
|
||||||
@@ -1151,10 +1168,11 @@ class WebGLInterface {
|
|||||||
},
|
},
|
||||||
TransformFeedbackVaryings: (program, varyings_ptr, varyings_len, bufferMode) => {
|
TransformFeedbackVaryings: (program, varyings_ptr, varyings_len, bufferMode) => {
|
||||||
this.assertWebGL2();
|
this.assertWebGL2();
|
||||||
|
const stringSize = this.mem.intSize*2;
|
||||||
let varyings = [];
|
let varyings = [];
|
||||||
for (let i = 0; i < varyings_len; i++) {
|
for (let i = 0; i < varyings_len; i++) {
|
||||||
let ptr = this.mem.loadPtr(varyings_ptr + i*STRING_SIZE + 0*4);
|
let ptr = this.mem.loadPtr(varyings_ptr + i*stringSize + 0*4);
|
||||||
let len = this.mem.loadPtr(varyings_ptr + i*STRING_SIZE + 1*4);
|
let len = this.mem.loadPtr(varyings_ptr + i*stringSize + 1*4);
|
||||||
varyings.push(this.mem.loadString(ptr, len));
|
varyings.push(this.mem.loadString(ptr, len));
|
||||||
}
|
}
|
||||||
this.ctx.transformFeedbackVaryings(this.programs[program], varyings, bufferMode);
|
this.ctx.transformFeedbackVaryings(this.programs[program], varyings, bufferMode);
|
||||||
@@ -1393,7 +1411,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
|
|||||||
},
|
},
|
||||||
"odin_dom": {
|
"odin_dom": {
|
||||||
init_event_raw: (ep) => {
|
init_event_raw: (ep) => {
|
||||||
const W = 4;
|
const W = wasmMemoryInterface.intSize;
|
||||||
let offset = ep;
|
let offset = ep;
|
||||||
let off = (amount, alignment) => {
|
let off = (amount, alignment) => {
|
||||||
if (alignment === undefined) {
|
if (alignment === undefined) {
|
||||||
@@ -1407,6 +1425,13 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
|
|||||||
return x;
|
return x;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let align = (alignment) => {
|
||||||
|
const modulo = offset & (alignment-1);
|
||||||
|
if (modulo != 0) {
|
||||||
|
offset += alignment - modulo
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let wmi = wasmMemoryInterface;
|
let wmi = wasmMemoryInterface;
|
||||||
|
|
||||||
let e = event_temp_data.event;
|
let e = event_temp_data.event;
|
||||||
@@ -1427,10 +1452,12 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
|
|||||||
wmi.storeU32(off(4), 0);
|
wmi.storeU32(off(4), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
wmi.storeUint(off(W), event_temp_data.id_ptr);
|
align(W);
|
||||||
wmi.storeUint(off(W), event_temp_data.id_len);
|
|
||||||
wmi.storeUint(off(W), 0); // padding
|
|
||||||
|
|
||||||
|
wmi.storeI32(off(W), event_temp_data.id_ptr);
|
||||||
|
wmi.storeUint(off(W), event_temp_data.id_len);
|
||||||
|
|
||||||
|
align(8);
|
||||||
wmi.storeF64(off(8), e.timeStamp*1e-3);
|
wmi.storeF64(off(8), e.timeStamp*1e-3);
|
||||||
|
|
||||||
wmi.storeU8(off(1), e.eventPhase);
|
wmi.storeU8(off(1), e.eventPhase);
|
||||||
@@ -1442,7 +1469,7 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
|
|||||||
wmi.storeU8(off(1), !!e.isComposing);
|
wmi.storeU8(off(1), !!e.isComposing);
|
||||||
wmi.storeU8(off(1), !!e.isTrusted);
|
wmi.storeU8(off(1), !!e.isTrusted);
|
||||||
|
|
||||||
let base = off(0, 8);
|
align(8);
|
||||||
if (e instanceof WheelEvent) {
|
if (e instanceof WheelEvent) {
|
||||||
wmi.storeF64(off(8), e.deltaX);
|
wmi.storeF64(off(8), e.deltaX);
|
||||||
wmi.storeF64(off(8), e.deltaY);
|
wmi.storeF64(off(8), e.deltaY);
|
||||||
@@ -1689,8 +1716,15 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement) {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
async function runWasm(wasmPath, consoleElement, extraForeignImports) {
|
/**
|
||||||
let wasmMemoryInterface = new WasmMemoryInterface();
|
* @param {string} wasmPath - Path to the WASM module to run
|
||||||
|
* @param {?HTMLPreElement} consoleElement - Optional console/pre element to append output to, in addition to the console
|
||||||
|
* @param {any} extraForeignImports - Imports, in addition to the default runtime to provide the module
|
||||||
|
* @param {?int} intSize - Size (in bytes) of the integer type, should be 4 on `js_wasm32` and 8 on `js_wasm64p32`
|
||||||
|
*/
|
||||||
|
async function runWasm(wasmPath, consoleElement, extraForeignImports, intSize = 4) {
|
||||||
|
const wasmMemoryInterface = new WasmMemoryInterface();
|
||||||
|
wasmMemoryInterface.setIntSize(intSize);
|
||||||
|
|
||||||
let imports = odinSetupDefaultImports(wasmMemoryInterface, consoleElement);
|
let imports = odinSetupDefaultImports(wasmMemoryInterface, consoleElement);
|
||||||
let exports = {};
|
let exports = {};
|
||||||
|
|||||||
Reference in New Issue
Block a user