From f31876fff984ef7050adcdbe7f4c8bb3255ed8d0 Mon Sep 17 00:00:00 2001 From: Matthias Liedtke Date: Wed, 29 Jan 2025 16:14:42 +0100 Subject: [PATCH] [wasm] Add more simd load instructions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Note that there are even more simd load instructions (those with "extract lane") but they have different signatures, so they will need separate Fuzzilli nodes and therefore are not included in this change. Bug: chromium:391916477 Change-Id: Iab3f1be0e0c640445ec181240508c2ee0228edab Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/7988888 Reviewed-by: Carl Smith Reviewed-by: Eva Herencsárová Commit-Queue: Matthias Liedtke --- Sources/Fuzzilli/Base/ProgramBuilder.swift | 4 +- .../CodeGen/CodeGeneratorWeights.swift | 2 +- .../Fuzzilli/CodeGen/WasmCodeGenerators.swift | 6 +- Sources/Fuzzilli/FuzzIL/Instruction.swift | 65 +++++++++- Sources/Fuzzilli/FuzzIL/Opcodes.swift | 2 +- Sources/Fuzzilli/FuzzIL/WasmOperations.swift | 25 +++- Sources/Fuzzilli/Lifting/FuzzILLifter.swift | 4 +- .../Fuzzilli/Lifting/JavaScriptLifter.swift | 2 +- Sources/Fuzzilli/Lifting/WasmLifter.swift | 6 +- .../Fuzzilli/Mutators/OperationMutator.swift | 2 +- Sources/Fuzzilli/Protobuf/operations.pb.swift | 114 ++++++++++++++++-- Sources/Fuzzilli/Protobuf/operations.proto | 21 +++- Sources/Fuzzilli/Protobuf/program.pb.swift | 22 ++-- Sources/Fuzzilli/Protobuf/program.proto | 2 +- Tests/FuzzilliTests/WasmTests.swift | 39 ++++++ 15 files changed, 269 insertions(+), 47 deletions(-) diff --git a/Sources/Fuzzilli/Base/ProgramBuilder.swift b/Sources/Fuzzilli/Base/ProgramBuilder.swift index ae9c7bf1..0df465c1 100644 --- a/Sources/Fuzzilli/Base/ProgramBuilder.swift +++ b/Sources/Fuzzilli/Base/ProgramBuilder.swift @@ -3346,9 +3346,9 @@ public class ProgramBuilder { } @discardableResult - public func wasmI64x2LoadSplat(memory: Variable, dynamicOffset: Variable, staticOffset: Int64) -> Variable { + func wasmSimdLoad(kind: WasmSimdLoad.Kind, memory: Variable, dynamicOffset: Variable, staticOffset: Int64) -> Variable { let isMemory64 = b.type(of: memory).wasmMemoryType!.isMemory64 - return b.emit(WasmI64x2LoadSplat(staticOffset: staticOffset, isMemory64: isMemory64), withInputs: [memory, dynamicOffset]).output + return b.emit(WasmSimdLoad(kind: kind, staticOffset: staticOffset, isMemory64: isMemory64), withInputs: [memory, dynamicOffset]).output } } diff --git a/Sources/Fuzzilli/CodeGen/CodeGeneratorWeights.swift b/Sources/Fuzzilli/CodeGen/CodeGeneratorWeights.swift index d140ab02..54dc9efc 100644 --- a/Sources/Fuzzilli/CodeGen/CodeGeneratorWeights.swift +++ b/Sources/Fuzzilli/CodeGen/CodeGeneratorWeights.swift @@ -292,7 +292,7 @@ public let codeGeneratorWeights = [ "WasmSimd128CompareGenerator": 5, "WasmI64x2SplatGenerator": 5, "WasmI64x2ExtractLaneGenerator": 5, - "WasmI64x2LoadSplatGenerator": 5, + "WasmSimdLoadGenerator": 5, "WasmSelectGenerator": 10, ] diff --git a/Sources/Fuzzilli/CodeGen/WasmCodeGenerators.swift b/Sources/Fuzzilli/CodeGen/WasmCodeGenerators.swift index d680061f..8654e548 100644 --- a/Sources/Fuzzilli/CodeGen/WasmCodeGenerators.swift +++ b/Sources/Fuzzilli/CodeGen/WasmCodeGenerators.swift @@ -850,13 +850,13 @@ public let WasmCodeGenerators: [CodeGenerator] = [ function.wasmI64x2ExtractLane(input, 0) }, - CodeGenerator("WasmI64x2LoadSplatGenerator", inContext: .wasmFunction, inputs: .required(.object(ofGroup: "WasmMemory"))) { b, memory in + CodeGenerator("WasmSimdLoadGenerator", inContext: .wasmFunction, inputs: .required(.object(ofGroup: "WasmMemory"))) { b, memory in if (b.hasZeroPages(memory: memory)) { return } let function = b.currentWasmModule.currentWasmFunction let (dynamicOffset, staticOffset) = b.generateMemoryIndexes(forMemory: memory) - - function.wasmI64x2LoadSplat(memory: memory, dynamicOffset: dynamicOffset, staticOffset: staticOffset) + let kind = chooseUniform(from: WasmSimdLoad.Kind.allCases) + function.wasmSimdLoad(kind: kind, memory: memory, dynamicOffset: dynamicOffset, staticOffset: staticOffset) }, // TODO: Add three generators for JSPI diff --git a/Sources/Fuzzilli/FuzzIL/Instruction.swift b/Sources/Fuzzilli/FuzzIL/Instruction.swift index 31636b9b..c3a150a2 100644 --- a/Sources/Fuzzilli/FuzzIL/Instruction.swift +++ b/Sources/Fuzzilli/FuzzIL/Instruction.swift @@ -431,6 +431,33 @@ extension Instruction: ProtobufConvertible { } } + func convertWasmSimdLoadKind(_ loadKind: WasmSimdLoad.Kind) -> Fuzzilli_Protobuf_WasmSimdLoadKind { + switch loadKind { + case .LoadS128: + return .loads128 + case .Load8x8S: + return .load8X8S + case .Load8x8U: + return .load8X8U + case .Load16x4S: + return .load16X4S + case .Load16x4U: + return .load16X4U + case .Load32x2S: + return .load32X2S + case .Load32x2U: + return .load32X2U + case .Load8Splat: + return .load8Splat + case .Load16Splat: + return .load16Splat + case .Load32Splat: + return .load32Splat + case .Load64Splat: + return .load64Splat + } + } + func convertWasmGlobal(wasmGlobal: WasmGlobal) -> Fuzzilli_Protobuf_WasmGlobal.OneOf_WasmGlobal { switch wasmGlobal { case .wasmi32(let val): @@ -1303,8 +1330,9 @@ extension Instruction: ProtobufConvertible { $0.wasmI64X2Splat = Fuzzilli_Protobuf_WasmI64x2Splat() case .wasmI64x2ExtractLane(_): $0.wasmI64X2ExtractLane = Fuzzilli_Protobuf_WasmI64x2ExtractLane() - case .wasmI64x2LoadSplat(let op): - $0.wasmI64X2LoadSplat = Fuzzilli_Protobuf_WasmI64x2LoadSplat.with { + case .wasmSimdLoad(let op): + $0.wasmSimdLoad = Fuzzilli_Protobuf_WasmSimdLoad.with { + $0.kind = convertWasmSimdLoadKind(op.kind) $0.staticOffset = op.staticOffset $0.isMemory64 = op.isMemory64 } @@ -1421,6 +1449,35 @@ extension Instruction: ProtobufConvertible { } } + func convertProtoWasmSimdLoadKind(_ loadKind: Fuzzilli_Protobuf_WasmSimdLoadKind) -> WasmSimdLoad.Kind { + switch loadKind { + case .loads128: + return .LoadS128 + case .load8X8S: + return .Load8x8S + case .load8X8U: + return .Load8x8U + case .load16X4S: + return .Load16x4S + case .load16X4U: + return .Load16x4U + case .load32X2S: + return .Load32x2S + case .load32X2U: + return .Load32x2U + case .load8Splat: + return .Load8Splat + case .load16Splat: + return .Load16Splat + case .load32Splat: + return .Load32Splat + case .load64Splat: + return .Load64Splat + case .UNRECOGNIZED(let i): + fatalError("Invalid WasmSimdLoadKind \(i)") + } + } + func convertWasmGlobal(_ proto: Fuzzilli_Protobuf_WasmGlobal) -> WasmGlobal { switch proto.wasmGlobal { case .nullref(_): @@ -2093,8 +2150,8 @@ extension Instruction: ProtobufConvertible { op = WasmI64x2Splat() case .wasmI64X2ExtractLane(_): op = WasmI64x2ExtractLane(lane: 0) - case .wasmI64X2LoadSplat(let p): - op = WasmI64x2LoadSplat(staticOffset: p.staticOffset, isMemory64: p.isMemory64) + case .wasmSimdLoad(let p): + op = WasmSimdLoad(kind: convertProtoWasmSimdLoadKind(p.kind), staticOffset: p.staticOffset, isMemory64: p.isMemory64) } guard op.numInputs + op.numOutputs + op.numInnerOutputs == inouts.count else { diff --git a/Sources/Fuzzilli/FuzzIL/Opcodes.swift b/Sources/Fuzzilli/FuzzIL/Opcodes.swift index 25a03210..8af19f43 100644 --- a/Sources/Fuzzilli/FuzzIL/Opcodes.swift +++ b/Sources/Fuzzilli/FuzzIL/Opcodes.swift @@ -308,7 +308,7 @@ enum Opcode { case wasmSimd128FloatBinOp(WasmSimd128FloatBinOp) case wasmI64x2Splat(WasmI64x2Splat) case wasmI64x2ExtractLane(WasmI64x2ExtractLane) - case wasmI64x2LoadSplat(WasmI64x2LoadSplat) + case wasmSimdLoad(WasmSimdLoad) case wasmUnreachable(WasmUnreachable) case wasmSelect(WasmSelect) diff --git a/Sources/Fuzzilli/FuzzIL/WasmOperations.swift b/Sources/Fuzzilli/FuzzIL/WasmOperations.swift index 07230321..59e14a59 100644 --- a/Sources/Fuzzilli/FuzzIL/WasmOperations.swift +++ b/Sources/Fuzzilli/FuzzIL/WasmOperations.swift @@ -1523,13 +1523,30 @@ final class WasmI64x2ExtractLane: WasmOperation { } } -final class WasmI64x2LoadSplat: WasmOperation { - override var opcode: Opcode { .wasmI64x2LoadSplat(self) } - +final class WasmSimdLoad: WasmOperation { + enum Kind: UInt8, CaseIterable { + // TODO(mliedtke): Test all the other variants! + case LoadS128 = 0x00 + case Load8x8S = 0x01 + case Load8x8U = 0x02 + case Load16x4S = 0x03 + case Load16x4U = 0x04 + case Load32x2S = 0x05 + case Load32x2U = 0x06 + case Load8Splat = 0x07 + case Load16Splat = 0x08 + case Load32Splat = 0x09 + case Load64Splat = 0x0A + } + + override var opcode: Opcode { .wasmSimdLoad(self) } + + let kind: Kind let staticOffset: Int64 let isMemory64: Bool - init(staticOffset: Int64, isMemory64: Bool) { + init(kind: Kind, staticOffset: Int64, isMemory64: Bool) { + self.kind = kind self.staticOffset = staticOffset self.isMemory64 = isMemory64 let dynamicOffsetType = isMemory64 ? ILType.wasmi64 : ILType.wasmi32 diff --git a/Sources/Fuzzilli/Lifting/FuzzILLifter.swift b/Sources/Fuzzilli/Lifting/FuzzILLifter.swift index 9bcc9d46..e525d2e2 100644 --- a/Sources/Fuzzilli/Lifting/FuzzILLifter.swift +++ b/Sources/Fuzzilli/Lifting/FuzzILLifter.swift @@ -1099,8 +1099,8 @@ public class FuzzILLifter: Lifter { case .wasmI64x2ExtractLane(let op): w.emit("\(output()) <- WasmI64x2ExtractLane \(input(0)) \(op.lane)") - case .wasmI64x2LoadSplat(_): - w.emit("\(output()) <- WasmI64x2LoadSplat \(input(0))") + case .wasmSimdLoad(let op): + w.emit("\(output()) <- WasmSimdLoad \(op.kind) \(input(0)) + \(op.staticOffset)") default: fatalError("No FuzzIL lifting for this operation!") diff --git a/Sources/Fuzzilli/Lifting/JavaScriptLifter.swift b/Sources/Fuzzilli/Lifting/JavaScriptLifter.swift index 5391228f..773f8a97 100644 --- a/Sources/Fuzzilli/Lifting/JavaScriptLifter.swift +++ b/Sources/Fuzzilli/Lifting/JavaScriptLifter.swift @@ -1607,7 +1607,7 @@ public class JavaScriptLifter: Lifter { .wasmSimd128Compare(_), .wasmI64x2Splat(_), .wasmI64x2ExtractLane(_), - .wasmI64x2LoadSplat(_): + .wasmSimdLoad(_): fatalError("unreachable") } diff --git a/Sources/Fuzzilli/Lifting/WasmLifter.swift b/Sources/Fuzzilli/Lifting/WasmLifter.swift index 8388020c..d409445f 100644 --- a/Sources/Fuzzilli/Lifting/WasmLifter.swift +++ b/Sources/Fuzzilli/Lifting/WasmLifter.swift @@ -1071,7 +1071,7 @@ public class WasmLifter { try memoryOpImportAnalysis(instr: instr, isMemory64: op.isMemory64) case .wasmMemoryStore(let op): try memoryOpImportAnalysis(instr: instr, isMemory64: op.isMemory64) - case .wasmI64x2LoadSplat(let op): + case .wasmSimdLoad(let op): try memoryOpImportAnalysis(instr: instr, isMemory64: op.isMemory64) case .wasmTableGet(_), .wasmTableSet(_): @@ -1556,9 +1556,9 @@ public class WasmLifter { return Data([0xFD]) + Leb128.unsignedEncode(0x12) case .wasmI64x2ExtractLane(let op): return Data([0xFD]) + Leb128.unsignedEncode(0x1D) + Leb128.unsignedEncode(op.lane) - case .wasmI64x2LoadSplat(let op): + case .wasmSimdLoad(let op): // The memory immediate is {staticOffset, align} where align is 0 by default. Use signed encoding for potential bad (i.e. negative) offsets. - return Data([0xFD]) + Leb128.unsignedEncode(0x0A) + Leb128.unsignedEncode(0) + Leb128.signedEncode(Int(op.staticOffset)) + return Data([0xFD, op.kind.rawValue]) + Leb128.unsignedEncode(0) + Leb128.signedEncode(Int(op.staticOffset)) default: fatalError("unreachable") diff --git a/Sources/Fuzzilli/Mutators/OperationMutator.swift b/Sources/Fuzzilli/Mutators/OperationMutator.swift index e27c8cf5..740d3596 100644 --- a/Sources/Fuzzilli/Mutators/OperationMutator.swift +++ b/Sources/Fuzzilli/Mutators/OperationMutator.swift @@ -377,7 +377,7 @@ public class OperationMutator: BaseInstructionMutator { case .wasmI64x2ExtractLane(let op): // TODO: ? newOp = op - case .wasmI64x2LoadSplat(let op): + case .wasmSimdLoad(let op): // TODO: ? newOp = op case .createWasmJSTag(let op): diff --git a/Sources/Fuzzilli/Protobuf/operations.pb.swift b/Sources/Fuzzilli/Protobuf/operations.pb.swift index 4f72c442..0efd2ada 100644 --- a/Sources/Fuzzilli/Protobuf/operations.pb.swift +++ b/Sources/Fuzzilli/Protobuf/operations.pb.swift @@ -751,6 +751,76 @@ public enum Fuzzilli_Protobuf_WasmMemoryStoreType: SwiftProtobuf.Enum, Swift.Cas } +public enum Fuzzilli_Protobuf_WasmSimdLoadKind: SwiftProtobuf.Enum, Swift.CaseIterable { + public typealias RawValue = Int + case loads128 // = 0 + case load8X8S // = 1 + case load8X8U // = 2 + case load16X4S // = 3 + case load16X4U // = 4 + case load32X2S // = 5 + case load32X2U // = 6 + case load8Splat // = 7 + case load16Splat // = 8 + case load32Splat // = 9 + case load64Splat // = 10 + case UNRECOGNIZED(Int) + + public init() { + self = .loads128 + } + + public init?(rawValue: Int) { + switch rawValue { + case 0: self = .loads128 + case 1: self = .load8X8S + case 2: self = .load8X8U + case 3: self = .load16X4S + case 4: self = .load16X4U + case 5: self = .load32X2S + case 6: self = .load32X2U + case 7: self = .load8Splat + case 8: self = .load16Splat + case 9: self = .load32Splat + case 10: self = .load64Splat + default: self = .UNRECOGNIZED(rawValue) + } + } + + public var rawValue: Int { + switch self { + case .loads128: return 0 + case .load8X8S: return 1 + case .load8X8U: return 2 + case .load16X4S: return 3 + case .load16X4U: return 4 + case .load32X2S: return 5 + case .load32X2U: return 6 + case .load8Splat: return 7 + case .load16Splat: return 8 + case .load32Splat: return 9 + case .load64Splat: return 10 + case .UNRECOGNIZED(let i): return i + } + } + + // The compiler won't synthesize support with the UNRECOGNIZED case. + public static let allCases: [Fuzzilli_Protobuf_WasmSimdLoadKind] = [ + .loads128, + .load8X8S, + .load8X8U, + .load16X4S, + .load16X4U, + .load32X2S, + .load32X2U, + .load8Splat, + .load16Splat, + .load32Splat, + .load64Splat, + ] + +} + /// Parameters used by function definitions, not an operation by itself. public struct Fuzzilli_Protobuf_Parameters: Sendable { // SwiftProtobuf.Message conformance is added in an extension below. See the @@ -4309,11 +4379,13 @@ public struct Fuzzilli_Protobuf_WasmI64x2ExtractLane: Sendable { public init() {} } -public struct Fuzzilli_Protobuf_WasmI64x2LoadSplat: Sendable { +public struct Fuzzilli_Protobuf_WasmSimdLoad: Sendable { // SwiftProtobuf.Message conformance is added in an extension below. See the // `Message` and `Message+*Additions` files in the SwiftProtobuf library for // methods supported on all messages. + public var kind: Fuzzilli_Protobuf_WasmSimdLoadKind = .loads128 + public var staticOffset: Int64 = 0 public var isMemory64: Bool = false @@ -4488,6 +4560,22 @@ extension Fuzzilli_Protobuf_WasmMemoryStoreType: SwiftProtobuf._ProtoNameProvidi ] } +extension Fuzzilli_Protobuf_WasmSimdLoadKind: SwiftProtobuf._ProtoNameProviding { + public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ + 0: .same(proto: "LOADS128"), + 1: .same(proto: "LOAD8x8S"), + 2: .same(proto: "LOAD8x8U"), + 3: .same(proto: "LOAD16x4S"), + 4: .same(proto: "LOAD16x4U"), + 5: .same(proto: "LOAD32x2S"), + 6: .same(proto: "LOAD32x2U"), + 7: .same(proto: "LOAD8SPLAT"), + 8: .same(proto: "LOAD16SPLAT"), + 9: .same(proto: "LOAD32SPLAT"), + 10: .same(proto: "LOAD64SPLAT"), + ] +} + extension Fuzzilli_Protobuf_Parameters: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { public static let protoMessageName: String = _protobuf_package + ".Parameters" public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ @@ -12597,11 +12685,12 @@ extension Fuzzilli_Protobuf_WasmI64x2ExtractLane: SwiftProtobuf.Message, SwiftPr } } -extension Fuzzilli_Protobuf_WasmI64x2LoadSplat: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { - public static let protoMessageName: String = _protobuf_package + ".WasmI64x2LoadSplat" +extension Fuzzilli_Protobuf_WasmSimdLoad: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding { + public static let protoMessageName: String = _protobuf_package + ".WasmSimdLoad" public static let _protobuf_nameMap: SwiftProtobuf._NameMap = [ - 1: .same(proto: "staticOffset"), - 2: .same(proto: "isMemory64"), + 1: .same(proto: "kind"), + 2: .same(proto: "staticOffset"), + 3: .same(proto: "isMemory64"), ] public mutating func decodeMessage(decoder: inout D) throws { @@ -12610,24 +12699,29 @@ extension Fuzzilli_Protobuf_WasmI64x2LoadSplat: SwiftProtobuf.Message, SwiftProt // allocates stack space for every case branch when no optimizations are // enabled. https://github.com/apple/swift-protobuf/issues/1034 switch fieldNumber { - case 1: try { try decoder.decodeSingularInt64Field(value: &self.staticOffset) }() - case 2: try { try decoder.decodeSingularBoolField(value: &self.isMemory64) }() + case 1: try { try decoder.decodeSingularEnumField(value: &self.kind) }() + case 2: try { try decoder.decodeSingularInt64Field(value: &self.staticOffset) }() + case 3: try { try decoder.decodeSingularBoolField(value: &self.isMemory64) }() default: break } } } public func traverse(visitor: inout V) throws { + if self.kind != .loads128 { + try visitor.visitSingularEnumField(value: self.kind, fieldNumber: 1) + } if self.staticOffset != 0 { - try visitor.visitSingularInt64Field(value: self.staticOffset, fieldNumber: 1) + try visitor.visitSingularInt64Field(value: self.staticOffset, fieldNumber: 2) } if self.isMemory64 != false { - try visitor.visitSingularBoolField(value: self.isMemory64, fieldNumber: 2) + try visitor.visitSingularBoolField(value: self.isMemory64, fieldNumber: 3) } try unknownFields.traverse(visitor: &visitor) } - public static func ==(lhs: Fuzzilli_Protobuf_WasmI64x2LoadSplat, rhs: Fuzzilli_Protobuf_WasmI64x2LoadSplat) -> Bool { + public static func ==(lhs: Fuzzilli_Protobuf_WasmSimdLoad, rhs: Fuzzilli_Protobuf_WasmSimdLoad) -> Bool { + if lhs.kind != rhs.kind {return false} if lhs.staticOffset != rhs.staticOffset {return false} if lhs.isMemory64 != rhs.isMemory64 {return false} if lhs.unknownFields != rhs.unknownFields {return false} diff --git a/Sources/Fuzzilli/Protobuf/operations.proto b/Sources/Fuzzilli/Protobuf/operations.proto index 2859b496..e9ae34bf 100644 --- a/Sources/Fuzzilli/Protobuf/operations.proto +++ b/Sources/Fuzzilli/Protobuf/operations.proto @@ -1255,7 +1255,22 @@ message WasmI64x2Splat { message WasmI64x2ExtractLane { } -message WasmI64x2LoadSplat { - int64 staticOffset = 1; - bool isMemory64 = 2; +enum WasmSimdLoadKind { + LOADS128 = 0; + LOAD8x8S = 1; + LOAD8x8U = 2; + LOAD16x4S = 3; + LOAD16x4U = 4; + LOAD32x2S = 5; + LOAD32x2U = 6; + LOAD8SPLAT = 7; + LOAD16SPLAT = 8; + LOAD32SPLAT = 9; + LOAD64SPLAT = 10; +} + +message WasmSimdLoad { + WasmSimdLoadKind kind = 1; + int64 staticOffset = 2; + bool isMemory64 = 3; } diff --git a/Sources/Fuzzilli/Protobuf/program.pb.swift b/Sources/Fuzzilli/Protobuf/program.pb.swift index f7f85942..eeaa73cf 100644 --- a/Sources/Fuzzilli/Protobuf/program.pb.swift +++ b/Sources/Fuzzilli/Protobuf/program.pb.swift @@ -2233,12 +2233,12 @@ public struct Fuzzilli_Protobuf_Instruction: Sendable { set {operation = .wasmI64X2ExtractLane(newValue)} } - public var wasmI64X2LoadSplat: Fuzzilli_Protobuf_WasmI64x2LoadSplat { + public var wasmSimdLoad: Fuzzilli_Protobuf_WasmSimdLoad { get { - if case .wasmI64X2LoadSplat(let v)? = operation {return v} - return Fuzzilli_Protobuf_WasmI64x2LoadSplat() + if case .wasmSimdLoad(let v)? = operation {return v} + return Fuzzilli_Protobuf_WasmSimdLoad() } - set {operation = .wasmI64X2LoadSplat(newValue)} + set {operation = .wasmSimdLoad(newValue)} } public var wasmUnreachable: Fuzzilli_Protobuf_WasmUnreachable { @@ -2533,7 +2533,7 @@ public struct Fuzzilli_Protobuf_Instruction: Sendable { case wasmSimd128FloatBinOp(Fuzzilli_Protobuf_WasmSimd128FloatBinOp) case wasmI64X2Splat(Fuzzilli_Protobuf_WasmI64x2Splat) case wasmI64X2ExtractLane(Fuzzilli_Protobuf_WasmI64x2ExtractLane) - case wasmI64X2LoadSplat(Fuzzilli_Protobuf_WasmI64x2LoadSplat) + case wasmSimdLoad(Fuzzilli_Protobuf_WasmSimdLoad) case wasmUnreachable(Fuzzilli_Protobuf_WasmUnreachable) case wasmSelect(Fuzzilli_Protobuf_WasmSelect) @@ -2859,7 +2859,7 @@ extension Fuzzilli_Protobuf_Instruction: SwiftProtobuf.Message, SwiftProtobuf._M 272: .same(proto: "wasmSimd128FloatBinOp"), 273: .same(proto: "wasmI64x2Splat"), 274: .same(proto: "wasmI64x2ExtractLane"), - 275: .same(proto: "wasmI64x2LoadSplat"), + 275: .same(proto: "wasmSimdLoad"), 276: .same(proto: "wasmUnreachable"), 277: .same(proto: "wasmSelect"), ] @@ -6416,16 +6416,16 @@ extension Fuzzilli_Protobuf_Instruction: SwiftProtobuf.Message, SwiftProtobuf._M } }() case 275: try { - var v: Fuzzilli_Protobuf_WasmI64x2LoadSplat? + var v: Fuzzilli_Protobuf_WasmSimdLoad? var hadOneofValue = false if let current = self.operation { hadOneofValue = true - if case .wasmI64X2LoadSplat(let m) = current {v = m} + if case .wasmSimdLoad(let m) = current {v = m} } try decoder.decodeSingularMessageField(value: &v) if let v = v { if hadOneofValue {try decoder.handleConflictingOneOf()} - self.operation = .wasmI64X2LoadSplat(v) + self.operation = .wasmSimdLoad(v) } }() case 276: try { @@ -7560,8 +7560,8 @@ extension Fuzzilli_Protobuf_Instruction: SwiftProtobuf.Message, SwiftProtobuf._M guard case .wasmI64X2ExtractLane(let v)? = self.operation else { preconditionFailure() } try visitor.visitSingularMessageField(value: v, fieldNumber: 274) }() - case .wasmI64X2LoadSplat?: try { - guard case .wasmI64X2LoadSplat(let v)? = self.operation else { preconditionFailure() } + case .wasmSimdLoad?: try { + guard case .wasmSimdLoad(let v)? = self.operation else { preconditionFailure() } try visitor.visitSingularMessageField(value: v, fieldNumber: 275) }() case .wasmUnreachable?: try { diff --git a/Sources/Fuzzilli/Protobuf/program.proto b/Sources/Fuzzilli/Protobuf/program.proto index f984245f..c3bd42a1 100644 --- a/Sources/Fuzzilli/Protobuf/program.proto +++ b/Sources/Fuzzilli/Protobuf/program.proto @@ -298,7 +298,7 @@ message Instruction { WasmSimd128FloatBinOp wasmSimd128FloatBinOp = 272; WasmI64x2Splat wasmI64x2Splat = 273; WasmI64x2ExtractLane wasmI64x2ExtractLane = 274; - WasmI64x2LoadSplat wasmI64x2LoadSplat = 275; + WasmSimdLoad wasmSimdLoad = 275; WasmUnreachable wasmUnreachable = 276; WasmSelect wasmSelect = 277; } diff --git a/Tests/FuzzilliTests/WasmTests.swift b/Tests/FuzzilliTests/WasmTests.swift index 37f73367..cbd4b28a 100644 --- a/Tests/FuzzilliTests/WasmTests.swift +++ b/Tests/FuzzilliTests/WasmTests.swift @@ -690,6 +690,45 @@ class WasmFoundationTests: XCTestCase { try allMemoryStoreTypesExecution(isMemory64: true) } + func wasmSimdLoad(isMemory64: Bool) throws { + let runner = try GetJavaScriptExecutorOrSkipTest() + let liveTestConfig = Configuration(logLevel: .error, enableInspection: true) + let fuzzer = makeMockFuzzer(config: liveTestConfig, environment: JavaScriptEnvironment()) + let b = fuzzer.makeBuilder() + + let module = b.buildWasmModule { wasmModule in + let memory = wasmModule.addMemory(minPages: 5, maxPages: 12, isMemory64: isMemory64) + + wasmModule.addWasmFunction(with: [] => .wasmi64) { function, _ in + let const = isMemory64 ? function.consti64 : {function.consti32(Int32($0))} + function.wasmMemoryStore(memory: memory, dynamicOffset: const(0), + value: function.consti64(3), storeType: .I64StoreMem, staticOffset: 0) + function.wasmMemoryStore(memory: memory, dynamicOffset: const(8), + value: function.consti64(6), storeType: .I64StoreMem, staticOffset: 0) + + let val = function.wasmSimdLoad(kind: .LoadS128, memory: memory, + dynamicOffset: const(0), staticOffset: 0) + let sum = function.wasmi64BinOp(function.wasmI64x2ExtractLane(val, 0), + function.wasmI64x2ExtractLane(val, 1), binOpKind: .Add) + function.wasmReturn(sum) + } + } + + let res0 = b.callMethod(module.getExportedMethod(at: 0), on: module.loadExports()) + b.callFunction(b.createNamedVariable(forBuiltin: "output"), withArgs: [b.callMethod("toString", on: res0)]) + + let jsProg = fuzzer.lifter.lift(b.finalize()) + testForOutput(program: jsProg, runner: runner, outputString: "9\n") + } + + func testWasmSimdLoadOnMemory32() throws { + try wasmSimdLoad(isMemory64: false) + } + + func testWasmSimdLoadOnMemory64() throws { + try wasmSimdLoad(isMemory64: true) + } + func testLoops() throws { let runner = try GetJavaScriptExecutorOrSkipTest() let liveTestConfig = Configuration(logLevel: .error, enableInspection: true)