【问题标题】:Implement a struct in WASM text format以 WASM 文本格式实现结构
【发布时间】:2022-01-22 09:13:16
【问题描述】:

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 $0 1)
 (export "memory" (memory $0))
 (export "_Z14returnMyStructi" (func $_Z14returnMyStructi))
 (func $_Z14returnMyStructi (; 0 ;) (param $0 i32) (param $1 i32)
  (i32.store
   (get_local $0)
   (get_local $1)
  )
  (i32.store offset=4
   (get_local $0)
   (i32.shl
    (get_local $1)
    (i32.const 1)
   )
  )
 )
)

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

非常感谢您解释它的工作原理和原因。

【问题讨论】:

  • 你处理过组装吗?我的 2 美分是你不应该太在意输出的 WASM。它被设计为永远不会直接编写。
  • 我想写一个直接写 WASM 的编译器,用于教育目的。因此,我只关心 WASM,而不关心 C++

标签: c++ webassembly


【解决方案1】:

WASM 文本格式有结构吗?

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

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

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

您观察到的是 C++ 功能Return Value Optmization (RVO)。从 C++11 开始需要编译器来避免从函数返回的 PR 值结构(例如临时表达式)的额外副本。虽然标准没有规定 如何 这样做,但许多编译器通过将返回值转换为输出参数来实现这一点,例如这个:

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

转换成这个:

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

现在再看看函数签名:

 (func $_Z14returnMyStructi (; 0 ;) (param $0 i32) (param $1 i32)

有两个参数:

  • $0是一个MyStruct的地址,返回值会写在这里
  • $1myField

所以这条指令:

  (i32.store
   (get_local $0)
   (get_local $1)
  )

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

还有这条指令:

  (i32.store offset=4
   (get_local $0)
   (i32.shl
    (get_local $1)
    (i32.const 1)
   )
  )

i32.shlmyField 左移 1 位,有效地将其乘以 2。结果被写入输出地址后 4 个字节的地址。由于MyOtherField 距离MyStruct 的根有4 个字节,因此这是写入MyOtherField

【讨论】:

    猜你喜欢
    • 2013-08-08
    • 1970-01-01
    • 2015-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-05
    相关资源
    最近更新 更多