Skip to content

Commit 4ffa2ae

Browse files
committed
cmd/internal/obj/wasm: correct return PC for frameless wasmexport wrappers
For a wasmexport wrapper, we generate a call to the actual exported Go function, and use the wrapper function's PC 1 as the (fake) return address. This address is not used for returning, which is handled by the Wasm call stack. It is used for stack unwinding, and PC 1 makes it past the prologue and therefore has the right SP delta. But if the function has no arguments and results, the wrapper is frameless, with no prologue, and PC 1 doesn't exist. This causes the unwinder to fail. In this case, we put PC 0, which also has the correct SP delta (0). Fixes #69584. Change-Id: Ic047a6e62100db540b5099cc5a56a1d0f16d58b9 Reviewed-on: https://go-review.googlesource.com/c/go/+/624000 Reviewed-by: David Chase <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 26e1010 commit 4ffa2ae

File tree

3 files changed

+17
-5
lines changed

3 files changed

+17
-5
lines changed

lib/wasm/wasm_exec.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@
217217
}
218218

219219
const testCallExport = (a, b) => {
220+
this._inst.exports.testExport0();
220221
return this._inst.exports.testExport(a, b);
221222
}
222223

src/cmd/internal/obj/wasm/wasmobj.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,10 @@ func genWasmExportWrapper(s *obj.LSym, appendp func(p *obj.Prog, as obj.As, args
974974
Sym: s, // PC_F
975975
Offset: 1, // PC_B=1, past the prologue, so we have the right SP delta
976976
}
977+
if framesize == 0 {
978+
// Frameless function, no prologue.
979+
retAddr.Offset = 0
980+
}
977981
p = appendp(p, AI64Const, retAddr)
978982
p = appendp(p, AI64Store, constAddr(0))
979983
// Set PC_B parameter to function entry
@@ -1014,11 +1018,13 @@ func genWasmExportWrapper(s *obj.LSym, appendp func(p *obj.Prog, as obj.As, args
10141018
}
10151019

10161020
// Epilogue. Cannot use ARET as we don't follow Go calling convention.
1017-
// SP += framesize
1018-
p = appendp(p, AGet, regAddr(REG_SP))
1019-
p = appendp(p, AI32Const, constAddr(framesize))
1020-
p = appendp(p, AI32Add)
1021-
p = appendp(p, ASet, regAddr(REG_SP))
1021+
if framesize > 0 {
1022+
// SP += framesize
1023+
p = appendp(p, AGet, regAddr(REG_SP))
1024+
p = appendp(p, AI32Const, constAddr(framesize))
1025+
p = appendp(p, AI32Add)
1026+
p = appendp(p, ASet, regAddr(REG_SP))
1027+
}
10221028
p = appendp(p, AReturn)
10231029
}
10241030

src/syscall/js/js_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ func testExport(a int32, b int64) int64 {
7575
return <-ch + <-ch
7676
}
7777

78+
//go:wasmexport testExport0
79+
func testExport0() { // no arg or result (see issue 69584)
80+
runtime.GC()
81+
}
82+
7883
var testExportCalled bool
7984

8085
func growStack(n int64) {

0 commit comments

Comments
 (0)