2

不幸的是,我无法获得一个工作工具链来将 C/C++ 编译为 wasm 文件,但我希望一个善良的灵魂可以帮助我。给定程序片段:

struct foo {
    int a;
    float b;
};

void function(foo * p);

void my_program() {
    struct foo my_foo;
    my_foo.a = 1;
    my_foo.b = -3.0F;
    foo(&my_foo);
}

wasm 代码是my_program什么样的?

4

1 回答 1

4

我将假设您的意思是浪费的文本格式是什么样的?

我在您的代码中调整了几件事,以便它可以编译:

struct foo {
    int a;
    float b;
};

extern void bar(struct foo * p);

void my_program() {
    struct foo my_foo;
    my_foo.a = 1;
    my_foo.b = -3.0F;
    bar(&my_foo);
} 

使用 emscripten/binaryen 编译它,然后使用 wasm2wast:

emcc -s WASM=1 -s SIDE_MODULE=1 -O2 str.c -o str.js
wasm-dis str.wasm -o str.wast

请注意,如果没有-s SIDE_MODULE=1 -O2,emscripten 会引入一堆标准库(malloc 等),并且 wast 文件有 10,000 行长。我假设您可能只想要相当简单的 wasm/wast 结果,而不需要所有的链接/包含。

这会产生以下废品文件:

(module
 (type $0 (func (param i32)))
 (type $1 (func))
 (import "env" "memoryBase" (global $import$0 i32))
 (import "env" "_bar" (func $import$1 (param i32)))
 (import "env" "memory" (memory $0 256))
 (import "env" "table" (table 0 anyfunc))
 (import "env" "tableBase" (global $import$4 i32))
 (global $global$0 (mut i32) (i32.const 0))
 (global $global$1 (mut i32) (i32.const 0))
 (export "_my_program" (func $0))
 (export "__post_instantiate" (func $2))
 (export "runPostSets" (func $1))
 (func $0 (type $1)
  (local $var$0 i32)
  (local $var$1 i32)
  (block $label$0
   (set_local $var$0
    (get_global $global$0)
   )
   (set_global $global$0
    (i32.add
     (get_global $global$0)
     (i32.const 16)
    )
   )
   (i32.store
    (tee_local $var$1
     (get_local $var$0)
    )
    (i32.const 1)
   )
   (f32.store offset=4
    (get_local $var$1)
    (f32.const -3)
   )
   (call $import$1
    (get_local $var$1)
   )
   (set_global $global$0
    (get_local $var$0)
   )
  )
 )
 (func $1 (type $1)
  (nop)
 )
 (func $2 (type $1)
  (block $label$0
   (set_global $global$0
    (get_global $import$0)
   )
   (set_global $global$1
    (i32.add
     (get_global $global$0)
     (i32.const 5242880)
    )
   )
   (call $1)
  )
 )
 ;; custom section "dylink", size 5
)

请注意,memoryBasetableBase__post_instantiaterunPostSets是用于平台内存集成/初始化的 emscripten 添加。memoryBase基本上是 C 堆栈的开始,值被复制__post_instantiate$global$0(对于此模块中的所有函数都是全局的)。当my_program被调用时,发生的第一件事是我们将堆栈指针调整 16 以指向编译器在堆栈上为 my_foo 结构“分配”空间的位置。我们现在做一些i32.store操作offset=X来更新foo. 当函数返回时,我们将堆栈指针($global$0)恢复到我们进入函数时的位置。

于 2017-04-26T20:57:33.163 回答