1

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.

1 Answer 1

1

index.js

'use strict';

import fs from 'fs';

const bin = fs.readFileSync('test.wasm');

// only checks for primes up to 100
const primeAppBin = new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 1, 10, 2, 96, 0, 1, 127, 96, 1, 127, 1, 127, 3, 3, 2, 1, 0, 5, 4, 1, 1, 1, 1, 7, 32, 3, 6, 109, 101, 109, 111, 114, 121, 2, 0, 7, 105, 115, 80, 114, 105, 109, 101, 0, 0, 9, 103, 101, 116, 80, 114, 105, 109, 101, 115, 0, 1, 10, 142, 1, 2, 61, 1, 2, 127, 65, 1, 33, 1, 32, 0, 65, 4, 78, 4, 127, 32, 0, 65, 127, 106, 33, 2, 65, 2, 33, 1, 2, 64, 3, 64, 32, 0, 32, 1, 111, 69, 13, 1, 32, 1, 65, 1, 106, 34, 1, 32, 2, 71, 13, 0, 11, 65, 1, 15, 11, 65, 0, 5, 65, 1, 11, 11, 78, 1, 4, 127, 65, 2, 33, 0, 3, 64, 2, 64, 32, 0, 65, 4, 79, 4, 64, 32, 0, 65, 127, 106, 33, 3, 65, 2, 33, 2, 3, 64, 32, 0, 32, 2, 112, 69, 13, 2, 32, 2, 65, 1, 106, 34, 2, 32, 3, 71, 13, 0, 11, 11, 32, 1, 65, 1, 106, 33, 1, 11, 32, 0, 65, 1, 106, 34, 0, 65, 228, 0, 71, 13, 0, 11, 32, 1, 11, 11, 9, 1, 0, 65, 128, 12, 11, 2, 160, 6]);

(async () => {
  let buff;
  const imports = {
    env: {
      execWasm: (byteOffset, length) => {
        WebAssembly.instantiate(new Uint8Array(buff, byteOffset, length)).then(app => console.log(app.instance.exports.getPrimes() + ' primes found'));
      }
    }
  };
  const app = await WebAssembly.instantiate(bin, imports);
  const { memory, test } = app.instance.exports;
  const view = new Uint8Array(memory.buffer, 0, primeAppBin.length);
  for (let i in view) view[i] = primeAppBin[i];
  buff = memory.buffer;
  test(view.byteOffset, view.byteLength);
})();

test.cpp

// emcc -O3 "test.cpp" -o "test.wasm" -s STANDALONE_WASM -s EXPORTED_FUNCTIONS="['_test']" -s ERROR_ON_UNDEFINED_SYMBOLS=0 -Wl,--no-entry -msimd128 -s INITIAL_MEMORY=64kb -s ALLOW_MEMORY_GROWTH=0 -s TOTAL_STACK=0kb

#include <emscripten.h>

extern "C" {
  extern void execWasm(int byteOffset, int length);
  EMSCRIPTEN_KEEPALIVE
  void test (int byteOffset, int length) {
    execWasm(byteOffset, length);
  }
}

primes.cpp

// emcc -O3 "primes.cpp" -o "primes.wasm" -s STANDALONE_WASM -s EXPORTED_FUNCTIONS="['_getPrimes']" -s ERROR_ON_UNDEFINED_SYMBOLS=0 -Wl,--no-entry -msimd128 -s INITIAL_MEMORY=64kb -s ALLOW_MEMORY_GROWTH=0 -s TOTAL_STACK=0kb

extern "C" {
    bool isPrime(int n) {
        for (int i = 2; i < n - 1; i++) {
            if (n % i == 0)
            return false;
        }
    return true;
    }

    int getPrimes() {
        int primesFound = 0;

        for (int i = 2; i < 4'206'969; i++) {
            if (isPrime(i)) {
                primesFound++;
            }
        }
        return primesFound;
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.