【问题标题】:How to generate a Webassembly (WAT) with i64 instead of i32 from a C code如何从 C 代码中使用 i64 而不是 i32 生成 Webassembly (WAT)
【发布时间】:2018-10-29 20:25:17
【问题描述】:

我正在尝试使用 i64 生成一个 .wat 文件,但它只是编译为 i32。

在我使用int和int64_t测试的C代码中,我没有成功。

这是 C 代码:

#include <stdio.h>
#include <stdint.h>

#define MAX 64

int main(void) {
    int64_t v1[MAX], v2[MAX], v3[MAX];
    int64_t i;

    for(i = 0; i < MAX; i++)
       v3[i] = v1[i] + v2[i];

    for(i = 0; i < MAX; i++)
        printf("%llu\n", v3[i]);

    return 0;
}

然后我使用 CLI 编译成 .wasm 和 .wat 格式:

$ emcc -Oz ex1.c -s WASM=1 -s SIDE_MODULE=1 -s ONLY_MY_CODE=1 -o ex1.wasm
$ wasm2wat ex1.wasm -o ex1.wat

这是编译后的 .wat 文件:

(module
(type (;0;) (func (result i32)))
(type (;1;) (func (param i32 i32 i32 i32) (result i32)))
(type (;2;) (func (param i32 i32) (result i32)))
(type (;3;) (func))
(import "env" "getTempRet0" (func (;0;) (type 0)))
(import "env" "_i64Add" (func (;1;) (type 1)))
(import "env" "_printf" (func (;2;) (type 2)))
(import "env" "memoryBase" (global (;0;) i32))
(import "env" "memory" (memory (;0;) 256))
(func (;3;) (type 0) (result i32)
    (local i32 i32 i32 i32 i32 i32 i32 i32 i32)
    get_global 1
    set_local 2
    get_global 1
    i32.const 1552
    i32.add
    set_global 1
    get_local 2
    i32.const 1536
    i32.add
    set_local 5
    get_local 2
    i32.const 1024
    i32.add
    set_local 7
    get_local 2
    i32.const 512
    i32.add
    set_local 8
    loop  ;; label = @1
    get_local 4
    i32.const 0
    i32.lt_u
    get_local 4
    i32.eqz
    get_local 0
    i32.const 64
    i32.lt_u
    i32.and
    i32.or
    if  ;; label = @2
    get_local 8
    get_local 0
    i32.const 3
    i32.shl
    i32.add
    tee_local 1
    i32.load
    get_local 1
    i32.load offset=4
    get_local 7
    get_local 0
    i32.const 3
    i32.shl
    i32.add
    tee_local 1
    i32.load
    get_local 1
    i32.load offset=4
    call 1
    set_local 3
    call 0
    set_local 6
    get_local 2
    get_local 0
    i32.const 3
    i32.shl
    i32.add
    tee_local 1
    get_local 3
    i32.store
    get_local 1
    get_local 6
    i32.store offset=4
    get_local 0
    get_local 4
    i32.const 1
    i32.const 0
    call 1
    set_local 0
    call 0
    set_local 4
    br 1 (;@1;)
    end
    end
    i32.const 0
    set_local 3
    i32.const 0
    set_local 0
    loop  ;; label = @1
    get_local 3
    i32.const 0
    i32.lt_u
    get_local 3
    i32.eqz
    get_local 0
    i32.const 64
    i32.lt_u
    i32.and
    i32.or
    if  ;; label = @2
    get_local 2
    get_local 0
    i32.const 3
    i32.shl
    i32.add
    tee_local 6
    i32.load offset=4
    set_local 1
    get_local 5
    get_local 6
    i32.load
    i32.store
    get_local 5
    get_local 1
    i32.store offset=4
    get_global 0
    get_local 5
    call 2
    drop
    get_local 0
    get_local 3
    i32.const 1
    i32.const 0
    call 1
    set_local 0
    call 0
    set_local 3
    br 1 (;@1;)
    end
    end
    get_local 2
    set_global 1
    i32.const 0)
    (func (;4;) (type 3)
          get_global 0
          i32.const 16
          i32.add
          set_global 1
          get_global 1
          i32.const 5242880
          i32.add
          set_global 2)
    (global (;1;) (mut i32) (i32.const 0))
(global (;2;) (mut i32) (i32.const 0))
(export "__post_instantiate" (func 4))
(export "_main" (func 3))
(data (get_global 0) "%llu\0a"))

我正在研究 mbebenita WebAssembly Explorer 代码,但我有点困惑,但我知道它会生成 i64 和 x86 程序集。

我知道我可以使用 WebAssembly Explorer 来生成我的 .wat 文件和 x86 程序集,但就我而言,我需要使用 CLI 进行编译。

【问题讨论】:

  • 当您说“i64 和 x86 程序集。”时,您希望是指 x86-64。这不一定与使用 32 位类型的 WASM 相关;希望智能编译器可以将 WASM 中的 i32 add + add-with-carry 优化为 x86-64 asm 中的单个 64 位 add。
  • WASM 确实允许使用 i64 类型:mbebenita.github.io/WasmExplorer/…
  • 我不知道我是否正确,但当我的意思是 i64(在 .wast 内)时,WasmExplorer 上的代码显示:(模块(表 0 anyfunc)(内存 $0 1)(导出"memory" (memory $0)) (export "_Z3addx" (func $_Z3addx)) (func $_Z3addx (; 0 ;) (param $0 i64) (result i64) (i64.shl (get_local $0) (i64.const 1 ) ) ) )
  • WasmExplorer 已经有一个窗格,可以直接显示 C++ -> x86-64 asm 的 clang/LLVM 输出。如您所见,即使对于那个琐碎的return x+x 函数,它也比“Firefox x86-64”更有效,使用一个lea rax, [rdi + rdi] 而不是围绕add 的多个无用的mov 指令。但是还有一个更好的 C/C++ 到 x86 32 位、x86-64、ARM、PowerPC 或任何 asm 的站点:Matt Godbolt 的编译器资源管理器站点:godbolt.org 请参阅 How to remove "noise" from GCC/clang assembly output?
  • " -s LEGALIZE_JS_FFI=0" 对我有用。但是 '-s ONLY_MY_CODE=1' 会导致该选项出错。

标签: firefox x86-64 emscripten webassembly


【解决方案1】:

当您默认使用 SIDE_MODULE=1 构建时,emscripten 将默认构建与 asmjs 兼容的模块,这意味着它不会假定原生 64 位支持。

似乎有计划解决此限制: https://github.com/kripken/emscripten/blob/fd38f3bbf1fdc2f48078f641eb57b1c6fa2a538f/tools/shared.py#L2316 https://github.com/kripken/emscripten/blob/fd38f3bbf1fdc2f48078f641eb57b1c6fa2a538f/emscripten.py#L485

看起来如果你想要原生 i64 支持你今天不能使用 SIDE_MODULE。

【讨论】:

    猜你喜欢
    • 2018-12-16
    • 1970-01-01
    • 2019-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多