6

没有使用indirect_callavailable online 的示例。基于语义文档,我尝试了

(call_indirect 
    (i32.const 0)
    (i32.const 0)
    )

数字是随机的,而不是像我预期的那样给出运行时错误。我收到解析错误。

什么是正确的语法call_indirect

4

2 回答 2

5

的正确语法call_indirect似乎是

(call_indirect $fsig
   (i32.const 0)
)

$fsig部分中定义的预期函数签名在哪里type,参数是函数的地址(或者更确切地说是它在 中的索引table)。

以下面调用函数指针的 C 代码示例为例:

typedef void(*fp)();

void dispatch(fp x) {
  x();
}

编译

(module
  (type $FUNCSIG$v (func))
  (table 0 anyfunc)
  (memory $0 1)
  (export "memory" (memory $0))
  (export "dispatch" (func $dispatch))
  (func $dispatch (param $0 i32)
    (call_indirect $FUNCSIG$v
      (get_local $0)
    )
  )
)

这是一个更完整的示例,我们实际上调用了一个test返回值的函数:

(module
  (type $FUNCSIG$i (func (result i32)))
  (table 1 anyfunc)
  (elem (i32.const 0) $test)
  (memory $0 1)

  (func $test (type $FUNCSIG$i) (result i32)
    (i32.const 42)
  )

  (func $main (result i32)
    (call_indirect $FUNCSIG$i
      (i32.const 0)
    )
  )

)
于 2017-08-16T13:30:44.860 回答
0

文档摘录:

表基本上是可调整大小的引用数组,可以通过 WebAssembly 代码中的索引进行访问。要了解为什么需要表,我们首先需要观察 call 指令采用静态函数索引,因此只能调用一个函数——但是如果被调用者是运行时值怎么办?

  • 在 JavaScript 中我们经常看到:函数是一等值。
  • 在 C/C++ 中,我们通过函数指针看到了这一点。
  • 在 C++ 中,我们通过虚函数看到了这一点。

WebAssembly 需要一种调用指令来实现这一点,所以我们给了它 call_indirect,它接受一个动态函数操作数。问题是我们必须在 WebAssembly 中提供操作数的唯一类型是(当前)i32/i64/f32/f64。

WebAssembly 可以添加一个 anyfunc 类型(“any”,因为该类型可以保存任何签名的函数),但不幸的是,出于安全原因,这个 anyfunc 类型不能存储在线性内存中。线性内存将存储值的原始内容公开为字节,这将允许 wasm 内容任意观察和破坏原始函数地址,这在 Web 上是不允许的。

解决方案是将函数引用存储在表中,并改为传递表索引,它们只是 i32 值。call_indirect 的操作数因此可以是 i32 索引值。

因此,总而言之,call_indirect需要签名进行验证,并将i32值作为指向相应表中所需函数的参数。与其他 WASM 指令一样,参数可以从堆栈中弹出,也可以从嵌套指令中检索。因此我们可以有:

call_indirect (type 123)      ;; Type as an index in the table,
                              ;; argument on the stack from previous instructions.

或者

call_indirect $funcSignature  ;; The same, but using a type name instead of index.

或者

(call_indirect $funcSignature ;; The argument is provided by the nested instructions.
      (get_local $0)
)

请参阅:https ://developer.mozilla.org/en-US/docs/WebAssembly/Understanding_the_text_format#webassembly_tables

于 2022-01-01T03:07:16.970 回答