私は WebAssembly を試していて、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;
}
}
これを Windows で emcc /O3 を使用してコンパイルすると、次のバイト ストリームが得られます。
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
おそらくほとんどの人には理解できないでしょうが、VSC の WASM to WAT ツールは、これが次の 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"))
別のプログラムから、次の EM_JS が呼び出されます。これは、WASM からの意図であり、javascript エンジンに WASM をコンパイルして実行するように指示します。
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())
);
});
次のエラーが表示されます。
Uncaught (in promise) CompileError: WebAssembly.instantiate(): unexpected section <Export> @+158
これでどこに行くべきか完全にはわかりません。ほとんどの場合、WebAssembly の制限を試しているだけです。