Skip to content

Commit f71063a

Browse files
Translator: Fix a miscompilation bug in the return instruction
1 parent 2e9acfc commit f71063a

File tree

1 file changed

+22
-8
lines changed

1 file changed

+22
-8
lines changed

Sources/WasmKit/Translator.swift

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ fileprivate struct MetaProgramCounter {
169169
/// ```
170170
/// | Offset | Description |
171171
/// |------------------------------------|----------------------|
172-
/// | 0 ~ max(params, results)-1 | Frame header |
172+
/// | SP-3 ~ SP-(max(params, results)+3) | Frame header |
173173
/// | SP-3 | * Saved Instance |
174174
/// | SP-2 | * Saved PC |
175175
/// | SP-1 | * Saved SP |
@@ -190,19 +190,19 @@ fileprivate struct MetaProgramCounter {
190190

191191
struct FrameHeaderLayout {
192192
let type: FunctionType
193-
let paramResultBase: VReg
193+
let size: VReg
194194

195195
init(type: FunctionType) {
196196
self.type = type
197-
self.paramResultBase = Self.size(of: type)
197+
self.size = Self.size(of: type)
198198
}
199199

200200
func paramReg(_ index: Int) -> VReg {
201-
VReg(index) - paramResultBase
201+
VReg(index) - size
202202
}
203203

204204
func returnReg(_ index: Int) -> VReg {
205-
return VReg(index) - paramResultBase
205+
return VReg(index) - size
206206
}
207207

208208
internal static func size(of: FunctionType) -> VReg {
@@ -236,13 +236,17 @@ struct StackLayout {
236236
}
237237

238238
func localReg(_ index: LocalIndex) -> VReg {
239-
if index < frameHeader.type.parameters.count {
239+
if isParameter(index) {
240240
return frameHeader.paramReg(Int(index))
241241
} else {
242242
return VReg(index) - VReg(frameHeader.type.parameters.count)
243243
}
244244
}
245245

246+
func isParameter(_ index: LocalIndex) -> Bool {
247+
index < frameHeader.type.parameters.count
248+
}
249+
246250
func constReg(_ index: Int) -> VReg {
247251
return VReg(numberOfLocals + index)
248252
}
@@ -990,11 +994,21 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
990994
}
991995

992996
private mutating func visitReturnLike() throws {
993-
preserveOnStack(depth: self.type.results.count)
997+
var copies: [(source: VReg, dest: VReg)] = []
994998
for (index, resultType) in self.type.results.enumerated().reversed() {
995999
guard let operand = try popOperand(resultType) else { continue }
996-
let source = ensureOnVReg(operand)
1000+
var source = ensureOnVReg(operand)
1001+
if case .local(let localIndex) = operand, stackLayout.isParameter(localIndex) {
1002+
// Parameter space is shared with return values, so we need to copy it to the stack
1003+
// before copying to the return slot to avoid overwriting the parameter value.
1004+
let copyTo = valueStack.stackRegBase + VReg(valueStack.height)
1005+
emitCopyStack(from: localReg(localIndex), to: copyTo)
1006+
source = copyTo
1007+
}
9971008
let dest = returnReg(index)
1009+
copies.append((source, dest))
1010+
}
1011+
for (source, dest) in copies {
9981012
emitCopyStack(from: source, to: dest)
9991013
}
10001014
}

0 commit comments

Comments
 (0)