我使用clang --target=wasm32-unknown-wasi ...
将Hello World C程序编译成WebAssembly。一切正常,.wasm
文件可以像wasmer一样在运行时正常运行。
但是当我检查.wasm
文件(在.wat
格式)时,我发现一些i64指令,如:
(func $__lseek (type $t1) (param $p0 i32) (param $p1 i64) (param $p2 i32) (result i64)
(local $l3 i32)
global.get $g0
i32.const 16
i32.sub
local.tee $l3
global.set $g0
block $B0
block $B1
local.get $p0
local.get $p1
local.get $p2
i32.const 255
i32.and
local.get $l3
i32.const 8
i32.add
call $__wasi_fd_seek
local.tee $p0
i32.eqz
br_if $B1
i32.const 0
i32.const 70
local.get $p0
local.get $p0
i32.const 76
i32.eq
select
i32.store offset=3696
i64.const -1
local.set $p1
br $B0
end
local.get $l3
i64.load offset=8
local.set $p1
end
local.get $l3
i32.const 16
i32.add
global.set $g0
local.get $p1)
看起来很奇怪:为什么clang会发出i64指令,而目标是wasm32?
根据https://github.com/WebAssembly/wasi-libc/issues/158中的讨论,我认为这可能是因为在链接期间引入了一些包含i64指令的wasi api。我说的对吗?
感谢您的关注!
我觉得这没什么不对。瞄准32位意味着内存寻址是32位的。由于这个原因,在内存存储指令之前,你所有的都是32位指令(即偏移量和值都是i32),你在某个点有这个:
i32.store offset=3696
这是隐式内存索引0(目前唯一可用的索引)中的存储。存储的值是32位整型,偏移量为i32(在此之前计算+ 3696)。在这个例子中,你所关心的是i32,而是。首先计算偏移量,然后价值。
WebAssembly的MVP支持64位整数"开箱即用"。这意味着您可以自由地使用这些值,以及f32和f64。然而,这是你的程序值,MVP只支持i32内存寻址。就在最近,BitInt
成为WebAssembly中与i64
匹配的JS类型,而memory64
后mvp正准备进入生产系统。
详细内容如下:
(; push 0 (i32 type) ;)
i32.const 0
(; stack depth from here = 1 ;)
(; push 70 (i32 type) ;)
i32.const 70
(; stack depth from here = 2 ;)
(; push the first parameter two times (that is of i32 type) ;)
local.get $p0
local.get $p0
(; stack depth from here = 4 ;)
(; push 76 (i32 type))
i32.const 76
(; stack depth from here = 5 ;)
(; check is 76 equal to $p0, pop 2, push 1 all i32 types ;)
i32.eq
(; stack depth from here = 4 ;)
(; [t t i32] -> [t], i.e. pop 3, push 1, all i32 types ;)
select
(; stack depth from here = 2 ;)
(; [offset i32, value i32] -> [], pop 2, push zero ;)
i32.store offset=3696
(; stack depth 0 ;)
直接offset=3696
是一个偏移量,它将被添加到从堆栈中计算的偏移量中,以接收effective address
,该值将被精确地写入。