How to build a wasm binary

1,269 views
Skip to first unread message

Wink Saville

unread,
Apr 14, 2017, 4:05:36 PM4/14/17
to emscripten-discuss
I'd like to compile C source files to a wasm file module, so that I might use it with another compiler that generates wasm, such as TurboScript. For example here is a simple C file:

int addTwo(int a, int b) {
    return a + b;
}

So I tried:

$ emcc -c addTwo.c -o addTwo.wasm -s WASM=1

Them ise wasm2wast to see the result, but that failed:

$ wasm2wast addTwo.wasm -o addTwo.wast
error: @0x00000004: bad magic value

I then read the emcc help and determined that emcc defaults to bc output

$ emcc -Oz -c addTwo.c -o addTwo.bc

And then disassembled the output:

$ llvm-dis < addTwo.bc
; ModuleID = '<stdin>'
source_filename = "addTwo.c"
target datalayout = "e-p:32:32-i64:64-v128:32:128-n32-S128"
target triple = "asmjs-unknown-emscripten"

; Function Attrs: minsize noinline norecurse nounwind optsize readnone
define i32 @addTwo(i32, i32) local_unnamed_addr #0 {
  %3 = add nsw i32 %1, %0
  ret i32 %3
}

attributes #0 = { minsize noinline norecurse nounwind optsize readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.ident = !{!0}

!0 = !{!"clang version 4.0.0 (https://github.com/kripken/emscripten-fastcomp-clang d4b1e0785f1ee15ab78207de4380e82e3407c6ea) (https://github.com/kripken/emscripten-fastcomp 084a1d917ea6172e7d65b9d8c254df843851ec98) (emscripten 1.37.9 : 1.37.9)"}


So the output is bc, now how to go from bc to wasm? Or maybe there is a "right" way :)

Alon Zakai

unread,
Apr 14, 2017, 5:05:06 PM4/14/17
to emscripten-discuss
In general most apps use emcc to emit a combination of js+wasm, where the js has all the necessary code to load and support the wasm. But if you want to emit standalone wasm (no support js) that you can load and use in some other manner, there is


--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsub...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Wink Saville

unread,
Apr 14, 2017, 6:17:18 PM4/14/17
to emscripten-discuss
Worked, thanks. The command I used was:

emcc -Oz addTwo.c -s WASM=1 -s SIDE_MODULE=1 -o addTwo.wasm

And converted to wast with:

wasm2wast addTwo.wasm -o addTwo.wast

And the resulting wast was:

(module
  (type (;0;) (func (param i32 i32) (result i32)))
  (type (;1;) (func))
  (import "env" "memoryBase" (global (;0;) i32))
  (import "env" "memory" (memory (;0;) 256))
  (import "env" "table" (table (;0;) 0 anyfunc))
  (import "env" "tableBase" (global (;1;) i32))
  (func (;0;) (type 0) (param i32 i32) (result i32)
    get_local 1
    get_local 0
    i32.add)
  (func (;1;) (type 1)
    nop)
  (func (;2;) (type 1)
    block  ;; label = @1
      get_global 0
      set_global 2
      get_global 2
      i32.const 5242880
      i32.add
      set_global 3
      call 1
    end)
  (global (;2;) (mut i32) (i32.const 0))
  (global (;3;) (mut i32) (i32.const 0))
  (export "__post_instantiate" (func 2))
  (export "_addTwo" (func 0))
  (export "runPostSets" (func 1)))

Where can I find information on semantics associated with memorybase, memory global, and table?

Thanks again!

Alon Zakai

unread,
Apr 14, 2017, 10:20:11 PM4/14/17
to emscripten-discuss

To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Wink Saville

unread,
Apr 15, 2017, 3:02:00 AM4/15/17
to emscripten-discuss
That helps thanks, but now I'd like to use emcc to generate code so that I can "staticly" link wasm files.

So I created an inc function which uses addTwo to increment a variable:

$ cat inc.c
extern int addTwo(int a, int b);

int inc(int v) {
    return addTwo(v, 1);
}

If I compile inc.c to wasm using emcc and then convert it to wast using wasm2wast

emcc -Oz inc.c -s WASM=1 -s SIDE_MODULE=1 -o inc.wasm
wasm2wast inc.wasm -o inc.wast

The result is:

(module
  (type (;0;) (func (param i32 i32) (result i32)))
  (type (;1;) (func (param i32) (result i32)))
  (type (;2;) (func))
  (import "env" "memoryBase" (global (;0;) i32))
  (import "env" "_addTwo" (func (;0;) (type 0)))
  (import "env" "memory" (memory (;0;) 256))
  (import "env" "table" (table (;0;) 0 anyfunc))
  (import "env" "tableBase" (global (;1;) i32))
  (func (;1;) (type 1) (param i32) (result i32)
    get_local 0
    i32.const 1
    call 0)
  (func (;2;) (type 2)
    nop)
  (func (;3;) (type 2)
    block  ;; label = @1
      get_global 0
      set_global 2
      get_global 2
      i32.const 5242880
      i32.add
      set_global 3
      call 2
    end)
  (global (;2;) (mut i32) (i32.const 0))
  (global (;3;) (mut i32) (i32.const 0))
  (export "_inc" (func 1))
  (export "__post_instantiate" (func 3))
  (export "runPostSets" (func 2)))

I then tried to use wabt/wasm-link to link inc.wasm and addTwo.wasm I get an error:

wasm-link addTwo.wasm inc.wasm -o addTwoInc.wasm
unsupported import module: env

I looked at the source for wasm-link and the error comes from binary-reader-linker.cc:

Result BinaryReaderLinker::OnImport(uint32_t index,
                                    StringSlice module_name,
                                    StringSlice field_name) {
  if (!string_slice_eq_cstr(&module_name, WABT_LINK_MODULE_NAME)) {
    WABT_FATAL("unsupported import module: " PRIstringslice,
               WABT_PRINTF_STRING_SLICE_ARG(module_name));
  }
  return Result::Ok;

And WABT_LINK_MODULE_NAME comes from:

./wasm-link.h:#define WABT_LINK_MODULE_NAME "__extern"



Soooooo, the problem seems to be the import sections are named "env" where as
wasm-link expects them to be "__extern". How can is request emcc to create
import sections named "__extern"?

 

To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsub...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Alon Zakai

unread,
Apr 16, 2017, 9:34:35 PM4/16/17
to emscripten-discuss
I'm not sure where '__extern' comes from in wabt, might be worth opening an issue and asking. Can also just try to modify wabt locally to not require that specific string.

However, more generally, the dynamic linking output from emcc hasn't been tested with static linking much yet. There is a PR open for a wasm-merge tool that should do it,


so perhaps try that. But static linking in wasm is an area that is still in development, so a lot probably won't work.

To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Wink Saville

unread,
Apr 17, 2017, 2:08:25 AM4/17/17
to emscripten-discuss
Thanks for the heads up, I'll give wasm-merge a try.

I kinda got wasm-link to "work" (i.e. successfully "link")
I changed to using clang 5.0 (i.e. master branch) as talked about in Using WebAssembly in LLVM. And then
used `sed` to change "env" to "__extern" which resolved the "unsupported import module: env" error from
wasm-link.

I then ran into another wasm-link error: "unsupport export type: 2". This was resolved by
using --import-memory parameter to s2wasm. I've not tried actually instantiate the "linked"
file yet (I'm tired) but I won't be surprised if it fails as there is not memory being imported
in the resulting file.

Here is my little test for the curious. Anyway, we'll see how things go tomorrow and I'll
update this thread if anything "useful" happens.

Thanks again!

To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsub...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-discuss+unsub...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages