C++ WebAssembly assembler

Overview

wasmblr

A single header file WebAssembly assembler.

This library makes it easier to generate web assembly binaries directly from C++. Useful for JIT compilation from within projects compiled with Emscripten. For examples see below, or read the test.cc file.

Contributions welcome!

Usage

#include "wasmblr.h" and compile with -std=c++11 or higher.

In C++:

struct Code : wasmblr::CodeGenerator {
  Code() : wasmblr::CodeGenerator() {
    auto add_func = function({f32, f32}, {f32}, [&]() {
      local.get(0);
      local.get(1);
      f32.add();
    });
    export_(add_func, "add");
  }
};


Code c;
auto bytes = c.emit();
std::ofstream wasm("add.wasm", std::ios::binary);
wasm.write((char*)bytes.data(), bytes.size());

If you'd prefer to avoid inheritance, you can use the code generator directly:

wasmblr::CodeGenerator cg;
auto add_func = cg.function({cg.f32, cg.f32}, {cg.f32}, [&]() {
  cg.local.get(0);
  cg.local.get(1);
  cg.f32.add();
});
cg.export_(add_func, "add");

auto bytes = cg.emit();
std::ofstream wasm("add.wasm", std::ios::binary);
wasm.write((char*)bytes.data(), bytes.size());

And then, in JavaScript:

const wasm = fs.readFileSync('add.wasm'); // or however you'd like to load it
const m = new WebAssembly.Module(wasm);
const instance = new WebAssembly.Instance(m, {});
// use the function
console.log(instance.exports.add(8, 9));

Test

With node.js installed,

g++ test.cc -std=c++11 -o test
./test

Supported Features

The semantics of the assembler attempt to mimic the WebAssembly standard closely. In the case of reserved keywords in C++ (such as export, xor, etc.), the mnemonic has an underscore appended (e.g. export_, i32.xor_).

A couple of example uses follow:

Recursion

struct Code : wasmblr::CodeGenerator {
  // NB: Needs to be a class variable; the function body is evaluated later
  uint32_t factorial;
  Code() : wasmblr::CodeGenerator() {
    factorial = function({f32}, {f32}, [&]() {
      local.get(0);
      f32.const_(1.0f);
      f32.lt();
      // base case
      if_(f32);
      {
        f32.const_(1.0f);
      }
      else_();
      {
        local.get(0);
        local.get(0);
        f32.const_(1.0f);
        f32.sub();
        call(factorial);
        f32.mul();
      }
      end();
    });
    export_(factorial, "factorial");
  }
};

Blocks

If-statements

struct Code : wasmblr::CodeGenerator {
  Code() : wasmblr::CodeGenerator() {
    auto if_func = function({f32}, {f32}, [&]() {
      f32.const_(0.0f);
      local.get(0);
      f32.gt();
      if_(f32);
      f32.const_(0.0f);
      else_();
      local.get(0);
      end();
    });
    export_(if_func, "relu");
  }
};

Loops

struct Code : wasmblr::CodeGenerator {
  Code() : wasmblr::CodeGenerator() {
    auto loop_fn = function({}, {i32}, [&]() {
      auto i = local(i32);

      loop(void_);
      {
        local.get(i);
        i32.const_(1);
        i32.add();
        local.set(i);

        local.get(i);
        i32.const_(10);
        i32.lt_s();
        br_if(0);
      }
      end();
      local.get(i);
    });
    export_(loop_fn, "loop");
  }
};

Memory

struct Code : wasmblr::CodeGenerator {
  Code() : wasmblr::CodeGenerator() {
    memory(1, 10).export_("mem");
    auto store = function({}, {}, [&]() {
      i32.const_(0);     // index 0
      i32.const_(1337);  // value 1337
      i32.store(0, 0);   // align 0, offset 0
    });
    export_(store, "store");
  }
};

SIMD (32-bit lanes for now)

struct Code : wasmblr::CodeGenerator {
  Code() : wasmblr::CodeGenerator() {
    memory(1, 10).export_("mem");
    auto square = function({}, {}, [&]() {
      auto vec = local(v128);
      i32.const_(0);
      v128.load();
      local.set(vec);

      local.get(vec);
      local.get(vec);
      v128.f32x4_mul();
      local.set(vec);

      i32.const_(0);
      local.get(vec);
      v128.store();
    });
    export_(square, "simd_square");
  }
};

