WebAssembly のテキスト表現 WAT を WASM に変換するには

blog1.mammb.com


WebAssembly のテキスト表現 WAT とは

WebAssembly には、バイナリー形式の WASM の他に、人間が読んだり編集したりできるテキスト表現である WAT が定義されています。

テキスト形式ではモジュールは 1 つの大きな S 式として表現されます。

例えば、2つの整数を引数に、その合計を返却する add 関数は以下のように定義できます。

(module
  (func $add (param $lhs i32) (param $rhs i32) (result i32)
    local.get $lhs
    local.get $rhs
    i32.add)
  (export "add" (func $add))
)

上記を add.wat として保存し、wasmtime で以下のように実行することができます。

$ wasmtime add.wat --invoke add 1 2
3

--invoke での実行は以下のワーニングになりますが、ここでは気にしません。

warning: using `--invoke` with a function that takes arguments is experimental and may break in the future


テキスト表現 WAT を WASM に変換する

WABT(The WebAssembly Binary Toolkit) を使うことで、変換できます。

以下で公開されているため、リリースページからバイナリをダウンロードします。

https://github.com/webassembly/wabt

ダウンロードしたファイルを解凍すると、bin ディレクトリに各種ツールが入っています。

wat2wasm によりテキスト表現 WAT を WASM に変換できます。

$ wabt/bin/wat2wasm add.wat -o add.wasm

add.wasm が作成され、wasmtime で実行することができます。

$ wasmtime add.wasm --invoke add 1 2
3


wat2wasm を -v オプションで実行すれば、バイナリ変換内容を理解しやすい形で出力することができます。

$ wabt/bin/wat2wasm add.wat -v

0000000: 0061 736d                                 ; WASM_BINARY_MAGIC
0000004: 0100 0000                                 ; WASM_BINARY_VERSION
; section "Type" (1)
0000008: 01                                        ; section code
0000009: 00                                        ; section size (guess)
000000a: 01                                        ; num types
; func type 0
000000b: 60                                        ; func
000000c: 02                                        ; num params
000000d: 7f                                        ; i32
000000e: 7f                                        ; i32
000000f: 01                                        ; num results
0000010: 7f                                        ; i32
...


WASM をテキスト表現 WAT に変換する

wasm2wat を使うと、WASM をテキスト表現 WAT に変換することもできます。

$ wabt/bin/wasm2wat add.wasm -o add.wat

add.wat は以下のように変換されます。

(module
  (type (;0;) (func (param i32 i32) (result i32)))
  (func (;0;) (type 0) (param i32 i32) (result i32)
    local.get 0
    local.get 1
    i32.add)
  (export "add" (func 0)))

※先の例では $lhs などと名前を付けて定義していましたが、こちらでは単なる数値での参照に戻ります。


WABT のその他のツール

WABTには上記の他、次のようなツールが含まれています。

  • wasm-objdump: WASM バイナリに関する情報を表示
  • wasm-interp: WebAssembly バイナリファイルのインタプリタ
  • wasm-decompile: WASM バイナリを可読な C-like シンタックスにデコンパイルする
  • wat-desugar: WATテキスト形式(S式、flat syntax) をパースしてフラットな形式に簡素化する
  • wasm2c: WebAssembly のバイナリファイルを C のソースとヘッダに変換する
  • wasm-strip: WebAssembly のバイナリファイルのセクションを削除する
  • wasm-validate: WebAssembly のバイナリ形式でファイルを検証する
  • wast2json: wasm spec test フォーマットのファイルを JSON ファイルと関連する wasm バイナリファイルに変換する
  • wasm-opcodecnt: 命令のオペコード使用量を数える
  • spectest-interp: Spectest JSONファイルを読み、そのテストをインタープリタで実行する