Skip to content

Commit a350d0f

Browse files
Doga YükselV8-internal LUCI CQ
authored andcommitted
[wasm] Added ref.cast instruction
Fuzzilli functionality for ref.cast added similarly to ref.test Bug: 474940922 Change-Id: I7cd3a28b05b7289c8ea0836be0c6d1024556e24c Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/8995238 Commit-Queue: Doga Yüksel <dyuksel@google.com> Reviewed-by: Danylo Mocherniuk <mdanylo@google.com> Reviewed-by: Matthias Liedtke <mliedtke@google.com>
1 parent 8092333 commit a350d0f

16 files changed

Lines changed: 268 additions & 12 deletions

Sources/Fuzzilli/Base/ProgramBuilder.swift

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4436,10 +4436,18 @@ public class ProgramBuilder {
44364436

44374437
@discardableResult
44384438
public func wasmRefTest(_ ref: Variable, refType: ILType, typeDef: Variable? = nil) -> Variable {
4439-
typeDef == nil
4440-
? b.emit(WasmRefTest(refType: refType), withInputs: [ref]).output
4441-
: b.emit(WasmRefTest(refType: refType), withInputs: [ref, typeDef!]).output
4439+
let inputs = typeDef == nil ? [ref] : [ref, typeDef!]
4440+
let types: [ILType] = typeDef == nil ? [.wasmGenericRef] : [.wasmGenericRef, .wasmTypeDef()]
4441+
return b.emit(WasmRefTest(refType: refType), withInputs: inputs, types: types).output
44424442
}
4443+
4444+
@discardableResult
4445+
public func wasmRefCast(_ ref: Variable, refType: ILType, typeDef: Variable? = nil) -> Variable {
4446+
let inputs = typeDef == nil ? [ref] : [ref, typeDef!]
4447+
let types: [ILType] = typeDef == nil ? [.wasmGenericRef] : [.wasmGenericRef, .wasmTypeDef()]
4448+
return b.emit(WasmRefCast(refType: refType), withInputs: inputs, types: types).output
4449+
}
4450+
44434451
}
44444452

44454453
public class WasmModule {

Sources/Fuzzilli/CodeGen/CodeGeneratorWeights.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,4 +381,6 @@ public let codeGeneratorWeights = [
381381
"WasmExternConvertAnyGenerator": 5,
382382
"WasmRefTestGenerator": 5,
383383
"WasmRefTestAbstractGenerator": 5,
384+
"WasmRefCastGenerator": 5,
385+
"WasmRefCastAbstractGenerator": 5,
384386
]

Sources/Fuzzilli/CodeGen/WasmCodeGenerators.swift

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,56 @@ public let WasmCodeGenerators: [CodeGenerator] = [
387387
)
388388
},
389389