TODO

Many things. I would appreciate any help filing issues for missing things!

You might also like...
A basic assembler

Assembler ASSEMBLER DERLEYİCİSİ Programlama Dilleri (derleyiciler) giriş olarak yazılan bir programın kaynak kodunu alır (kodun doğru yazıldığı varsay

A fully customisable assembler for your own instruction sets

CASM A fully customisable assembler for your own instruction sets! What Is CASM? 🇨 Documentation 📚 Command-Line Usage 💻 How To Install CASM 💾 Buil

x86-64 Assembler based on Zydis

Zasm : x86-64 Assembler based on Zydis Why? Some of my projects were using Zydis and AsmJit where instructions where were first decoded with Zydis and

Minimalistic C++/Python GUI library for OpenGL, GLES2/3, Metal, and WebAssembly/WebGL
Minimalistic C++/Python GUI library for OpenGL, GLES2/3, Metal, and WebAssembly/WebGL

NanoGUI NanoGUI is a minimalistic cross-platform widget library for OpenGL 3+, GLES 2/3, and Metal. It supports automatic layout generation, stateful

2048 written in C and compiled to WebAssembly

2048.wasm 2048 written in C and compiled to WebAssembly Play Use the arrow keys ( ᐊ ᐅ ᐃ ᐁ ) to slide the tiles. press n to play over. Usage Compile C

Portrait segmentation in your web browser with ncnn and webassembly

ncnn-webassembly-portrait-segmentation open https://nihui.github.io/ncnn-webassembly-portrait-segmentation and enjoy build and deploy Install emscript

web server & client. Fully C++/WebAssembly. Server runs on google cloud function. Client uses a C++ virtual dom.

Starter project. A web server and client fully made with C++/WebAssembly. A simple CMake configuration describes how to build and run everything.

WasmEdge Runtime is a high-performance, extensible, and hardware optimized WebAssembly Virtual Machine for automotive, cloud, AI, and blockchain applications.

WasmEdge Runtime is a high-performance, extensible, and hardware optimized WebAssembly Virtual Machine for automotive, cloud, AI, and blockchain applications.

Deploy SCRFD, an efficient high accuracy face detection approach, in your web browser with ncnn and webassembly

ncnn-webassembly-scrfd open https://nihui.github.io/ncnn-webassembly-scrfd and enjoy build and deploy Install emscripten

A (relatively) small node library to clone and pull git repositories in a standalone manner thanks to libgit2, powered by WebAssembly and Emscripten

simple-git-wasm A (relatively) small node library to clone and pull git repositories in a standalone manner thanks to libgit2, powered by WebAssembly

Deploy OcrLite in your web browser with ncnn and webassembly
Deploy OcrLite in your web browser with ncnn and webassembly

ncnn-webassembly-ocrlite Requirements ncnn webassembly opencv-mobile webassembly 3.4.13 Build Install emscripten git clone https://github.com/emscript

Python bindings for Wasm3, the fastest WebAssembly interpreter

pywasm3 Python bindings for Wasm3, the fastest WebAssembly interpreter Main repository: Wasm3 project Install # Latest release: pip3 install pywasm3

Chocolate Doom WebAssembly port with WebSockets support

Wasm Doom This is a Chocolate Doom WebAssembly port with WebSockets support. Requirements You need to install Emscripten and a few other tools first:

A WebAssembly interpreter written in C for demonstration.
A WebAssembly interpreter written in C for demonstration.

wasmc 中文文档 A WebAssembly interpreter written in C for demonstration. This repository implements a WebAssembly interpreter. It is written to clarify ho

A tiny programming language that transpiles to C, C++, Java, TypeScript, Python, C#, Swift, Lua and WebAssembly 🚀
A tiny programming language that transpiles to C, C++, Java, TypeScript, Python, C#, Swift, Lua and WebAssembly 🚀

A tiny programming language that transpiles to C, C++, Java, TypeScript, Python, C#, Swift, Lua and WebAssembly 🚀

Very fast Markdown parser and HTML generator implemented in WebAssembly, based on md4c

Very fast Markdown parser and HTML generator implemented in WebAssembly, based on md4c

A fully-featured Falling-Sand game in the browser - Powered by WebAssembly
A fully-featured Falling-Sand game in the browser - Powered by WebAssembly

PLOP A fully-featured Falling-Sand game powered by WebAssembly! Try it out here Building Required Dev-Dependencies: clang uglifyjs $ git clone https:/

WebAssembly version of DuckDB

DuckDB-Wasm DuckDB-Wasm is an in-process analytical SQL database for the browser. It is powered by WebAssembly, speaks Arrow fluently, reads Parquet,

Run statically-compiled WebAssembly apps on any embedded platform
Run statically-compiled WebAssembly apps on any embedded platform

embedded-wasm-apps Run native, statically-compiled AssemblyScript, Rust, C/C++, TinyGo, Zig, etc. apps on any platform How it works The approach is si

Comments
  • Printing in human-readable textual format

    Printing in human-readable textual format

    Please, could you possibly share if this library also supports emitting WebAssembly Code in WAT (WebAssembly Text format) format?

    In case it does not support emitting in WAT format, could you possibly share what/where I could do some changes to get output in WAT format, please?

    opened by Shaikh-Ubaid 2
  • [WIP] code size reduction

    [WIP] code size reduction

    Removing a lot of the STL to reduce bloated binary size

    Was:

    -rw-r--r--  1 bwasti  staff    50K Jan 21 00:01 add.js
    

    This branch:

    -rw-r--r--   1 bwasti  staff    30K Jan 21 00:00 add.js
    
    opened by bwasti 0
Owner
Bram Wasti
https://twitter.com/bwasti
Bram Wasti
🚀 The fastest WebAssembly interpreter, and the most universal runtime

Wasm3 The fastest WebAssembly interpreter, and the most universal runtime. Based on CoreMark 1.0 and independent benchmarks. Your mileage may vary. Ge

Wasm3 Labs 5.6k Dec 31, 2022
eBPF bytecode assembler and compiler

An eBPF bytecode assembler and compiler that * Assembles the bytecode to object code. * Compiles the bytecode to C macro preprocessors. Symbolic

Emil Masoumi 6 Jan 23, 2022
Commodore 6502ASM, the original 6502/65C02/65CE02 Assembler used by Commodore for C65 project

Commodore 6502ASM This is the source code of the 6502/65C02/65CE02 assembler developed and used by Commodore for the C65 project. It aims to be compat

Michael Steil 17 Nov 29, 2022
ASMotor is a portable and generic assembler engine and development system written in ANSI C99

ASMotor is a portable and generic assembler engine and development system written in ANSI C99 and licensed under the GNU Public License v3. The package consists of the assembler, the librarian and the linker. It can be used as either a cross or native development system.

null 42 Nov 18, 2022
A mini assembler for x86_64, written for fun and learning.

minias A mini assembler for x86_64, written for fun and learning. Goals: A simple, tiny, fast implementation (in that order). Assemble the output of c

null 193 Dec 9, 2022
A mini x86-64 assembler for fun

A mini x86-64 assembler for fun

null 193 Dec 9, 2022
A simple assembler, made primarily for assembling output from my compiler.

Assembler This assembler is not currently meant for general use. It supports only the instructions and features emitted (and used) in my C compiler. I

null 2 Nov 14, 2021
Operating system model using an assembler RISC-V RV32I instruction set.(development)

General Information Operating system model using an assembler RISC-V RV32I instruction set.(development) С++ Standard - c++17 gcc 9.3.0(Linux,unicode)

Alex Green 1 Dec 21, 2021
Toy 8 bit CPU with a real assembler

neko8 neko8 is a 8 bit CPU emulator designed to be easy to learn written in C. It uses its own simple architecture and can be programmed in its own fo

rem 4 Jan 4, 2022
x86 Assembler used for generating shellcode

Intel x86 assembler [email protected] syntax: Decimal “integers begin with a non-zero digit followed by zero or more decimal digits (0–9)” B

thescientist 1 Dec 28, 2022