Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add backtrace support #150

Merged
merged 11 commits into from
Oct 21, 2024
22 changes: 21 additions & 1 deletion Sources/WAT/Encoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ struct ExpressionEncoder: InstructionEncoder {
}
}

func encode(module: inout Wat) throws -> [UInt8] {
func encode(module: inout Wat, options: EncodeOptions) throws -> [UInt8] {
var encoder = Encoder()
encoder.writeHeader()

Expand Down Expand Up @@ -675,5 +675,25 @@ func encode(module: inout Wat) throws -> [UInt8] {
}
}

// (Optional) Name Section
if !module.functionsMap.isEmpty, options.nameSection {
encoder.section(id: 0) { encoder in
encoder.encode("name")
// Subsection 1: Function names
encoder.section(id: 1) { encoder in
let functionNames = module.functionsMap.enumerated().compactMap { i, decl -> (Int, String)? in
guard let name = decl.id else { return nil }
return (i, name.value)
}
encoder.encodeVector(functionNames) { entry, encoder in
let (index, name) = entry
encoder.writeUnsignedLEB128(UInt(index))
// Drop initial "$"
encoder.encode(String(name.dropFirst()))
}
}
}
}

return encoder.output
}
26 changes: 22 additions & 4 deletions Sources/WAT/WAT.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
import WasmParser

/// Options for encoding a WebAssembly module into a binary format.
public struct EncodeOptions {
/// Whether to include the name section.
public var nameSection: Bool

/// The default encoding options.
public static let `default` = EncodeOptions()

/// Creates a new encoding options instance.
public init(nameSection: Bool = false) {
self.nameSection = nameSection
}
}

/// Transforms a WebAssembly text format (WAT) string into a WebAssembly binary format byte array.
/// - Parameter input: The WAT string to transform
/// - Returns: The WebAssembly binary format byte array
Expand All @@ -17,9 +31,13 @@ import WasmParser
/// )
/// """)
/// ```
public func wat2wasm(_ input: String, features: WasmFeatureSet = .default) throws -> [UInt8] {
public func wat2wasm(
_ input: String,
features: WasmFeatureSet = .default,
options: EncodeOptions = .default
) throws -> [UInt8] {
var wat = try parseWAT(input, features: features)
return try encode(module: &wat)
return try encode(module: &wat, options: options)
}

/// A WAT module representation.
Expand Down Expand Up @@ -65,8 +83,8 @@ public struct Wat {
/// This method effectively consumes the module value, encoding it into a
/// binary format byte array. If you need to encode the module multiple times,
/// you should create a copy of the module value before encoding it.
public mutating func encode() throws -> [UInt8] {
try WAT.encode(module: &self)
public mutating func encode(options: EncodeOptions = .default) throws -> [UInt8] {
try WAT.encode(module: &self, options: options)
}
}

Expand Down
8 changes: 4 additions & 4 deletions Sources/WasmKit/Execution/ConstEvaluation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ extension ConstExpression {

private func _evaluate<C: ConstEvaluationContextProtocol>(context: C) throws -> Value {
guard self.last == .end, self.count == 2 else {
throw InstantiationError.unsupported("Expect `end` at the end of offset expression")
throw ValidationError(.expectedEndAtOffsetExpression)
}
let constInst = self[0]
switch constInst {
Expand All @@ -68,7 +68,7 @@ extension ConstExpression {
case .refFunc(let functionIndex):
return try .ref(context.functionRef(functionIndex))
default:
throw InstantiationError.unsupported("illegal const expression instruction: \(constInst)")
throw ValidationError(.illegalConstExpressionInstruction(constInst))
}
}
}
Expand Down Expand Up @@ -97,10 +97,10 @@ extension WasmParser.ElementSegment {
case .ref(.function(let addr)):
return .function(addr)
default:
throw Trap._raw("Unexpected global value type for element initializer expression")
throw ValidationError(.unexpectedGlobalValueType)
}
default:
throw Trap._raw("Unexpected element initializer expression: \(expression)")
throw ValidationError(.unexpectedElementInitializer(expression: "\(expression)"))
}
}
}
Loading