Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Messages - Major

Pages: [1]
Help / Re: strlen in wast
« on: October 15, 2017, 10:14:23 pm »
If you don't set $head than it would always load from memory location 0 rather than the location of the string s

Code: [Select]
(i32.load8_u offset=0 (get_local $head))))

Tutorials / Web Assembly Hello World
« on: October 15, 2017, 07:50:23 am »
This past weekend I finally got some time to read through the current documents and mess around with various projects including WAVM. In the process after discovering no one seems to have bothered to create a Hello World! program, so I did.

WebAssembly currently has two formats, a binary format and an editable AST form.  (They are not final and there is even talk of going with something other than the AST form for the official text mode.)  Given that wasm AST is readable one thing I have watched for has been someone posting a Hello World! program as that provides a rich entry point as it doesn't require that you figure out how to compile any C code into wasm to see what it would look like. (I have seen examples that show off adding two numbers, but Hello World being such a classic I figured someone would eventually make it.)  Given the intertwined history of Emscripten with WebAssembly it wasn't a surprise when reading through the WAVM source I discovered that it had exposed Emscripten intrinsics so programs compiled using Emscripten could be run on WAVM.

A short while after finding the Emscripten intrinsics I had a working WebAssembly Hello World! program. The wasm ATS isn't exactly made for programming (typically you will compile to it) and no doubt this example will be improved upon and might even break as WebAssembly improves and changes the spec, but it brings the barrier for playing with WebAssembly down a little bit.  Enjoy!

