Skip to content

Commit 125e91c

Browse files
Validation: Fix end instruction handling
1 parent 5283139 commit 125e91c

File tree

2 files changed

+18
-22
lines changed

2 files changed

+18
-22
lines changed

Sources/WasmKit/Translator.swift

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -989,7 +989,8 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
989989
private mutating func visitReturnLike() throws {
990990
preserveOnStack(depth: self.type.results.count)
991991
for (index, resultType) in self.type.results.enumerated().reversed() {
992-
let source = ensureOnVReg(try valueStack.pop(resultType))
992+
guard let operand = try popOperand(resultType) else { continue }
993+
let source = ensureOnVReg(operand)
993994
let dest = returnReg(index)
994995
emitCopyStack(from: source, to: dest)
995996
}
@@ -1170,9 +1171,7 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
11701171
}
11711172

11721173
mutating func visitEnd() throws -> Output {
1173-
guard let poppedFrame = controlStack.popFrame() else {
1174-
throw TranslationError("Unexpected `end` instruction")
1175-
}
1174+
let toBePopped = try controlStack.currentFrame()
11761175
// Reset the last emission to avoid relinking the result of the last instruction inside the block.
11771176
// Relinking results across the block boundary is invalid because the producer instruction is not
11781177
// statically known. Think about the following case:
@@ -1187,46 +1186,47 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
11871186
// ```
11881187
//
11891188
iseqBuilder.resetLastEmission()
1190-
if case .block(root: true) = poppedFrame.kind {
1191-
if poppedFrame.reachable {
1189+
if case .block(root: true) = toBePopped.kind {
1190+
if toBePopped.reachable {
11921191
try translateReturn()
11931192
// TODO: Merge logic with regular block frame
1194-
guard valueStack.height == poppedFrame.stackHeight else {
1193+
guard valueStack.height == toBePopped.stackHeight else {
11951194
throw ValidationError("values remaining on stack at end of block")
11961195
}
11971196
}
1198-
try iseqBuilder.pinLabelHere(poppedFrame.continuation)
1197+
try iseqBuilder.pinLabelHere(toBePopped.continuation)
11991198
return
12001199
}
12011200

1202-
if case .if(_, _, isElse: false) = poppedFrame.kind {
1201+
if case .if(_, _, isElse: false) = toBePopped.kind {
12031202
// `if` inst without `else` must have the same parameter and result types
1204-
let blockType = poppedFrame.blockType
1203+
let blockType = toBePopped.blockType
12051204
guard blockType.parameters == blockType.results else {
12061205
throw TranslationError("Expected the same parameter and result types for `if` block but got \(blockType)")
12071206
}
12081207
}
12091208

12101209
// NOTE: `valueStack.height - poppedFrame.stackHeight` is usually the same as `poppedFrame.copyCount`
12111210
// but it's not always the case when this block is already unreachable.
1212-
preserveOnStack(depth: Int(valueStack.height - poppedFrame.stackHeight))
1213-
switch poppedFrame.kind {
1211+
preserveOnStack(depth: Int(valueStack.height - toBePopped.stackHeight))
1212+
switch toBePopped.kind {
12141213
case .block:
1215-
try iseqBuilder.pinLabelHere(poppedFrame.continuation)
1214+
try iseqBuilder.pinLabelHere(toBePopped.continuation)
12161215
case .loop: break
12171216
case .if:
1218-
try iseqBuilder.pinLabelHere(poppedFrame.continuation)
1217+
try iseqBuilder.pinLabelHere(toBePopped.continuation)
12191218
}
1220-
for result in poppedFrame.blockType.results.reversed() {
1221-
guard try checkBeforePop(typeHint: result, controlFrame: poppedFrame) else { continue }
1219+
for result in toBePopped.blockType.results.reversed() {
1220+
guard try checkBeforePop(typeHint: result, controlFrame: toBePopped) else { continue }
12221221
_ = try valueStack.pop(result)
12231222
}
1224-
guard valueStack.height == poppedFrame.stackHeight else {
1223+
guard valueStack.height == toBePopped.stackHeight else {
12251224
throw ValidationError("values remaining on stack at end of block")
12261225
}
1227-
for result in poppedFrame.blockType.results {
1226+
for result in toBePopped.blockType.results {
12281227
_ = valueStack.push(result)
12291228
}
1229+
_ = controlStack.popFrame()
12301230
}
12311231

12321232
private static func computePopCount(
@@ -1411,7 +1411,6 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
14111411
}
14121412

14131413
mutating func visitReturn() throws -> Output {
1414-
guard try controlStack.currentFrame().reachable else { return }
14151414
try translateReturn()
14161415
try markUnreachable()
14171416
}

Tests/WasmKitTests/SpectestTests.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@ final class SpectestTests: XCTestCase {
2222
path: Self.testPaths,
2323
include: [],
2424
exclude: [
25-
"labels.wast",
26-
"load.wast",
27-
"local_get.wast",
2825
"loop.wast",
2926
"memory.wast",
3027
"memory_grow.wast",

0 commit comments

Comments
 (0)