390+
CodeGenerator(
391+
"WasmRefCastGenerator", inContext: .single(.wasmFunction),
392+
inputs: .requiredComplex(.init(.wasmTypeDef())),
393+
produces: [.wasmGenericRef]
394+
) { b, typeDef in
395+
guard let abstractType =
396+
b.type(of: typeDef).wasmTypeDefinition?.description?.abstractHeapSupertype?.heapType
397+
as? WasmAbstractHeapType
398+
else { fatalError("Invalid type description for \(b.type(of: typeDef))") }
399+
let function = b.currentWasmModule.currentWasmFunction
400+
let variable = switch abstractType {
401+
case .WasmFunc, .WasmNoFunc:
402+
function.findOrGenerateWasmVar(ofType: .wasmFuncRef())
403+
case .WasmArray, .WasmStruct:
404+
function.findOrGenerateWasmVar(ofType: .wasmAnyRef())
405+
default:
406+
fatalError("The type \(abstractType) shouldn't have a definition")
407+
}
408+
let refType = ILType.wasmRef(.Index(), nullability: Bool.random())
409+
function.wasmRefCast(variable, refType: refType, typeDef: typeDef)
410+
},
411+
412+
CodeGenerator(
413+
"WasmRefCastAbstractGenerator", inContext: .single(.wasmFunction),
414+
inputs: .required(.wasmGenericRef),
415+
produces: [.wasmGenericRef]
416+
) { b, ref in
417+
let function = b.currentWasmModule.currentWasmFunction
418+
let heapType = switch b.type(of: ref).wasmReferenceType!.kind {
419+
case .Abstract(let heapTypeInfo):
420+
heapTypeInfo.heapType
421+
case .Index(let desc):
422+
desc.get()!.abstractHeapSupertype!.heapType
423+
}
424+
let incompatible: [WasmAbstractHeapType] = [.WasmStruct, .WasmArray, .WasmI31]
425+
let chosenType = chooseUniform(
426+
from: WasmAbstractHeapType.allCases.filter {
427+
$0 != heapType &&
428+
$0.inSameHierarchy(heapType) &&
429+
( // 90% of the time it won't contain two incompatible types
430+
probability(0.1) ||
431+
!(incompatible.contains($0) && incompatible.contains(heapType))
432+
)
433+
}
434+
)
435+
// TODO(pawkra): add shared variant.
436+
let newType = ILType.wasmRef(.Abstract(HeapTypeInfo(chosenType, shared: false)), nullability: Bool.random())
437+
function.wasmRefCast(ref, refType: newType)
438+
},
439+
390440
// Primitive Value Generators
391441

