Skip to content

Commit 02fafbe

Browse files
WasmParser: Add ExpressionParser API
1 parent 75e89fa commit 02fafbe

File tree

3 files changed

+58
-7
lines changed

3 files changed

+58
-7
lines changed

Sources/WasmKit/Translator.swift

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -344,22 +344,22 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
344344

345345
private mutating func setReachability(_ value: Bool) throws {
346346
guard !self.frames.isEmpty else {
347-
throw TranslationError("Control stack is empty. Instruction cannot be appeared after \"end\" of function")
347+
throw ValidationError("Control stack is empty. Instruction cannot be appeared after \"end\" of function")
348348
}
349349
self.frames[self.frames.count - 1].reachable = value
350350
}
351351

352352
func currentFrame() throws -> ControlFrame {
353353
guard let frame = self.frames.last else {
354-
throw TranslationError("Control stack is empty. Instruction cannot be appeared after \"end\" of function")
354+
throw ValidationError("Control stack is empty. Instruction cannot be appeared after \"end\" of function")
355355
}
356356
return frame
357357
}
358358

359359
func branchTarget(relativeDepth: UInt32) throws -> ControlFrame {
360360
let index = frames.count - 1 - Int(relativeDepth)
361361
guard frames.indices.contains(index) else {
362-
throw TranslationError("Relative depth \(relativeDepth) is out of range")
362+
throw ValidationError("Relative depth \(relativeDepth) is out of range")
363363
}
364364
return frames[index]
365365
}
@@ -1062,7 +1062,16 @@ struct InstructionTranslator<Context: TranslatorContext>: InstructionVisitor {
10621062
// Emit `onEnter` instruction at the beginning of the function
10631063
emit(.onEnter(functionIndex))
10641064
}
1065-
try code.parseExpression(visitor: &self)
1065+
var parser = ExpressionParser(code: code)
1066+
var offset = parser.offset
1067+
do {
1068+
while try parser.visit(visitor: &self) {
1069+
offset = parser.offset
1070+
}
1071+
} catch var error as ValidationError {
1072+
error.offset = offset
1073+
throw error
1074+
}
10661075
return try finalize()
10671076
}
10681077

Sources/WasmKit/Validator.swift

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
import WasmParser
22

33
struct ValidationError: Error, CustomStringConvertible {
4-
let description: String
4+
let message: String
5+
var offset: Int?
56

6-
init(_ description: String) {
7-
self.description = description
7+
var description: String {
8+
if let offset = offset {
9+
return "\(message) at offset 0x\(String(offset, radix: 16))"
10+
} else {
11+
return message
12+
}
13+
}
14+
15+
init(_ message: String) {
16+
self.message = message
817
}
918
}
1019

Sources/WasmParser/WasmParser.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,39 @@ extension Code {
126126
}
127127
}
128128

129+
// TODO: Move `doParseInstruction` under `ExpressionParser` struct
130+
@_documentation(visibility: internal)
131+
public struct ExpressionParser {
132+
@usableFromInline
133+
let parser: Parser<StaticByteStream>
134+
@usableFromInline
135+
var lastCode: InstructionCode?
136+
137+
public var offset: Int {
138+
self.parser.currentIndex
139+
}
140+
141+
public init(code: Code) {
142+
self.parser = Parser(
143+
stream: StaticByteStream(bytes: code.expression),
144+
features: code.features,
145+
hasDataCount: code.hasDataCount
146+
)
147+
}
148+
149+
@inlinable
150+
public mutating func visit<V: InstructionVisitor>(visitor: inout V) throws -> Bool {
151+
lastCode = try parser.parseInstruction(visitor: &visitor)
152+
let shouldContinue = try !parser.stream.hasReachedEnd()
153+
if !shouldContinue {
154+
guard lastCode == .end else {
155+
throw WasmParserError.endOpcodeExpected
156+
}
157+
}
158+
return shouldContinue
159+
}
160+
}
161+
129162
/// Flags for enabling/disabling WebAssembly features
130163
public struct WasmFeatureSet: OptionSet {
131164
/// The raw value of the feature set

0 commit comments

Comments
 (0)