Skip to content

Commit 6f28ac1

Browse files
WAT: Fix for assert_malformed test cases in call_indirect.wast
1 parent 4b1170c commit 6f28ac1

File tree

4 files changed

+29
-33
lines changed

4 files changed

+29
-33
lines changed

Sources/WAT/Encoder.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,17 @@ struct Encoder {
9595
output.append(contentsOf: exprEncoder.encoder.output)
9696
lexer = parser.parser.lexer
9797
}
98+
99+
mutating func writeInstruction(lexer: inout Lexer, wat: inout Wat) throws {
100+
var parser = ExpressionParser<ExpressionEncoder>(lexer: lexer, features: wat.features)
101+
var exprEncoder = ExpressionEncoder()
102+
guard try parser.instruction(visitor: &exprEncoder, wat: &wat) else {
103+
throw WatParserError("unexpected end of instruction", location: lexer.location())
104+
}
105+
try exprEncoder.visitEnd()
106+
output.append(contentsOf: exprEncoder.encoder.output)
107+
lexer = parser.parser.lexer
108+
}
98109
}
99110

100111
protocol WasmEncodable {
@@ -235,8 +246,10 @@ extension WAT.WatParser.ElementDecl {
235246
}
236247
if case let .active(_, offset) = self.mode {
237248
switch offset {
238-
case .source(var lexer):
249+
case .expression(var lexer):
239250
try encoder.writeExpression(lexer: &lexer, wat: &wat)
251+
case .singleInstruction(var lexer):
252+
try encoder.writeInstruction(lexer: &lexer, wat: &wat)
240253
case .synthesized(let offset):
241254
var exprEncoder = ExpressionEncoder()
242255
if isMemory64(tableIndex: Int(tableIndex ?? 0)) {

Sources/WAT/Parser/ExpressionParser.swift

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -91,17 +91,10 @@ struct ExpressionParser<Visitor: InstructionVisitor> {
9191
}
9292
}
9393

94-
@discardableResult
95-
mutating func parse(visitor: inout Visitor, wat: inout Wat) throws -> Int {
96-
var numberOfInstructions = 0
97-
while true {
98-
guard try instruction(visitor: &visitor, wat: &wat) else {
99-
numberOfInstructions += 1
100-
break
101-
}
94+
mutating func parse(visitor: inout Visitor, wat: inout Wat) throws {
95+
while try instruction(visitor: &visitor, wat: &wat) {
10296
// Parse more instructions
10397
}
104-
return numberOfInstructions
10598
}
10699

107100
mutating func parseElemExprList(visitor: inout Visitor, wat: inout Wat) throws {
@@ -170,7 +163,7 @@ struct ExpressionParser<Visitor: InstructionVisitor> {
170163

171164
/// Parse "(instr)" or "instr" and visit the instruction.
172165
/// - Returns: `true` if an instruction was parsed. Otherwise, `false`.
173-
private mutating func instruction(visitor: inout Visitor, wat: inout Wat) throws -> Bool {
166+
mutating func instruction(visitor: inout Visitor, wat: inout Wat) throws -> Bool {
174167
if try nonFoldedInstruction(visitor: &visitor, wat: &wat) {
175168
return true
176169
}
@@ -206,9 +199,7 @@ struct ExpressionParser<Visitor: InstructionVisitor> {
206199
}
207200
try parser.expect(.leftParen)
208201
let keyword = try parser.expectKeyword()
209-
guard let visit = try parseTextInstruction(keyword: keyword, wat: &wat) else {
210-
return false
211-
}
202+
let visit = try parseTextInstruction(keyword: keyword, wat: &wat)
212203
let suspense: Suspense
213204
switch keyword {
214205
case "if":
@@ -265,7 +256,7 @@ struct ExpressionParser<Visitor: InstructionVisitor> {
265256
}
266257

267258
/// Parse a single instruction without consuming the surrounding parentheses and instruction keyword.
268-
private mutating func parseTextInstruction(keyword: String, wat: inout Wat) throws -> ((inout Visitor) throws -> Visitor.Output)? {
259+
private mutating func parseTextInstruction(keyword: String, wat: inout Wat) throws -> ((inout Visitor) throws -> Visitor.Output) {
269260
switch keyword {
270261
case "select":
271262
// Special handling for "select", which have two variants 1. with type, 2. without type
@@ -293,7 +284,10 @@ struct ExpressionParser<Visitor: InstructionVisitor> {
293284
}
294285
default:
295286
// Other instructions are parsed by auto-generated code.
296-
return try WAT.parseTextInstruction(keyword: keyword, expressionParser: &self, wat: &wat)
287+
guard let visit = try WAT.parseTextInstruction(keyword: keyword, expressionParser: &self, wat: &wat) else {
288+
throw WatParserError("unknown instruction \(keyword)", location: parser.lexer.location())
289+
}
290+
return visit
297291
}
298292
}
299293

@@ -302,12 +296,8 @@ struct ExpressionParser<Visitor: InstructionVisitor> {
302296
guard let keyword = try parser.peekKeyword() else {
303297
return false
304298
}
305-
let originalParser = parser
306299
try parser.consume()
307-
guard let visit = try parseTextInstruction(keyword: keyword, wat: &wat) else {
308-
parser = originalParser
309-
return false
310-
}
300+
let visit = try parseTextInstruction(keyword: keyword, wat: &wat)
311301
_ = try visit(&visitor)
312302
return true
313303
}
@@ -455,7 +445,7 @@ extension ExpressionParser {
455445
} else {
456446
tableIndex = 0
457447
}
458-
let typeUse = try withWatParser { try $0.typeUse(mayHaveName: true) }
448+
let typeUse = try withWatParser { try $0.typeUse(mayHaveName: false) }
459449
let (_, typeIndex) = try wat.types.resolve(use: typeUse)
460450
return (UInt32(typeIndex), tableIndex)
461451
}

Sources/WAT/Parser/WatParser.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,8 @@ struct WatParser {
106106

107107
struct ElementDecl: NamedModuleFieldDecl {
108108
enum Offset {
109-
case source(Lexer)
109+
case expression(Lexer)
110+
case singleInstruction(Lexer)
110111
case synthesized(Int)
111112
}
112113
enum Mode {
@@ -350,12 +351,12 @@ struct WatParser {
350351
} else {
351352
table = try tableUse()
352353
if try parser.takeParenBlockStart("offset") {
353-
mode = .active(table: table, offset: .source(parser.lexer))
354+
mode = .active(table: table, offset: .expression(parser.lexer))
354355
try parser.skipParenBlock()
355356
} else {
356357
if try parser.peek(.leftParen) != nil {
357358
// abbreviated offset instruction
358-
mode = .active(table: table, offset: .source(parser.lexer))
359+
mode = .active(table: table, offset: .singleInstruction(parser.lexer))
359360
try parser.consume() // consume (
360361
try parser.skipParenBlock() // skip offset expr
361362
} else {

Tests/WATTests/EncoderTests.swift

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -107,19 +107,11 @@ class EncoderTests: XCTestCase {
107107

108108
var stats = CompatibilityTestStats()
109109
let excluded: [String] = [
110-
"call_indirect.wast",
111110
"const.wast",
112111
"float_literals.wast",
113-
"func.wast",
114-
"if.wast",
115112
"imports.wast",
116113
"int_literals.wast",
117-
"load.wast",
118-
"load64.wast",
119-
"loop.wast",
120-
"obsolete-keywords.wast",
121114
"start.wast",
122-
"store.wast",
123115
"token.wast",
124116
"utf8-invalid-encoding.wast"
125117
]

0 commit comments

Comments
 (0)