Skip to content

Commit 4dee437

Browse files
LiedtkeV8-internal LUCI CQ
authored andcommitted
[wasm] Use wasm-gc signatures for wasm functions
While this changes the IL to emit wasm-gc signatures for the functions, it doesn't yet actually allow using wasm-gc types in them. A few places (WasmDefineTable and WasmCallIndirect / WasmReturnCallIndirect) still need to be adapted to allow wasm-gc types before we can actually allow indexed wasm-gc types in function signatures. Bug: 445356784 Change-Id: I5715f584cfa5ee664f957a28e28bf80b6f3cdd9e Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/9115296 Commit-Queue: Matthias Liedtke <mliedtke@google.com> Reviewed-by: Manos Koukoutos <manoskouk@google.com>
1 parent 2b9cdba commit 4dee437

10 files changed

Lines changed: 69 additions & 76 deletions

File tree

Sources/Fuzzilli/Base/ProgramBuilder.swift

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3495,11 +3495,14 @@ public class ProgramBuilder {
34953495
private let b: ProgramBuilder
34963496
let signature: WasmSignature
34973497
let jsSignature: Signature
3498+
let signatureDef: Variable
34983499

3499-
public init(forBuilder b: ProgramBuilder, withSignature signature: WasmSignature) {
3500+
public init(forBuilder b: ProgramBuilder, signatureDef: Variable) {
3501+
assert(b.type(of: signatureDef).Is(.wasmTypeDef()))
35003502
self.b = b
3501-
self.signature = signature
3503+
self.signature = b.type(of: signatureDef).wasmFunctionSignatureDefSignature
35023504
self.jsSignature = convertWasmSignatureToJsSignature(signature)
3505+
self.signatureDef = signatureDef
35033506
}
35043507

35053508
// Wasm Instructions
@@ -4500,9 +4503,16 @@ public class ProgramBuilder {
45004503
// TODO: distinguish between exported and non-exported functions
45014504
@discardableResult
45024505
public func addWasmFunction(with signature: WasmSignature, _ body: (WasmFunction, Variable, [Variable]) -> [Variable]) -> Variable {
4503-
let instr = b.emit(BeginWasmFunction(signature: signature))
4506+
let signatureDef = b.wasmDefineAdHocSignatureType(signature: signature)
4507+
return addWasmFunction(signature: signatureDef, body)
4508+
}
4509+
4510+
@discardableResult
4511+
public func addWasmFunction(signature: Variable, _ body: (WasmFunction, Variable, [Variable]) -> [Variable]) -> Variable {
4512+
let signatureType = b.type(of: signature).wasmFunctionSignatureDefSignature
4513+
let instr = b.emit(BeginWasmFunction(parameterCount: signatureType.parameterTypes.count), withInputs: [signature])
45044514
let results = body(currentWasmFunction, instr.innerOutput(0), Array(instr.innerOutputs(1...)))
4505-
return b.emit(EndWasmFunction(signature: signature), withInputs: results).output
4515+
return b.emit(EndWasmFunction(outputCount: signatureType.outputTypes.count), withInputs: [signature] + results, types: [.wasmTypeDef()] + signatureType.outputTypes).output
45064516
}
45074517

45084518
@discardableResult
@@ -5022,8 +5032,8 @@ public class ProgramBuilder {
50225032
break
50235033
case .wasmDefineTag(_):
50245034
break
5025-
case .beginWasmFunction(let op):
5026-
activeWasmModule!.functions.append(WasmFunction(forBuilder: self, withSignature: op.signature))
5035+
case .beginWasmFunction(_):
5036+
activeWasmModule!.functions.append(WasmFunction(forBuilder: self, signatureDef: instr.input(0)))
50275037
case .wasmBeginTry(_),
50285038
.wasmEndTryDelegate(_),
50295039
.wasmBeginTryDelegate(_),

Sources/Fuzzilli/CodeGen/WasmCodeGenerators.swift

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1276,23 +1276,25 @@ public let WasmCodeGenerators: [CodeGenerator] = [
12761276
provides: [.wasmFunction]
12771277
) { b in
12781278
let module = b.currentWasmModule
1279+
// TODO(mliedtke): Support index wasm-gc types in the signature. This requires the
1280+
// WasmDefineTable operation to track their types in a way that is compatible with
1281+
// wasm-gc types. Similarly, WasmCallIndirect and WasmReturnCallIndirect need to be
1282+
// adapted to use wasm-gc signatures.
12791283
let functionSignature = b.randomWasmSignature()
1280-
b.emit(BeginWasmFunction(signature: functionSignature))
1284+
let signatureDef = b.wasmDefineAdHocSignatureType(signature: functionSignature)
1285+
b.emit(BeginWasmFunction(parameterCount: functionSignature.parameterTypes.count), withInputs: [signatureDef])
12811286
},
12821287
GeneratorStub(
12831288
"WasmFunctionEndGenerator",
12841289
inContext: .single(.wasmFunction),
12851290
produces: [.wasmFunctionDef()]
12861291
) { b in
12871292
let function = b.currentWasmFunction
1288-
let results = function.signature.outputTypes.map {
1289-
b.randomVariable(ofType: $0) ?? b.currentWasmFunction
1290-
.generateRandomWasmVar(ofType: $0)!
1291-
}
1293+
let results = function.signature.outputTypes.map(function.findOrGenerateWasmVar)
12921294

12931295
b.emit(
1294-
EndWasmFunction(signature: function.signature),
1295-
withInputs: results)
1296+
EndWasmFunction(outputCount: results.count),
1297+
withInputs: [function.signatureDef] + results)
12961298
},
12971299
]),
12981300

Sources/Fuzzilli/FuzzIL/Instruction.swift

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,13 +1373,11 @@ extension Instruction: ProtobufConvertible {
13731373
$0.wasmDropDataSegment = Fuzzilli_Protobuf_WasmDropDataSegment()
13741374
case .beginWasmFunction(let op):
13751375
$0.beginWasmFunction = Fuzzilli_Protobuf_BeginWasmFunction.with {
1376-
$0.parameterTypes = op.signature.parameterTypes.map(ILTypeToWasmTypeEnum)
1377-
$0.outputTypes = op.signature.outputTypes.map(ILTypeToWasmTypeEnum)
1376+
$0.parameterCount = Int32(op.parameterCount)
13781377
}
13791378
case .endWasmFunction(let op):
13801379
$0.endWasmFunction = Fuzzilli_Protobuf_EndWasmFunction.with {
1381-
$0.parameterTypes = op.signature.parameterTypes.map(ILTypeToWasmTypeEnum)
1382-
$0.outputTypes = op.signature.outputTypes.map(ILTypeToWasmTypeEnum)
1380+
$0.outputCount = Int32(op.outputCount)
13831381
}
13841382
case .wasmBeginBlock(let op):
13851383
$0.wasmBeginBlock = Fuzzilli_Protobuf_WasmBeginBlock.with {
@@ -2441,13 +2439,9 @@ extension Instruction: ProtobufConvertible {
24412439
case .wasmDropDataSegment(_):
24422440
op = WasmDropDataSegment()
24432441
case .beginWasmFunction(let p):
2444-
let parameters = p.parameterTypes.map(WasmTypeEnumToILType)
2445-
let outputs = p.outputTypes.map(WasmTypeEnumToILType)
2446-
op = BeginWasmFunction(signature: parameters => outputs)
2442+
op = BeginWasmFunction(parameterCount: Int(p.parameterCount))
24472443
case .endWasmFunction(let p):
2448-
let parameters = p.parameterTypes.map(WasmTypeEnumToILType)
2449-
let outputs = p.outputTypes.map(WasmTypeEnumToILType)
2450-
op = EndWasmFunction(signature: parameters => outputs)
2444+
op = EndWasmFunction(outputCount: Int(p.outputCount))
24512445
case .wasmBeginBlock(let p):
24522446
op = WasmBeginBlock(parameterCount: Int(p.parameterCount))
24532447
case .wasmEndBlock(let p):

Sources/Fuzzilli/FuzzIL/JSTyper.swift

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -812,11 +812,13 @@ public struct JSTyper: Analyzer {
812812
let definingInstruction = defUseAnalyzer.definition(of: instr.input(1))
813813
// Here we query the typer for the signature of the instruction as that is the correct "JS" Signature instead of taking the call-site specific converted wasm signature.
814814
dynamicObjectGroupManager.addWasmFunction(withSignature: type(of: instr.input(1)).signature ?? Signature.forUnknownFunction, forDefinition: definingInstruction, forVariable: instr.input(1))
815-
case .beginWasmFunction(let op):
816-
wasmTypeBeginBlock(instr, op.signature)
817-
case .endWasmFunction(let op):
818-
setType(of: instr.output, to: .wasmFunctionDef(op.signature))
819-
dynamicObjectGroupManager.addWasmFunction(withSignature: ProgramBuilder.convertWasmSignatureToJsSignature(op.signature), forDefinition: instr, forVariable: instr.output)
815+
case .beginWasmFunction(_):
816+
let signature = type(of: instr.input(0)).wasmFunctionSignatureDefSignature
817+
wasmTypeBeginBlock(instr, signature)
818+
case .endWasmFunction(_):
819+
let signature = type(of: instr.input(0)).wasmFunctionSignatureDefSignature
820+
setType(of: instr.output, to: .wasmFunctionDef(signature))
821+
dynamicObjectGroupManager.addWasmFunction(withSignature: ProgramBuilder.convertWasmSignatureToJsSignature(signature), forDefinition: instr, forVariable: instr.output)
820822
case .wasmSelect(_):
821823
setType(of: instr.output, to: type(of: instr.input(0)))
822824
case .wasmBeginBlock(_):

Sources/Fuzzilli/FuzzIL/WasmOperations.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1552,22 +1552,22 @@ final class WasmReassign: WasmOperation {
15521552

15531553
final class BeginWasmFunction: WasmOperation {
15541554
override var opcode: Opcode { .beginWasmFunction(self) }
1555-
public let signature: WasmSignature
15561555

1557-
init(signature: WasmSignature) {
1558-
self.signature = signature
1559-
super.init(numInnerOutputs: 1 + signature.parameterTypes.count, attributes: [.isBlockStart], requiredContext: [.wasm], contextOpened: [.wasmFunction])
1556+
init(parameterCount: Int) {
1557+
super.init(numInputs: 1, numInnerOutputs: 1 + parameterCount, attributes: [.isBlockStart], requiredContext: [.wasm], contextOpened: [.wasmFunction])
15601558
}
1559+
1560+
var parameterCount: Int { numInnerOutputs - 1 }
15611561
}
15621562

15631563
final class EndWasmFunction: WasmOperation {
15641564
override var opcode: Opcode { .endWasmFunction(self) }
1565-
let signature: WasmSignature
15661565

1567-
init(signature: WasmSignature) {
1568-
self.signature = signature
1569-
super.init(numInputs: signature.outputTypes.count, numOutputs: 1, attributes: [.isBlockEnd], requiredContext: [.wasmFunction])
1566+
init(outputCount: Int) {
1567+
super.init(numInputs: 1 + outputCount, numOutputs: 1, attributes: [.isBlockEnd], requiredContext: [.wasmFunction])
15701568
}
1569+
1570+
var outputCount: Int { numInputs - 1 }
15711571
}
15721572

15731573
/// This class is used to indicate nops in the wasm world, this makes handling of minimization much easier.

Sources/Fuzzilli/Lifting/FuzzILLifter.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -830,9 +830,9 @@ public class FuzzILLifter: Lifter {
830830

831831
// Wasm Instructions
832832

833-
case .beginWasmFunction(let op):
833+
case .beginWasmFunction(_):
834834
// TODO(cffsmith): do this properly?
835-
w.emit("BeginWasmFunction (\(op.signature)) -> L:\(instr.innerOutput(0)) [\(liftCallArguments(instr.innerOutputs(1...)))]")
835+
w.emit("BeginWasmFunction \(input(0)) -> L:\(instr.innerOutput(0)) [\(liftCallArguments(instr.innerOutputs(1...)))]")
836836
w.increaseIndentionLevel()
837837

838838
case .endWasmFunction:

Sources/Fuzzilli/Lifting/WasmLifter.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,8 +1287,9 @@ public class WasmLifter {
12871287
// Just analyze the instruction but do nothing else here.
12881288
// This lets the typer know that we can skip this instruction without breaking any analysis.
12891289
break
1290-
case .beginWasmFunction(let op):
1291-
let functionInfo = FunctionInfo(op.signature, Data(), for: self, withArguments: Array(instr.innerOutputs))
1290+
case .beginWasmFunction(_):
1291+
let signature = typer.type(of: instr.input(0)).wasmFunctionSignatureDefSignature
1292+
let functionInfo = FunctionInfo(signature, Data(), for: self, withArguments: Array(instr.innerOutputs))
12921293
self.exports.append(.function(functionInfo))
12931294
// Set the current active function as we are *actively* in it.
12941295
currentFunction = functionInfo

Sources/Fuzzilli/Protobuf/operations.pb.swift

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4180,9 +4180,7 @@ public struct Fuzzilli_Protobuf_BeginWasmFunction: Sendable {
41804180
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
41814181
// methods supported on all messages.
41824182

4183-
public var parameterTypes: [Fuzzilli_Protobuf_WasmILType] = []
4184-
4185-
public var outputTypes: [Fuzzilli_Protobuf_WasmILType] = []
4183+
public var parameterCount: Int32 = 0
41864184

41874185
public var unknownFields = SwiftProtobuf.UnknownStorage()
41884186

@@ -4194,9 +4192,7 @@ public struct Fuzzilli_Protobuf_EndWasmFunction: Sendable {
41944192
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
41954193
// methods supported on all messages.
41964194

4197-
public var parameterTypes: [Fuzzilli_Protobuf_WasmILType] = []
4198-
4199-
public var outputTypes: [Fuzzilli_Protobuf_WasmILType] = []
4195+
public var outputCount: Int32 = 0
42004196

42014197
public var unknownFields = SwiftProtobuf.UnknownStorage()
42024198

@@ -11689,69 +11685,59 @@ extension Fuzzilli_Protobuf_WasmILType: SwiftProtobuf.Message, SwiftProtobuf._Me
1168911685

1169011686
extension Fuzzilli_Protobuf_BeginWasmFunction: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
1169111687
public static let protoMessageName: String = _protobuf_package + ".BeginWasmFunction"
11692-
public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}parameterTypes\0\u{1}outputTypes\0")
11688+
public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}parameterCount\0")
1169311689

1169411690
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
1169511691
while let fieldNumber = try decoder.nextFieldNumber() {
1169611692
// The use of inline closures is to circumvent an issue where the compiler
1169711693
// allocates stack space for every case branch when no optimizations are
1169811694
// enabled. https://github.com/apple/swift-protobuf/issues/1034
1169911695
switch fieldNumber {
11700-
case 1: try { try decoder.decodeRepeatedMessageField(value: &self.parameterTypes) }()
11701-
case 2: try { try decoder.decodeRepeatedMessageField(value: &self.outputTypes) }()
11696+
case 1: try { try decoder.decodeSingularInt32Field(value: &self.parameterCount) }()
1170211697
default: break
1170311698
}
1170411699
}
1170511700
}
1170611701

1170711702
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
11708-
if !self.parameterTypes.isEmpty {
11709-
try visitor.visitRepeatedMessageField(value: self.parameterTypes, fieldNumber: 1)
11710-
}
11711-
if !self.outputTypes.isEmpty {
11712-
try visitor.visitRepeatedMessageField(value: self.outputTypes, fieldNumber: 2)
11703+
if self.parameterCount != 0 {
11704+
try visitor.visitSingularInt32Field(value: self.parameterCount, fieldNumber: 1)
1171311705
}
1171411706
try unknownFields.traverse(visitor: &visitor)
1171511707
}
1171611708

1171711709
public static func ==(lhs: Fuzzilli_Protobuf_BeginWasmFunction, rhs: Fuzzilli_Protobuf_BeginWasmFunction) -> Bool {
11718-
if lhs.parameterTypes != rhs.parameterTypes {return false}
11719-
if lhs.outputTypes != rhs.outputTypes {return false}
11710+
if lhs.parameterCount != rhs.parameterCount {return false}
1172011711
if lhs.unknownFields != rhs.unknownFields {return false}
1172111712
return true
1172211713
}
1172311714
}
1172411715

1172511716
extension Fuzzilli_Protobuf_EndWasmFunction: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
1172611717
public static let protoMessageName: String = _protobuf_package + ".EndWasmFunction"
11727-
public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}parameterTypes\0\u{1}outputTypes\0")
11718+
public static let _protobuf_nameMap = SwiftProtobuf._NameMap(bytecode: "\0\u{1}outputCount\0")
1172811719

1172911720
public mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
1173011721
while let fieldNumber = try decoder.nextFieldNumber() {
1173111722
// The use of inline closures is to circumvent an issue where the compiler
1173211723
// allocates stack space for every case branch when no optimizations are
1173311724
// enabled. https://github.com/apple/swift-protobuf/issues/1034
1173411725
switch fieldNumber {
11735-
case 1: try { try decoder.decodeRepeatedMessageField(value: &self.parameterTypes) }()
11736-
case 2: try { try decoder.decodeRepeatedMessageField(value: &self.outputTypes) }()
11726+
case 1: try { try decoder.decodeSingularInt32Field(value: &self.outputCount) }()
1173711727
default: break
1173811728
}
1173911729
}
1174011730
}
1174111731

1174211732
public func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
11743-
if !self.parameterTypes.isEmpty {
11744-
try visitor.visitRepeatedMessageField(value: self.parameterTypes, fieldNumber: 1)
11745-
}
11746-
if !self.outputTypes.isEmpty {
11747-
try visitor.visitRepeatedMessageField(value: self.outputTypes, fieldNumber: 2)
11733+
if self.outputCount != 0 {
11734+
try visitor.visitSingularInt32Field(value: self.outputCount, fieldNumber: 1)
1174811735
}
1174911736
try unknownFields.traverse(visitor: &visitor)
1175011737
}
1175111738

1175211739
public static func ==(lhs: Fuzzilli_Protobuf_EndWasmFunction, rhs: Fuzzilli_Protobuf_EndWasmFunction) -> Bool {
11753-
if lhs.parameterTypes != rhs.parameterTypes {return false}
11754-
if lhs.outputTypes != rhs.outputTypes {return false}
11740+
if lhs.outputCount != rhs.outputCount {return false}
1175511741
if lhs.unknownFields != rhs.unknownFields {return false}
1175611742
return true
1175711743
}

Sources/Fuzzilli/Protobuf/operations.proto

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -929,13 +929,11 @@ message WasmILType {
929929
}
930930

931931
message BeginWasmFunction {
932-
repeated WasmILType parameterTypes = 1;
933-
repeated WasmILType outputTypes = 2;
932+
int32 parameterCount = 1;
934933
}
935934

936935
message EndWasmFunction {
937-
repeated WasmILType parameterTypes = 1;
938-
repeated WasmILType outputTypes = 2;
936+
int32 outputCount = 1;
939937
}
940938

941939
message WasmJsCall {

Tests/FuzzilliTests/MinimizerTest.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1592,7 +1592,7 @@ class MinimizerTests: XCTestCase {
15921592
} catchAllBody: { label in
15931593
function.wasmReturn(function.consti64(-1))
15941594
}
1595-
return [function.consti32(-1)]
1595+
return [function.consti64(-1)]
15961596
}
15971597
}
15981598

@@ -1602,7 +1602,7 @@ class MinimizerTests: XCTestCase {
16021602
function.wasmBuildLegacyTryVoid { label in
16031603
function.wasmReturn(function.consti64(42))
16041604
}
1605-
return [function.consti32(-1)]
1605+
return [function.consti64(-1)]
16061606
}
16071607
}
16081608
}
@@ -1628,7 +1628,7 @@ class MinimizerTests: XCTestCase {
16281628
function.wasmReturn(val)
16291629
}),
16301630
(tag: irrelevantTag, body: { _, _, _ in })])
1631-
return [function.consti32(-1)]
1631+
return [function.consti64(-1)]
16321632
}
16331633
}
16341634

@@ -1642,7 +1642,7 @@ class MinimizerTests: XCTestCase {
16421642
}, catchClauses: [(tag: tag, body: { _, _, _ in
16431643
function.wasmReturn(function.consti64(42))
16441644
})])
1645-
return [function.consti32(-1)]
1645+
return [function.consti64(-1)]
16461646
}
16471647
}
16481648
}
@@ -1659,15 +1659,15 @@ class MinimizerTests: XCTestCase {
16591659
evaluator.nextInstructionIsImportant(in: b)
16601660
function.wasmReturn(val)
16611661
}, catchClauses: [(tag: tag, body: { _, _, _ in function.wasmUnreachable() })])
1662-
return [function.consti32(-1)]
1662+
return [function.consti64(-1)]
16631663
}
16641664
}
16651665

16661666
} minified: { b in
16671667
return b.buildWasmModule { wasmModule in
16681668
wasmModule.addWasmFunction(with: [] => [.wasmi64]) { function, _, _ in
16691669
function.wasmReturn(function.consti64(42))
1670-
return [function.consti32(-1)]
1670+
return [function.consti64(-1)]
16711671
}
16721672
}
16731673
}

0 commit comments

Comments
 (0)