Skip to content

Function References Draft #168

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

Draft
wants to merge 18 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add remaining instructions
  • Loading branch information
iainsmith committed Jan 4, 2025
commit 93721a38e647b4bbeb558d9ba81cb11c3b40d2fd
13 changes: 13 additions & 0 deletions Sources/WAT/BinaryInstructionEncoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -396,4 +396,17 @@ extension BinaryInstructionEncoder {
try encodeInstruction([0x14])
try encodeImmediates(functionIndex: functionIndex)
}
mutating func visitReturnCallRef(functionIndex: UInt32) throws {
try encodeInstruction([0x15])
try encodeImmediates(functionIndex: functionIndex)
}
mutating func visitAsNonNull() throws { try encodeInstruction([0xD4]) }
mutating func visitBrOnNull(functionIndex: UInt32) throws {
try encodeInstruction([0xD5])
try encodeImmediates(functionIndex: functionIndex)
}
mutating func visitBrOnNonNull(functionIndex: UInt32) throws {
try encodeInstruction([0xD6])
try encodeImmediates(functionIndex: functionIndex)
}
}
10 changes: 10 additions & 0 deletions Sources/WAT/ParseTextInstruction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,16 @@ func parseTextInstruction<V: InstructionVisitor>(keyword: String, expressionPars
case "call_ref":
let (functionIndex) = try expressionParser.visitCallRef(wat: &wat)
return { return try $0.visitCallRef(functionIndex: functionIndex) }
case "return_call_ref":
let (functionIndex) = try expressionParser.visitReturnCallRef(wat: &wat)
return { return try $0.visitReturnCallRef(functionIndex: functionIndex) }
case "as_non_null": return { return try $0.visitAsNonNull() }
case "br_on_null":
let (functionIndex) = try expressionParser.visitBrOnNull(wat: &wat)
return { return try $0.visitBrOnNull(functionIndex: functionIndex) }
case "br_on_non_null":
let (functionIndex) = try expressionParser.visitBrOnNonNull(wat: &wat)
return { return try $0.visitBrOnNonNull(functionIndex: functionIndex) }
default: return nil
}
}
11 changes: 10 additions & 1 deletion Sources/WAT/Parser/ExpressionParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ struct ExpressionParser<Visitor: InstructionVisitor> {

private mutating func refKind() throws -> ReferenceType {
if try parser.take(.id) {
return .funcRef // not sure about this.
return .funcRef // not sure about this.
} else if try parser.takeKeyword("func") {
return .funcRef
} else if try parser.takeKeyword("extern") {
Expand Down Expand Up @@ -445,6 +445,15 @@ extension ExpressionParser {
let use = try parser.expectIndexOrId()
return UInt32(try wat.types.resolve(use: use).index)
}
mutating func visitReturnCallRef(wat: inout Wat) throws -> UInt32 {
return 0
}
mutating func visitBrOnNull(wat: inout Wat) throws -> UInt32 {
return 0
}
mutating func visitBrOnNonNull(wat: inout Wat) throws -> UInt32 {
return 0
}
mutating func visitCallIndirect(wat: inout Wat) throws -> (typeIndex: UInt32, tableIndex: UInt32) {
let tableIndex: UInt32
if let tableId = try parser.takeIndexOrId() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,11 @@ extension Int32: InstructionImmediate {

extension Instruction.RefNullOperand {
init(result: VReg, type: ReferenceType) {
self.init(result: result, rawType: type.heapType.rawValue) // need to figure out rawType here
self.init(result: result, rawType: type.heapType.rawValue) // need to figure out rawType here
}

var type: ReferenceType {
ReferenceType(isNullable: true, heapType: HeapType(rawValue: rawType)!) // is this still a valid conversion?
ReferenceType(isNullable: true, heapType: HeapType(rawValue: rawType)!) // is this still a valid conversion?
}
}

Expand Down
17 changes: 17 additions & 0 deletions Sources/WasmParser/BinaryInstructionDecoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ protocol BinaryInstructionDecoder {
@inlinable mutating func visitTableSize() throws -> UInt32
/// Decode `call_ref` immediates
@inlinable mutating func visitCallRef() throws -> UInt32
/// Decode `return_call_ref` immediates
@inlinable mutating func visitReturnCallRef() throws -> UInt32
/// Decode `br_on_null` immediates
@inlinable mutating func visitBrOnNull() throws -> UInt32
/// Decode `br_on_non_null` immediates
@inlinable mutating func visitBrOnNonNull() throws -> UInt32
}
@inlinable
func parseBinaryInstruction<V: InstructionVisitor, D: BinaryInstructionDecoder>(visitor: inout V, decoder: inout D) throws -> Bool {
Expand Down Expand Up @@ -137,6 +143,9 @@ func parseBinaryInstruction<V: InstructionVisitor, D: BinaryInstructionDecoder>(
case 0x14:
let (functionIndex) = try decoder.visitCallRef()
try visitor.visitCallRef(functionIndex: functionIndex)
case 0x15:
let (functionIndex) = try decoder.visitReturnCallRef()
try visitor.visitReturnCallRef(functionIndex: functionIndex)
case 0x1A:
try visitor.visitDrop()
case 0x1B:
Expand Down Expand Up @@ -516,6 +525,14 @@ func parseBinaryInstruction<V: InstructionVisitor, D: BinaryInstructionDecoder>(
case 0xD2:
let (functionIndex) = try decoder.visitRefFunc()
try visitor.visitRefFunc(functionIndex: functionIndex)
case 0xD4:
try visitor.visitAsNonNull()
case 0xD5:
let (functionIndex) = try decoder.visitBrOnNull()
try visitor.visitBrOnNull(functionIndex: functionIndex)
case 0xD6:
let (functionIndex) = try decoder.visitBrOnNonNull()
try visitor.visitBrOnNonNull(functionIndex: functionIndex)
case 0xFC:

let opcode1 = try decoder.claimNextByte()
Expand Down
24 changes: 24 additions & 0 deletions Sources/WasmParser/InstructionVisitor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,10 @@ public enum Instruction: Equatable {
case `tableGrow`(table: UInt32)
case `tableSize`(table: UInt32)
case `callRef`(functionIndex: UInt32)
case `returnCallRef`(functionIndex: UInt32)
case `asNonNull`
case `brOnNull`(functionIndex: UInt32)
case `brOnNonNull`(functionIndex: UInt32)
}

/// A visitor that visits all instructions by a single visit method.
Expand Down Expand Up @@ -289,6 +293,10 @@ extension AnyInstructionVisitor {
public mutating func visitTableGrow(table: UInt32) throws { return try self.visit(.tableGrow(table: table)) }
public mutating func visitTableSize(table: UInt32) throws { return try self.visit(.tableSize(table: table)) }
public mutating func visitCallRef(functionIndex: UInt32) throws { return try self.visit(.callRef(functionIndex: functionIndex)) }
public mutating func visitReturnCallRef(functionIndex: UInt32) throws { return try self.visit(.returnCallRef(functionIndex: functionIndex)) }
public mutating func visitAsNonNull() throws { return try self.visit(.asNonNull) }
public mutating func visitBrOnNull(functionIndex: UInt32) throws { return try self.visit(.brOnNull(functionIndex: functionIndex)) }
public mutating func visitBrOnNonNull(functionIndex: UInt32) throws { return try self.visit(.brOnNonNull(functionIndex: functionIndex)) }
}

/// A visitor for WebAssembly instructions.
Expand Down Expand Up @@ -402,6 +410,14 @@ public protocol InstructionVisitor {
mutating func visitTableSize(table: UInt32) throws
/// Visiting `call_ref` instruction.
mutating func visitCallRef(functionIndex: UInt32) throws
/// Visiting `return_call_ref` instruction.
mutating func visitReturnCallRef(functionIndex: UInt32) throws
/// Visiting `as_non_null` instruction.
mutating func visitAsNonNull() throws
/// Visiting `br_on_null` instruction.
mutating func visitBrOnNull(functionIndex: UInt32) throws
/// Visiting `br_on_non_null` instruction.
mutating func visitBrOnNonNull(functionIndex: UInt32) throws
}

extension InstructionVisitor {
Expand Down Expand Up @@ -461,6 +477,10 @@ extension InstructionVisitor {
case let .tableGrow(table): return try visitTableGrow(table: table)
case let .tableSize(table): return try visitTableSize(table: table)
case let .callRef(functionIndex): return try visitCallRef(functionIndex: functionIndex)
case let .returnCallRef(functionIndex): return try visitReturnCallRef(functionIndex: functionIndex)
case .asNonNull: return try visitAsNonNull()
case let .brOnNull(functionIndex): return try visitBrOnNull(functionIndex: functionIndex)
case let .brOnNonNull(functionIndex): return try visitBrOnNonNull(functionIndex: functionIndex)
}
}
}
Expand Down Expand Up @@ -520,5 +540,9 @@ extension InstructionVisitor {
public mutating func visitTableGrow(table: UInt32) throws {}
public mutating func visitTableSize(table: UInt32) throws {}
public mutating func visitCallRef(functionIndex: UInt32) throws {}
public mutating func visitReturnCallRef(functionIndex: UInt32) throws {}
public mutating func visitAsNonNull() throws {}
public mutating func visitBrOnNull(functionIndex: UInt32) throws {}
public mutating func visitBrOnNonNull(functionIndex: UInt32) throws {}
}

10 changes: 10 additions & 0 deletions Sources/WasmParser/WasmParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,10 @@ extension Parser: BinaryInstructionDecoder {
return (typeIndex, tableIndex)
}

@inlinable mutating func visitReturnCallRef() throws -> UInt32 {
return 0
}

@inlinable mutating func visitTypedSelect() throws -> WasmTypes.ValueType {
let results = try parseVector { try parseValueType() }
guard results.count == 1 else {
Expand Down Expand Up @@ -692,6 +696,12 @@ extension Parser: BinaryInstructionDecoder {
}
return refType
}
@inlinable mutating func visitBrOnNull() throws -> UInt32 {
return 0
}
@inlinable mutating func visitBrOnNonNull() throws -> UInt32 {
return 0
}

@inlinable mutating func visitRefFunc() throws -> UInt32 { try parseUnsigned() }
@inlinable mutating func visitMemoryInit() throws -> UInt32 {
Expand Down
4 changes: 2 additions & 2 deletions Sources/WasmTypes/WasmTypes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ public struct FunctionType: Equatable, Hashable {

public enum HeapType: UInt8, Equatable, Hashable {
/// A reference to any kind of function.
case funcRef // -> to be renamed func
case funcRef // -> to be renamed func

/// An external host data.
case externRef // -> to be renamed extern
case externRef // -> to be renamed extern
}

/// Reference types
Expand Down
4 changes: 2 additions & 2 deletions Tests/WasmKitTests/SpectestTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ final class SpectestTests: XCTestCase {
let defaultConfig = EngineConfiguration()
let result = try await spectestResult(
path: Self.functionReferences,
include: ["function-references/call_ref.wast"], // focusing on call_ref for now, but will update to run all function-references tests.
include: ["function-references/call_ref.wast"], // focusing on call_ref for now, but will update to run all function-references tests.
exclude: [],
parallel: false,
configuration: defaultConfig
Expand Down Expand Up @@ -116,7 +116,7 @@ final class SpectestTests: XCTestCase {
"gc/type-rec.wast",
"gc/type-subtyping.wast",
"gc/unreached-invalid.wast",
"gc/unreached-valid.wast"
"gc/unreached-valid.wast",
]
)
}
Expand Down
6 changes: 5 additions & 1 deletion Utilities/Instructions.json
Original file line number Diff line number Diff line change
Expand Up @@ -202,5 +202,9 @@
["saturatingFloatToInt", "i64.trunc_sat_f32_u" , ["0xFC", "0x05"], [] , "conversion"],
["saturatingFloatToInt", "i64.trunc_sat_f64_s" , ["0xFC", "0x06"], [] , "conversion"],
["saturatingFloatToInt", "i64.trunc_sat_f64_u" , ["0xFC", "0x07"], [] , "conversion"],
["referenceTypes" , "call_ref" , ["0x14"] , [["functionIndex", "UInt32"]] , null ]
["referenceTypes" , "call_ref" , ["0x14"] , [["functionIndex", "UInt32"]] , null ],
["referenceTypes" , "return_call_ref" , ["0x15"] , [["functionIndex", "UInt32"]] , null ],
["referenceTypes" , "as_non_null" , ["0xd4"] , [] , null ],
["referenceTypes" , "br_on_null" , ["0xd5"] , [["functionIndex", "UInt32"]] , null ],
["referenceTypes" , "br_on_non_null" , ["0xd6"] , [["functionIndex", "UInt32"]] , null ]
]
Loading