指向本地结构的指针如何被翻译成 webassembly?

How do pointer to local structures get translated to webassembly?

不幸的是,我无法获得一个有效的工具链来将 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);
}

my_program 的 wasm 代码是什么样的?

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

我在你的代码中做了一些调整,以便它可以编译:

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 等),而垃圾文件有 10,000 行长。我假设您可能只想要相当简单的 wasm/wast 结果,而不需要所有 linkages/inclusions.

这导致以下垃圾文件:

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

请注意,memoryBasetableBase__post_instantiaterunPostSets 是平台内存的 emscripten 添加 integration/initialization。 memoryBase 基本上是 C 堆栈的开始,值由 __post_instantiate 复制到 $global[=20=](对于该模块中的所有函数都是全局的)。当调用 my_program 时,首先发生的事情是我们将堆栈指针调整 16 以指向编译器在堆栈上为 my_foo 结构设置 "allocated" space 的位置。我们现在使用 offset=X 执行几个 i32.store 操作来更新 foo 中的字段。当函数 returns 我们将堆栈指针 ($global[=20=]) 恢复到我们进入函数时的位置。