392442
CodeGenerator(

Sources/Fuzzilli/FuzzIL/Instruction.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1615,6 +1615,10 @@ extension Instruction: ProtobufConvertible {
16151615
$0.wasmRefTest = Fuzzilli_Protobuf_WasmRefTest.with {
16161616
$0.type = ILTypeToWasmTypeEnum(op.type)
16171617
}
1618+
case .wasmRefCast(let op):
1619+
$0.wasmRefCast = Fuzzilli_Protobuf_WasmRefCast.with {
1620+
$0.type = ILTypeToWasmTypeEnum(op.type)
1621+
}
16181622
case .wasmRefI31(let op):
16191623
$0.wasmRefI31 = Fuzzilli_Protobuf_WasmRefI31.with {
16201624
$0.isShared = op.isShared
@@ -2594,6 +2598,8 @@ extension Instruction: ProtobufConvertible {
25942598
op = WasmRefEq()
25952599
case .wasmRefTest(let p):
25962600
op = WasmRefTest(refType: WasmTypeEnumToILType(p.type))
2601+
case .wasmRefCast(let p):
2602+
op = WasmRefCast(refType: WasmTypeEnumToILType(p.type))
25972603
case .wasmRefI31(let p):
25982604
op = WasmRefI31(isShared: p.isShared)
25992605
case .wasmI31Get(let p):

Sources/Fuzzilli/FuzzIL/JSTyper.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,13 @@ public struct JSTyper: Analyzer {
949949
setType(of: instr.output, to: .wasmi32)
950950
case .wasmRefTest(_):
951951
setType(of: instr.output, to: .wasmi32)
952+
case .wasmRefCast(let op):
953+
if op.type.requiredInputCount() == 1 {
954+
let nullable = op.type.wasmReferenceType!.nullability
955+
setReferenceType(of: instr.output, typeDef: instr.input(1), nullability: nullable)
956+
} else {
957+
setType(of: instr.output, to: op.type)
958+
}
952959
case .wasmAnyConvertExtern(_):
953960
// TODO(pawkra): forward shared bit & update the comment
954961
// any.convert_extern forwards the nullability bit from the input.

Sources/Fuzzilli/FuzzIL/Opcodes.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,4 +368,5 @@ enum Opcode {
368368
case wasmRefEq(WasmRefEq)
369369
case wasmRefTest(WasmRefTest)
370370
case wasmDefineAdHocModuleSignatureType(WasmDefineAdHocModuleSignatureType)
371+
case wasmRefCast(WasmRefCast)
371372
}

Sources/Fuzzilli/FuzzIL/WasmOperations.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2336,6 +2336,15 @@ class WasmRefTest: WasmOperation {
23362336
}
23372337
}
23382338

2339+
class WasmRefCast: WasmOperation {
2340+
override var opcode: Opcode { .wasmRefCast(self) }
2341+
let type: ILType
2342+
init(refType: ILType) {
2343+
self.type = refType
2344+
super.init(numInputs: 1 + type.requiredInputCount(), numOutputs: 1, requiredContext: [.wasmFunction])
2345+
}
2346+
}
2347+
23392348
/// An atomic load from Wasm memory.
23402349
/// The accessed address is base + offset.
23412350
final class WasmAtomicLoad: WasmOperation {

Sources/Fuzzilli/Lifting/FuzzILLifter.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,6 +1349,10 @@ public class FuzzILLifter: Lifter {
13491349
let typeInput = op.type.requiredInputCount() > 0 ? " (IndexType: \(input(1)))" : ""
13501350
w.emit("\(output()) <- WasmRefTest \(op.type) \(input(0))\(typeInput)")
13511351

1352+
case .wasmRefCast(let op):
1353+
let typeInput = op.type.requiredInputCount() > 0 ? " (IndexType: \(input(1)))" : ""
1354+
w.emit("\(output()) <- WasmRefCast \(op.type) \(input(0))\(typeInput)")
1355+
13521356
case .wasmBeginTypeGroup(_):
13531357
w.emit("WasmBeginTypeGroup")
13541358
w.increaseIndentionLevel()

Sources/Fuzzilli/Lifting/JavaScriptLifter.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1795,7 +1795,8 @@ public class JavaScriptLifter: Lifter {
17951795
.wasmI31Get(_),
17961796
.wasmAnyConvertExtern(_),
17971797
.wasmExternConvertAny(_),
1798-
.wasmRefTest(_):
1798+
.wasmRefTest(_),
1799+
.wasmRefCast(_):
17991800
fatalError("unreachable")
18001801
}
18011802

Sources/Fuzzilli/Lifting/WasmLifter.swift

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,16 @@ public class WasmLifter {
584584
fatalError("This function supports only wasmReferenceType.")
585585
}
586586

587+
// Helper method in cases we have either abstract type represented by ILType or an index type Variable
588+
private func encodeReferenceType(_ refType: WasmReferenceType, instr: Instruction, typeInput: Int) throws -> Data {
589+
switch refType.kind {
590+
case .Abstract(let heapTypeInfo):
591+
return encodeAbstractHeapType(heapTypeInfo)
592+
case .Index(_):
593+
return try encodeWasmGCType(typer.getTypeDescription(of: instr.input(typeInput)))
594+
}
595+
}
596+
587597
private func buildTypeEntry(for desc: WasmTypeDescription, data: inout Data) throws {
588598
if let arrayDesc = desc as? WasmArrayTypeDescription {
589599
data += [0x5E]
@@ -2200,13 +2210,13 @@ public class WasmLifter {
22002210
case .wasmRefTest(let op):
22012211
let refType = op.type.wasmReferenceType!
22022212
let opCode: UInt8 = refType.nullability ? 0x15 : 0x14
2203-
let typeData = if refType.isAbstract() {
2204-
try encodeHeapType(op.type)
2205-
} else {
2206-
try encodeWasmGCType(typer.getTypeDescription(of: wasmInstruction.input(1)))
2207-
}
2213+
let typeData = try encodeReferenceType(refType, instr: wasmInstruction, typeInput: 1)
2214+
return Data([Prefix.GC.rawValue, opCode]) + typeData
2215+
case .wasmRefCast(let op):
2216+
let refType = op.type.wasmReferenceType!
2217+
let opCode: UInt8 = refType.nullability ? 0x17 : 0x16
2218+
let typeData = try encodeReferenceType(refType, instr: wasmInstruction, typeInput: 1)
22082219
return Data([Prefix.GC.rawValue, opCode]) + typeData
2209-
22102220
case .wasmDefineAdHocSignatureType(_):
22112221
// Nothing to do here, types are defined inside the typegroups, not inside a wasm
22122222
// function.

0 commit comments

Comments
 (0)