Code: [Select]
;; WebAssembly WASM AST Hello World! program

  (memory 1
   (segment 8 "hello world!\n")
  (import $__fwrite "env" "_fwrite" (param i32 i32 i32 i32) (result i32))
  (import $_get__stdout "env" "get__stdout" (param) (result i32))
  (export "main" $main)

  (func $main (result i32)
    (local $stdout i32)
    (set_local $stdout (call_import $_get__stdout))

    (return (call_import $__fwrite
       (i32.const 8)         ;; void *ptr    => Address of our string
       (i32.const 1)         ;; size_t size  => Data size
       (i32.const 13)        ;; size_t nmemb => Length of our string
       (get_local $stdout))  ;; stream

To run the program using WAVM save it locally to a file called helloworld.wast and execute it with the following command:
Code: [Select]
$ ./bin/wavm helloworld.wast
And for the inevitable comment that points out how much smaller it could be, here it is without comments, spaces, a local variable, return value and all of the other bits that make the program more useful as example code, but is "so much better" at only 6 lines.

Code: [Select]
  (memory 1 (segment 0 "Hello World!\n"))
  (import $__fwrite "env" "_fwrite" (param i32 i32 i32 i32) (result i32))
  (import $_get__stdout "env" "get__stdout" (param) (result i32))
  (func "main" (call_import $__fwrite (i32.const 0)(i32.const 1)(i32.const 13)(call_import $_get__stdout)))

And while you can't run this hello world on it, if you are just looking to explore what can be coded in wast you can play around with WebAssembly on the WebAssembly playground which was recently created by Jan Wolski. If you want to try going from a c source file all the way to the browser check this WebAssembly end to end how to document.

Discussions / WebAssembly playground
« on: October 15, 2017, 12:38:23 am »
Thought this was quite cool, definitely worth checking out:


Show Off / WAVM - WebAssembly VM
« on: October 14, 2017, 05:26:23 pm »

Tutorials / Build Your First Thing With WebAssembly
« on: October 13, 2017, 12:38:23 pm »
What is WebAssembly?
Well the official website describes it as:
WebAssembly or wasm is a new portable, size- and load-time-efficient format suitable for compilation to the web.

Uhh... wat? Format what? Text? Binary? Frankly this is just a bad description. So instead, get out your buzzword bingo cards and I'll wrap up all my experience with wasm and come up with my own description:

WebAssembly or wasm is a bytecode specification for writing performant, browser agnostic web components.

So we're still not quite to the point of sounding totally awesome with a quip, but here comes the rest of the elevator pitch. WebAssembly realizes performance gains by using statically typed variables which are much more efficient to reference than dynamically typed varaibles at runtime. WebAssembly is being developed by a W3C Community Group to eventually be supported by all spec compliant browsers. And the killer feature, eventually you'll be able to write these web components in any language.

Sounds a lot cooler now, doesn't it?

Let's get started
When it's time to learn a new thing, I usually look for the smallest possible example to see it working. Unfortunately for us all, that's not a reality with WebAssembly. In it's current state, wasm is basically a specification for bytecode. Imagine if back in 1996, some engineers from Sun Microsystems introduced the JVM... but no Java. I imagine that conversation going a little like: "Hey y'all, come check out this bytecode executing virtual machine we made!" "Cool! How do we write code for it?"

"Uhh.. cool man. I'll check it out sometime." "Awesome, let us know what you think and drop us a line on our github page if you run into any trouble." "You got it, we're gonna check out some of the other projects over here now."

And even that's a bad example because the JVM is based on the Java language, but hopefully you get the point. If your byte code doesn't show up on the scene with tools that compile to it, you're gonna have a hard time getting off the ground. So how do we actually get started then?

What came before WebAssembly
Most technology is the result of innovation, especially when a reasonable attempt is being made to make it a formal specification. Wasm is no different, it is effectively a continuation of the work done on asm.js, a specification for writing javascript components in a way that can be compiled with static typing. Wasm extends those ideas by writing a specification for bytecode that can be targeted by a compiler of any language, sent over the wire as a binary file instead of text encoding and developed over time by representatives from many of the major browsers instead of just Mozilla.

asm.js is just a specification for writing javascript using a minimal subset of the language features. You can write simple asm.js by hand, and if you just want to get your hands dirty, it's definitely the way to start. (it's best to put this in it's own file for later on, and the convention is to use your-module-name.asm.js)

Code: [Select]
function MyMathModule(global) {
    "use asm";
    var exp = global.Math.exp;
    function doubleExp(value) {
        value = +value;
        return +(+exp(+value) * 2.0);
    return { doubleExp: doubleExp };

This isn't a particularly useful function, but it is to spec. If it looks silly to you, you're not alone, but almost every character there is necessary. All of those unary + operators act as type annotations for the compiler so it knows that they are doubles and doesn't have to figure out what they are at runtime. It's super finicky but if you mess something up, the console in firefox will give you a reasonable error message to work off of.

If you want to use it in a browser, something like this works:

Code: [Select]
var myMath = new MyMathModule(window);
for(var i = 0; i < 5; i++) {

And if you got all that correct, the output should look something like this:

Get to the WebAssembly already
Now that we have a working piece of asm.js, we can use the tools provided by the WebAssembly github page to compile it to wasm. Now you have to clone the repo and build the tools yourself. This is the worst part. These tools are under constant development and it's a common occurrence that they break from time to time, especially if you're on windows.

You're definitely going to need make and cmake with commandline tools installed on your system regardless of whether you're on windows or mac. If you're on windows, you'll also need a version of visual studio 2015 installed. If you're on a mac, follow these instructions, and if you're on windows, follow these instructions: https://github.com/brakmic/bazaar/blob/master/webassembly/COMPILING_WIN32.md

Distributing working binaries would be a huge step in the right direction for the WebAssembly team.

If you managed to get through this successfully, a bin folder was created in the binaryen directory with some tools we can use to convert our asm.js to wasm. The first tool is asm2wasm.exe. This tool compiles the asm.js code to .s format code, which is a textual representation of the abstract syntax tree (AST) for the wasm output. Once you run the utility, you end up with something that looks like this:

Code: [Select]
  (memory 256 256)
  (export "memory" memory)
  (type $FUNCSIG$dd (func (param f64) (result f64)))
  (import $exp "global.Math" "exp" (param f64) (result f64))
  (export "doubleExp" $doubleExp)
  (func $doubleExp (param $0 f64) (result f64)
      (call_import $exp
        (get_local $0)
      (f64.const 2)

In the future we can disect this line by line, but for now I just want to show it to you and mention that since wasm is a binary format, right clicking and viewing source like you can do for any javascript today just doesn't work; it would look a lot like that byte code up top. The current plan is that when you view source on a wasm module, it would disassemble to this format to make it human readable.

The next thing we need to do is convert this .s format code to a wasm binary, and to do that we use wasm-as.exe, for wasm assembler. Once you run this file, you'll end up with the actual wasm bytecode we need for the browser.

Next, grab yourself the latest copy of Firefox or Chrome Canary and enable WebAssembly.

For Firefox, you'll need to go to about:config in the url bar, and then tell it you'll be careful. After that, type wasm in the search bar and double click javascript.options.wasm until the value is set to true and then completely restart the browser.

For Chrome Canary, you'll need to go to chrome://flags and scroll down until you find Experimental WebAssembly, click the enable link and completely restart the browser.

The last step is get the module running in the browser. This was another pain point when I first started because it's totally hidden. I couldn't anything in the spec related to the javascript API for using wasm modules. I ended up just opening up a console in Chrome Canary and typing WebAsse and nothing popped up. Next I tried typing Was and then it popped up! Looking at that object in the inspector was about the poorest documentation ever, but then it occurred to me to use some other tools (emscripten) that compiles to wasm. How I did that is the topic of another blog post, but after doing that I was able to create a working example.

Some time later I was clicking around and eventually ended up in the design repo for WebAssembly. There I saw a file named JS.md so I clicked on it and sure as shit, there was an actual javascript API with documentation. Pay close attention to the italic note at the top. The best part of this page however was the snippet at the very bottom which shows you how to load up a module very minimally. All I had to do was switch out the relevant parts and try it out.

Code: [Select]
    .then(function(response) {
        return response.arrayBuffer();
    .then(function(buffer) {
        var dependencies = {
            "global": {},
            "env": {}
        dependencies["global.Math"] = window.Math;
        var moduleBufferView = new Uint8Array(buffer);
        var myMathModule = Wasm.instantiateModule(moduleBufferView, dependencies);
        for(var i = 0; i < 5; i++) {

Toss that in an html file, fire up a server in your local folder and load it up. Here's what it looks like in both browsers:

Time to go file a bug report I guess. Remember, it's all experimental technology and very unstable, so try not to get overly frustrated when things like this happen.

ou've created your first WebAssembly component. What's next? We're really just cracking the surface here. Writing asm.js by hand was pretty cruical to this example, but doing anything non trivial in it takes a long time and lot of patience. Using emscripten to compile non trivial apps to asm.js is much easier. On that note, I highly suggest reading up on the asm.js specification, especially the memory model, because a lot of the concepts from there carry over to WebAssembly. Another quirk is that right now you cannot directly pass arrays as function arguments. There is some agreement that that should change, but nothing has made it in the spec yet. Go brush up on your pointer logic.

Another note, when you start doing non trivial things in wasm, you might find that it actually performs slower in WebAssembly than plain old javascript. Just remember that modern javascript engines are highly optimized for compiling javascript and it will take time for wasm compilation to catch up. WebAssembly is not ready for production usage.

Tutorials / WebAssembly talk from BlinkOn 5
« on: October 11, 2017, 03:02:23 am »
50min talk about WebAssembly from BlinkOn 5. A lot of more in-depth discussion than what is typically written about.


Help / Re: Help understanding difference in c to wasm compiler output(s)
« on: October 06, 2017, 07:50:23 am »
neglecting that seems to only double the expected output, while I'm otherwise seeing about 143 times the expected output... I'm new here, so I'm sure there are reasons and years-long git threads as to why, but it doesn't seem to fit wasm's stated size and load-time efficiency mission as it stands now.... (though it looks like building as a side module gets you down to only a little cruft, so... progress)

Could you please share those wasm files with me? I'm working on a disassembler / optimiser and these examples help me a lot!

just go over to the linked wasmFiddle page, select settings and build with any optimization state you like. the emcc one, w/ all that cruft, idk what is inside and as this is a work computer, I'd rather not, but if you install emsdk or emscripten, llvm, etc ( cloning from their github pages seemed to work best for me, especially since you need to install from the incoming branch ) you should get similar results with the supplied emcc command

Yea I've got the wasmFiddle outputs. -O3 works well, there's only a small number of useless bits in there. It seems acceptable to me. This version is 172 bytes.
-O0 doesn't work at all. Attempting to run the resulting wasm just gives you 'VM121-0 wasm-f1084df6-0:9 Uncaught RuntimeError: memory access out of bounds at <WASM UNNAMED> (<WASM>
  • +15)' and this is purely due to buggy output, not missing JS imports or whatever. However even this version is only 227 bytes in size.

I'm interested in seeing the huge 24481 bytes generated by emcc but last time I tried I was not able to get emcc working on my Windows machine. I'll try on a mac and see what happens.
For comparison the hand-compiled version I posted before is 140 bytes which is pretty close to the minimum possible for this piece of C code.

Help / Re: Help understanding difference in c to wasm compiler output(s)
« on: October 05, 2017, 05:26:23 pm »
neglecting that seems to only double the expected output, while I'm otherwise seeing about 143 times the expected output... I'm new here, so I'm sure there are reasons and years-long git threads as to why, but it doesn't seem to fit wasm's stated size and load-time efficiency mission as it stands now.... (though it looks like building as a side module gets you down to only a little cruft, so... progress)

Could you please share those wasm files with me? I'm working on a disassembler / optimiser and these examples help me a lot!

Help / Re: Help understanding difference in c to wasm compiler output(s)
« on: October 04, 2017, 07:50:23 pm »
I was talking to someone about compiling C to Wasm yesterday and we discovered that the -O3 optimised compiler output from Clang is pretty good, while the unoptimised output is so full of crap that it won't even run in the browsers at all.
Could you try adding -O3 to your emcc command and see what happens?

Help / Re: Help understanding difference in c to wasm compiler output(s)
« on: October 04, 2017, 05:26:23 am »
Just for fun, here's the decompiled WASM binary so you can see where all the bytes are going:


Try it out here

Here's a good overview:

- Wasm is smaller and thus quicker to download than JS
- Wasm is much easier to parse / decode than JS, saving CPU time
- Wasm is easier to optimise which means it runs faster
- Wasm does not have garbage collection

Pages: [1]