以 WASM 文本格式实现一个结构

Implement a struct in WASM text format

WASM 文本格式有结构吗?

(module
   (type (; can a type be a `struct` like in C or rust? ;) )
   (; rest of module ;)
)

我使用 this WasmExplorer tool

将以下 c++ 编译为 wasm
struct MyStruct {
  int MyField;
  long MyOtherField;
};

MyStruct returnMyStruct(int myField){
  return MyStruct {
    MyField: myField,
    MyOtherField: myField * 2
  };
}

它输出以下内容,但我无法理解 WASM 在做什么。

(module
 (table 0 anyfunc)
 (memory [=12=] 1)
 (export "memory" (memory [=12=]))
 (export "_Z14returnMyStructi" (func $_Z14returnMyStructi))
 (func $_Z14returnMyStructi (; 0 ;) (param [=12=] i32) (param  i32)
  (i32.store
   (get_local [=12=])
   (get_local )
  )
  (i32.store offset=4
   (get_local [=12=])
   (i32.shl
    (get_local )
    (i32.const 1)
   )
  )
 )
)

生成的函数没有 return 类型,它使用 i32.storei32.shl 以及偏移量。它是否将结构存储在内存中的某个地方?

如能解释其工作原理和原因,我们将不胜感激。

Does WASM text format have structs?

没有。与其他低级汇编语言一样,wasm 只有少数整数数据类型,并将内存视为一大块字节。这是一种简化,但是当像 C 这样的高级语言被编译为汇编时,结构变量会在内存中分配一个位置,每个字段都位于不同的地址。当您写入字段时,它:

  1. 取结构变量的地址
  2. 添加字段相对于结构根的偏移量
  3. 写入结果地址

The function generated does not have a return type, it uses i32.store and i32.shl along with an offset. Is it storing the struct in memory somewhere?

您观察到的是一个 C++ 特性,Return Value Optmization (RVO)。自 C++11 以来,编译器是必需的,以避免从函数中获取 returned 的 PR 值结构(例如临时表达式)的额外副本。虽然标准没有规定 如何 做到这一点,但许多编译器通过将 return 值转换为输出参数来实现这一点,例如这个:

MyStruct myFunc(int);
MyStruct myStruct;
myStruct = myFunc(42);

转换为:

void myFunc(MyStruct&, int);
MyStruct myStruct;
myFunc(myStruct, 42);

现在再看看函数签名:

 (func $_Z14returnMyStructi (; 0 ;) (param [=12=] i32) (param  i32)

有两个参数:

  • [=15=]是一个MyStruct的地址,return值会写入
  • </code> 是 <code>myField.

所以这条指令:

  (i32.store
   (get_local [=13=])
   (get_local )
  )

myField 写入输出地址。在这种情况下,MyStructMyField 成员位于偏移量零处,并且正在写入。

这条指令:

  (i32.store offset=4
   (get_local [=14=])
   (i32.shl
    (get_local )
    (i32.const 1)
   )
  )

i32.shlmyField 左移 1 位,有效地乘以 2。结果写入输出地址后 4 个字节的地址。由于 MyOtherFieldMyStruct 的根开始布局 4 个字节,这是写入 MyOtherField.