I'm experimenting with webassembly and I've made a toy module that brute forces primes in C
extern "C" {
bool isPrime(int n) {
for (int i = 2; i <= n; i++) {
if (n % i == 0) return false;
}
return true;
}
int getPrimes() {
int primesFound = 0;
for (int i = 2; i < 4206969; i++) {
if (isPrime(i)) {
primesFound++;
}
}
return primesFound;
}
}
Compiling this with emcc /O3 in windows gives me the following byte stream:
0x0, 0x61, 0x73, 0x6d, 0x1, 0x0, 0x0, 0x0, 0x1, 0x8, 0x2, 0x60,
0x0, 0x0, 0x60, 0x0, 0x1, 0x7f, 0x3, 0x3, 0x2, 0x0, 0x1, 0x5, 0x6, 0x1, 0x1, 0x80, 0x2,
0x80, 0x2, 0x7, 0x1f, 0x3, 0x6, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x2, 0x0, 0x9, 0x67,
0x65, 0x74, 0x50, 0x72, 0x69, 0x6d, 0x65, 0x73, 0x0, 0x1, 0x6, 0x5f, 0x73, 0x74, 0x61,
0x72, 0x74, 0x0, 0x0, 0xa, 0x4e, 0x2, 0x3, 0x0, 0x1, 0xb, 0x48, 0x1, 0x4, 0x7f, 0x41,
0x2, 0x21, 0x0, 0x3, 0x40, 0x41, 0x2, 0x21, 0x1, 0x2, 0x40, 0x3, 0x40, 0x20, 0x0, 0x20,
0x1, 0x70, 0x45, 0xd, 0x1, 0x20, 0x0, 0x20, 0x1, 0x46, 0x21, 0x3, 0x20, 0x1, 0x41, 0x1,
0x6a, 0x21, 0x1, 0x20, 0x3, 0x45, 0xd, 0x0, 0xb, 0x20, 0x2, 0x41, 0x1, 0x6a, 0x21, 0x2,
0xb, 0x20, 0x0, 0x41, 0x1, 0x6a, 0x22, 0x0, 0x41, 0xf9, 0xe2, 0x80, 0x2, 0x47, 0xd, 0x0,
0xb, 0x20, 0x2, 0xb, 0xb, 0xa, 0x1, 0x0, 0x41, 0x80, 0xc, 0xb, 0x3, 0xa0, 0x6, 0x50
Which is probably unintelligible to most, but VSC's WASM to WAT tool suggests that this represents the following WASM:
(module
(type $t0 (func))
(type $t1 (func (result i32)))
(func $_start (type $t0)
nop)
(func $getPrimes (type $t1) (result i32)
(local $l0 i32) (local $l1 i32) (local $l2 i32) (local $l3 i32)
i32.const 2
local.set $l0
loop $L0
i32.const 2
local.set $l1
block $B1
loop $L2
local.get $l0
local.get $l1
i32.rem_u
i32.eqz
br_if $B1
local.get $l0
local.get $l1
i32.eq
local.set $l3
local.get $l1
i32.const 1
i32.add
local.set $l1
local.get $l3
i32.eqz
br_if $L2
end
local.get $l2
i32.const 1
i32.add
local.set $l2
end
local.get $l0
i32.const 1
i32.add
local.tee $l0
i32.const 4206969
i32.ne
br_if $L0
end
local.get $l2)
(memory $memory 256 256)
(export "memory" (memory 0))
(export "getPrimes" (func $getPrimes))
(export "_start" (func $_start))
(data $d0 (i32.const 1536) "\a0\06P"))
From another program the following EM_JS is called, the intent being that from WASM, it tells the javascript engine to compile some WASM and then execute it.
EM_JS(int, call_wasmBlock, (const uint8_t* wasmBlock, uint32_t length), {
let wasmBuf = new Uint8Array(Module.HEAPU8.buffer, wasmBlock, length);
WebAssembly.instantiate(wasmBuf)
.then(
obj => console.log(obj.instance.exports.getPrimes())
);
});
I get this error:
Uncaught (in promise) CompileError: WebAssembly.instantiate(): unexpected section <Export> @+158
I am not fully sure where to go with this and itis mostly just experimentation with the limits of webassembly.
index.js
test.cpp
primes.cpp