A Shallow Dive into WebAssembly

Shoot yourself in the foot with C++ again. This time on the web.

·

4 min read

A Shallow Dive into WebAssembly

If you've been following the buzz in the past few years, you must have certainly heard about WebAssembly, the new, low-level, general purpose programming language that can be used to compile code for the web. Webassembly was created by Mozilla and Google to be extremely fast, safe and in order to provide a better alternative for JavaScript.

Webassembly has been designed with performance in mind. It has been built on top of LLVM which means it will have access to all of LLVM’s optimizations and features.

Webassembly was created by the WebAssembly Community Group in 2015. The goal of Webassembly is to provide a compilation target that has a similar level of performance as native machine code but with the high-level convenience of JavaScript. It is supported by all 4 of the major browser engines today.

But Why WebAssembly?

With the near-native performance promised by WebAssembly, It is quite possible to run really graphically intensive games right in the browser. You surely must have used Figma or atleast heard of it. It's a really powerful Graphic Design app which runs flawlessly, purely on the browser. The reason for its amazing performance is that It is powered by WebAssembly. Infact I am pretty confident that in the near future Audio/Video and Photo editing on the Web could go mainstream with such a leapfrog in performance.

WOW.png

AssemblyScript

In order to write WebAssembly Code which runs in your browser, you don't actually need to learn WebAssembly syntax. WebAssembly is better thought of as a compilation target for other higher level languages which are easier to write code in. In fact, if you know Typescript, you can jump right in to AssemblyScript which has approximately 13000 npm downloads each week at the time of this publication.

But if you're feeling really adventurous, you really gotta try compiling raw C++ into WebAssembly. Yes you heard me right, It is indeed possible to cause a segfault in the browser with your code!

Running C++ in the browser

With WebAssembly, it is possible to call a C++ function in the browser. You could use a toolchain like Emscripten to do this but it is completely possible to compile C++ directly into WebAssembly's binary format wasm by setting wasm32 as the target for clang++.

Let's write a function that does bitwise left-shifts and yields the nth power of 2

extern "C" {
  long long powerOf2(int n) {
    return (1 << n);
  }
}

C++ does Name Mangling which changes the name of the exported function and we won't be able to call it from the browser if that happens. To suppress this behaviour, we need to wrap the function in extern "C".

The C++ file can be compiled with the command :

clang++ --target=wasm32 --no-standard-libraries -Wl,--export-all -Wl,--no-entry -o power.wasm power.cpp
  • --target=wasm32 sets the target architecture to WebAssembly
  • --no-standard-libraries because this target does not support libc++ (discussed later)
  • -Wl,--export-all exports all symbols (the function powerOf2)
  • -Wl,--no-entry tells the compiler that there is no main function

Keep in mind that you're going to need clang++ and thus need to have LLVM installed. You could download the prebuilt packages depending on your OS or build llvm from source

once your wasm binary is generated, you can simply call that function in your webpage like so

<!DOCTYPE html>

<html>
  <head>
    <meta charset="utf-8" />
    <title>WASM instantiateStreaming() test</title>
  </head>

  <body>
    <script>
      WebAssembly.instantiateStreaming(fetch("power.wasm")).then((obj) =>
        console.log(obj.instance.exports.powerOf2(62))
      );
    </script>
  </body>
</html>

Code Based on source: WebAssembly JS-API documentation

Here, We are calling the powerOf2 function with an argument of 62

You can check the output in the console showing 1073741824n and the n indicates that the number is infact a BigInt, which is right as we return a long long from the C++ function.

image.png

As mentioned before, libc++ is not supported by the target wasm32, but in case you want to use it, you could target wasi refer to this answer on stackoverflow.

And That's it! You've successfully run C++ in your browser. It's time now to port all of your legacy code over to the browser. Hope you could follow along with this. Happy memory leaks and race conditions!