[DFG] Added type to some operations
* Array read/write * Fields read/write * Calls
This commit is contained in:
+4
-1
@@ -98,12 +98,13 @@ internal class CallGraphBuilder(val context: Context,
|
|||||||
is DataFlowIR.Node.Call -> block(node)
|
is DataFlowIR.Node.Call -> block(node)
|
||||||
|
|
||||||
is DataFlowIR.Node.Singleton ->
|
is DataFlowIR.Node.Singleton ->
|
||||||
node.constructor?.let { block(DataFlowIR.Node.Call(it, emptyList(), null)) }
|
node.constructor?.let { block(DataFlowIR.Node.Call(it, emptyList(), node.type, null)) }
|
||||||
|
|
||||||
is DataFlowIR.Node.ArrayRead ->
|
is DataFlowIR.Node.ArrayRead ->
|
||||||
block(DataFlowIR.Node.Call(
|
block(DataFlowIR.Node.Call(
|
||||||
callee = moduleDFG.symbolTable.mapFunction(arrayGet),
|
callee = moduleDFG.symbolTable.mapFunction(arrayGet),
|
||||||
arguments = listOf(node.array, node.index),
|
arguments = listOf(node.array, node.index),
|
||||||
|
returnType = node.type,
|
||||||
irCallSite = null)
|
irCallSite = null)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -111,6 +112,7 @@ internal class CallGraphBuilder(val context: Context,
|
|||||||
block(DataFlowIR.Node.Call(
|
block(DataFlowIR.Node.Call(
|
||||||
callee = moduleDFG.symbolTable.mapFunction(arraySet),
|
callee = moduleDFG.symbolTable.mapFunction(arraySet),
|
||||||
arguments = listOf(node.array, node.index, node.value),
|
arguments = listOf(node.array, node.index, node.value),
|
||||||
|
returnType = moduleDFG.symbolTable.mapType(context.irBuiltIns.unitType),
|
||||||
irCallSite = null)
|
irCallSite = null)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -118,6 +120,7 @@ internal class CallGraphBuilder(val context: Context,
|
|||||||
block(DataFlowIR.Node.Call(
|
block(DataFlowIR.Node.Call(
|
||||||
callee = node.symbol,
|
callee = node.symbol,
|
||||||
arguments = emptyList(),
|
arguments = emptyList(),
|
||||||
|
returnType = node.symbol.returnParameter.type,
|
||||||
irCallSite = null
|
irCallSite = null
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|||||||
+33
-6
@@ -514,6 +514,17 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
)
|
)
|
||||||
else DataFlowIR.Edge(getNode(expression), null)
|
else DataFlowIR.Edge(getNode(expression), null)
|
||||||
|
|
||||||
|
private fun mapReturnType(actualType: IrType, returnType: IrType): DataFlowIR.Type {
|
||||||
|
val returnedInlinedClass = returnType.getInlinedClassNative()
|
||||||
|
val actualInlinedClass = actualType.getInlinedClassNative()
|
||||||
|
|
||||||
|
return if (returnedInlinedClass == null) {
|
||||||
|
if (actualInlinedClass == null) symbolTable.mapType(actualType) else symbolTable.mapClassReferenceType(actualInlinedClass)
|
||||||
|
} else {
|
||||||
|
symbolTable.mapType(returnType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun getNode(expression: IrExpression): DataFlowIR.Node {
|
private fun getNode(expression: IrExpression): DataFlowIR.Node {
|
||||||
if (expression is IrGetValue) {
|
if (expression is IrGetValue) {
|
||||||
val valueDeclaration = expression.symbol.owner
|
val valueDeclaration = expression.symbol.owner
|
||||||
@@ -554,7 +565,10 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
|
|
||||||
is IrFunctionReference -> {
|
is IrFunctionReference -> {
|
||||||
val callee = value.symbol.owner
|
val callee = value.symbol.owner
|
||||||
DataFlowIR.Node.FunctionReference(symbolTable.mapFunction(callee), symbolTable.mapType(value.type))
|
DataFlowIR.Node.FunctionReference(
|
||||||
|
symbolTable.mapFunction(callee),
|
||||||
|
symbolTable.mapType(value.type),
|
||||||
|
/*TODO: substitute*/symbolTable.mapType(callee.returnType))
|
||||||
}
|
}
|
||||||
|
|
||||||
is IrConst<*> ->
|
is IrConst<*> ->
|
||||||
@@ -584,11 +598,17 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
is IrCall -> when (value.symbol) {
|
is IrCall -> when (value.symbol) {
|
||||||
getContinuationSymbol -> getContinuation()
|
getContinuationSymbol -> getContinuation()
|
||||||
|
|
||||||
arrayGetSymbol -> DataFlowIR.Node.ArrayRead(expressionToEdge(value.dispatchReceiver!!),
|
arrayGetSymbol -> DataFlowIR.Node.ArrayRead(
|
||||||
expressionToEdge(value.getValueArgument(0)!!), value)
|
array = expressionToEdge(value.dispatchReceiver!!),
|
||||||
|
index = expressionToEdge(value.getValueArgument(0)!!),
|
||||||
|
type = mapReturnType(value.type, context.irBuiltIns.anyType),
|
||||||
|
irCallSite = value)
|
||||||
|
|
||||||
arraySetSymbol -> DataFlowIR.Node.ArrayWrite(expressionToEdge(value.dispatchReceiver!!),
|
arraySetSymbol -> DataFlowIR.Node.ArrayWrite(
|
||||||
expressionToEdge(value.getValueArgument(0)!!), expressionToEdge(value.getValueArgument(1)!!))
|
array = expressionToEdge(value.dispatchReceiver!!),
|
||||||
|
index = expressionToEdge(value.getValueArgument(0)!!),
|
||||||
|
value = expressionToEdge(value.getValueArgument(1)!!),
|
||||||
|
type = mapReturnType(value.getValueArgument(1)!!.type, context.irBuiltIns.anyType))
|
||||||
|
|
||||||
createUninitializedInstanceSymbol ->
|
createUninitializedInstanceSymbol ->
|
||||||
DataFlowIR.Node.AllocInstance(symbolTable.mapClassReferenceType(
|
DataFlowIR.Node.AllocInstance(symbolTable.mapClassReferenceType(
|
||||||
@@ -606,6 +626,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
symbolTable.mapFunction(callee),
|
symbolTable.mapFunction(callee),
|
||||||
arguments,
|
arguments,
|
||||||
symbolTable.mapClassReferenceType(callee.constructedClass),
|
symbolTable.mapClassReferenceType(callee.constructedClass),
|
||||||
|
symbolTable.mapClassReferenceType(symbols.unit.owner),
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -652,6 +673,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
receiverType,
|
receiverType,
|
||||||
calleeHash,
|
calleeHash,
|
||||||
arguments,
|
arguments,
|
||||||
|
mapReturnType(value.type, callee.target.returnType),
|
||||||
value
|
value
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@@ -661,6 +683,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
receiverType,
|
receiverType,
|
||||||
vtableIndex,
|
vtableIndex,
|
||||||
arguments,
|
arguments,
|
||||||
|
mapReturnType(value.type, callee.target.returnType),
|
||||||
value
|
value
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -670,6 +693,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
symbolTable.mapFunction(actualCallee),
|
symbolTable.mapFunction(actualCallee),
|
||||||
arguments,
|
arguments,
|
||||||
actualCallee.dispatchReceiverParameter?.let { symbolTable.mapType(it.type) },
|
actualCallee.dispatchReceiverParameter?.let { symbolTable.mapType(it.type) },
|
||||||
|
mapReturnType(value.type, actualCallee.returnType),
|
||||||
value
|
value
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -686,6 +710,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
symbolTable.mapFunction(value.symbol.owner),
|
symbolTable.mapFunction(value.symbol.owner),
|
||||||
arguments.map { expressionToEdge(it) },
|
arguments.map { expressionToEdge(it) },
|
||||||
symbolTable.mapType(thiz.type),
|
symbolTable.mapType(thiz.type),
|
||||||
|
symbolTable.mapClassReferenceType(symbols.unit.owner),
|
||||||
value
|
value
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -702,6 +727,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
name.localHash.value,
|
name.localHash.value,
|
||||||
takeName { name }
|
takeName { name }
|
||||||
),
|
),
|
||||||
|
mapReturnType(value.type, value.symbol.owner.type),
|
||||||
value
|
value
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -718,7 +744,8 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
name.localHash.value,
|
name.localHash.value,
|
||||||
takeName { name }
|
takeName { name }
|
||||||
),
|
),
|
||||||
expressionToEdge(value.value)
|
expressionToEdge(value.value),
|
||||||
|
mapReturnType(value.value.type, value.symbol.owner.type)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+45
-34
@@ -451,13 +451,14 @@ internal object DFGSerializer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Call(val callee: Int, val arguments: Array<Edge>) {
|
class Call(val callee: Int, val arguments: Array<Edge>, val returnType: Int) {
|
||||||
|
|
||||||
constructor(data: ArraySlice) : this(data.readInt(), data.readArray { Edge(this) })
|
constructor(data: ArraySlice) : this(data.readInt(), data.readArray { Edge(this) }, data.readInt())
|
||||||
|
|
||||||
fun write(result: ArraySlice) {
|
fun write(result: ArraySlice) {
|
||||||
result.writeInt(callee)
|
result.writeInt(callee)
|
||||||
result.writeArray(arguments) { it.write(this) }
|
result.writeArray(arguments) { it.write(this) }
|
||||||
|
result.writeInt(returnType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,55 +531,60 @@ internal object DFGSerializer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FunctionReference(val symbol: Int, val type: Int) {
|
class FunctionReference(val symbol: Int, val type: Int, val returnType: Int) {
|
||||||
|
|
||||||
constructor(data: ArraySlice) : this(data.readInt(), data.readInt())
|
constructor(data: ArraySlice) : this(data.readInt(), data.readInt(), data.readInt())
|
||||||
|
|
||||||
fun write(result: ArraySlice) {
|
fun write(result: ArraySlice) {
|
||||||
result.writeInt(symbol)
|
result.writeInt(symbol)
|
||||||
result.writeInt(type)
|
result.writeInt(type)
|
||||||
|
result.writeInt(returnType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FieldRead(val receiver: Edge?, val field: Field) {
|
class FieldRead(val receiver: Edge?, val field: Field, val type: Int) {
|
||||||
|
|
||||||
constructor(data: ArraySlice) : this(data.readNullable { Edge(this) }, Field(data))
|
constructor(data: ArraySlice) : this(data.readNullable { Edge(this) }, Field(data), data.readInt())
|
||||||
|
|
||||||
fun write(result: ArraySlice) {
|
fun write(result: ArraySlice) {
|
||||||
result.writeNullable(receiver) { it.write(this) }
|
result.writeNullable(receiver) { it.write(this) }
|
||||||
field.write(result)
|
field.write(result)
|
||||||
|
result.writeInt(type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FieldWrite(val receiver: Edge?, val field: Field, val value: Edge) {
|
class FieldWrite(val receiver: Edge?, val field: Field, val value: Edge, val type: Int) {
|
||||||
|
|
||||||
constructor(data: ArraySlice) : this(data.readNullable { Edge(this) }, Field(data), Edge(data))
|
constructor(data: ArraySlice) : this(data.readNullable { Edge(this) }, Field(data), Edge(data), data.readInt())
|
||||||
|
|
||||||
fun write(result: ArraySlice) {
|
fun write(result: ArraySlice) {
|
||||||
result.writeNullable(receiver) { it.write(this) }
|
result.writeNullable(receiver) { it.write(this) }
|
||||||
field.write(result)
|
field.write(result)
|
||||||
value.write(result)
|
value.write(result)
|
||||||
|
result.writeInt(type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ArrayRead(val array: Edge, val index: Edge) {
|
class ArrayRead(val array: Edge, val index: Edge, val type: Int) {
|
||||||
|
|
||||||
constructor(data: ArraySlice) : this(Edge(data), Edge(data))
|
constructor(data: ArraySlice) : this(Edge(data), Edge(data), data.readInt())
|
||||||
|
|
||||||
fun write(result: ArraySlice) {
|
fun write(result: ArraySlice) {
|
||||||
array.write(result)
|
array.write(result)
|
||||||
index.write(result)
|
index.write(result)
|
||||||
|
result.writeInt(type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ArrayWrite(val array: Edge, val index: Edge, val value: Edge) {
|
class ArrayWrite(val array: Edge, val index: Edge, val value: Edge, val type: Int) {
|
||||||
|
|
||||||
constructor(data: ArraySlice) : this(Edge(data), Edge(data), Edge(data))
|
constructor(data: ArraySlice) : this(Edge(data), Edge(data), Edge(data), data.readInt())
|
||||||
|
|
||||||
fun write(result: ArraySlice) {
|
fun write(result: ArraySlice) {
|
||||||
array.write(result)
|
array.write(result)
|
||||||
index.write(result)
|
index.write(result)
|
||||||
value.write(result)
|
value.write(result)
|
||||||
|
result.writeInt(type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -693,20 +699,20 @@ internal object DFGSerializer {
|
|||||||
fun allocInst(type: Int) =
|
fun allocInst(type: Int) =
|
||||||
Node().also { it.allocInstance = AllocInstance(type) }
|
Node().also { it.allocInstance = AllocInstance(type) }
|
||||||
|
|
||||||
fun functionReference(symbol: Int, type: Int) =
|
fun functionReference(symbol: Int, type: Int, returnType: Int) =
|
||||||
Node().also { it.functionReference = FunctionReference(symbol, type) }
|
Node().also { it.functionReference = FunctionReference(symbol, type, returnType) }
|
||||||
|
|
||||||
fun fieldRead(receiver: Edge?, field: Field) =
|
fun fieldRead(receiver: Edge?, field: Field, type: Int) =
|
||||||
Node().also { it.fieldRead = FieldRead(receiver, field) }
|
Node().also { it.fieldRead = FieldRead(receiver, field, type) }
|
||||||
|
|
||||||
fun fieldWrite(receiver: Edge?, field: Field, value: Edge) =
|
fun fieldWrite(receiver: Edge?, field: Field, value: Edge, type: Int) =
|
||||||
Node().also { it.fieldWrite = FieldWrite(receiver, field, value) }
|
Node().also { it.fieldWrite = FieldWrite(receiver, field, value, type) }
|
||||||
|
|
||||||
fun arrayRead(array: Edge, index: Edge) =
|
fun arrayRead(array: Edge, index: Edge, type: Int) =
|
||||||
Node().also { it.arrayRead = ArrayRead(array, index) }
|
Node().also { it.arrayRead = ArrayRead(array, index, type) }
|
||||||
|
|
||||||
fun arrayWrite(array: Edge, index: Edge, value: Edge) =
|
fun arrayWrite(array: Edge, index: Edge, value: Edge, type: Int) =
|
||||||
Node().also { it.arrayWrite = ArrayWrite(array, index, value) }
|
Node().also { it.arrayWrite = ArrayWrite(array, index, value, type) }
|
||||||
|
|
||||||
fun variable(values: Array<Edge>, type: Int, kind: DataFlowIR.VariableKind) =
|
fun variable(values: Array<Edge>, type: Int, kind: DataFlowIR.VariableKind) =
|
||||||
Node().also { it.variable = Variable(values, type, kind.ordinal.toByte()) }
|
Node().also { it.variable = Variable(values, type, kind.ordinal.toByte()) }
|
||||||
@@ -897,7 +903,8 @@ internal object DFGSerializer {
|
|||||||
fun buildCall(call: DataFlowIR.Node.Call) =
|
fun buildCall(call: DataFlowIR.Node.Call) =
|
||||||
Call(
|
Call(
|
||||||
functionSymbolMap[call.callee]!!,
|
functionSymbolMap[call.callee]!!,
|
||||||
call.arguments.map { buildEdge(it) }.toTypedArray()
|
call.arguments.map { buildEdge(it) }.toTypedArray(),
|
||||||
|
typeMap[call.returnType]!!
|
||||||
)
|
)
|
||||||
|
|
||||||
fun buildVirtualCall(virtualCall: DataFlowIR.Node.VirtualCall) =
|
fun buildVirtualCall(virtualCall: DataFlowIR.Node.VirtualCall) =
|
||||||
@@ -932,19 +939,19 @@ internal object DFGSerializer {
|
|||||||
Node.allocInst(typeMap[node.type]!!)
|
Node.allocInst(typeMap[node.type]!!)
|
||||||
|
|
||||||
is DataFlowIR.Node.FunctionReference ->
|
is DataFlowIR.Node.FunctionReference ->
|
||||||
Node.functionReference(functionSymbolMap[node.symbol]!!, typeMap[node.type]!!)
|
Node.functionReference(functionSymbolMap[node.symbol]!!, typeMap[node.type]!!, typeMap[node.returnType]!!)
|
||||||
|
|
||||||
is DataFlowIR.Node.FieldRead ->
|
is DataFlowIR.Node.FieldRead ->
|
||||||
Node.fieldRead(node.receiver?.let { buildEdge(it) }, buildField(node.field))
|
Node.fieldRead(node.receiver?.let { buildEdge(it) }, buildField(node.field), typeMap[node.type]!!)
|
||||||
|
|
||||||
is DataFlowIR.Node.FieldWrite ->
|
is DataFlowIR.Node.FieldWrite ->
|
||||||
Node.fieldWrite(node.receiver?.let { buildEdge(it) }, buildField(node.field), buildEdge(node.value))
|
Node.fieldWrite(node.receiver?.let { buildEdge(it) }, buildField(node.field), buildEdge(node.value), typeMap[node.type]!!)
|
||||||
|
|
||||||
is DataFlowIR.Node.ArrayRead ->
|
is DataFlowIR.Node.ArrayRead ->
|
||||||
Node.arrayRead(buildEdge(node.array), buildEdge(node.index))
|
Node.arrayRead(buildEdge(node.array), buildEdge(node.index), typeMap[node.type]!!)
|
||||||
|
|
||||||
is DataFlowIR.Node.ArrayWrite ->
|
is DataFlowIR.Node.ArrayWrite ->
|
||||||
Node.arrayWrite(buildEdge(node.array), buildEdge(node.index), buildEdge(node.value))
|
Node.arrayWrite(buildEdge(node.array), buildEdge(node.index), buildEdge(node.value), typeMap[node.type]!!)
|
||||||
|
|
||||||
is DataFlowIR.Node.Variable ->
|
is DataFlowIR.Node.Variable ->
|
||||||
Node.variable(node.values.map { buildEdge(it) }.toTypedArray(), typeMap[node.type]!!, node.kind)
|
Node.variable(node.values.map { buildEdge(it) }.toTypedArray(), typeMap[node.type]!!, node.kind)
|
||||||
@@ -1110,6 +1117,7 @@ internal object DFGSerializer {
|
|||||||
DataFlowIR.Node.Call(
|
DataFlowIR.Node.Call(
|
||||||
functionSymbols[call.callee],
|
functionSymbols[call.callee],
|
||||||
call.arguments.map { deserializeEdge(it) },
|
call.arguments.map { deserializeEdge(it) },
|
||||||
|
types[call.returnType],
|
||||||
irCallSite = null
|
irCallSite = null
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1119,6 +1127,7 @@ internal object DFGSerializer {
|
|||||||
call.callee,
|
call.callee,
|
||||||
call.arguments,
|
call.arguments,
|
||||||
types[virtualCall.receiverType],
|
types[virtualCall.receiverType],
|
||||||
|
types[virtualCall.call.returnType],
|
||||||
irCallSite = null
|
irCallSite = null
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1141,7 +1150,7 @@ internal object DFGSerializer {
|
|||||||
val staticCall = it.staticCall!!
|
val staticCall = it.staticCall!!
|
||||||
val call = deserializeCall(staticCall.call)
|
val call = deserializeCall(staticCall.call)
|
||||||
val receiverType = staticCall.receiverType?.let { types[it] }
|
val receiverType = staticCall.receiverType?.let { types[it] }
|
||||||
DataFlowIR.Node.StaticCall(call.callee, call.arguments, receiverType, irCallSite = null)
|
DataFlowIR.Node.StaticCall(call.callee, call.arguments, receiverType, call.returnType, irCallSite = null)
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeType.NEW_OBJECT -> {
|
NodeType.NEW_OBJECT -> {
|
||||||
@@ -1158,6 +1167,7 @@ internal object DFGSerializer {
|
|||||||
virtualCall.receiverType,
|
virtualCall.receiverType,
|
||||||
vtableCall.calleeVtableIndex,
|
vtableCall.calleeVtableIndex,
|
||||||
virtualCall.arguments,
|
virtualCall.arguments,
|
||||||
|
virtualCall.returnType,
|
||||||
virtualCall.irCallSite
|
virtualCall.irCallSite
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1170,6 +1180,7 @@ internal object DFGSerializer {
|
|||||||
virtualCall.receiverType,
|
virtualCall.receiverType,
|
||||||
itableCall.calleeHash,
|
itableCall.calleeHash,
|
||||||
virtualCall.arguments,
|
virtualCall.arguments,
|
||||||
|
virtualCall.returnType,
|
||||||
virtualCall.irCallSite
|
virtualCall.irCallSite
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1185,29 +1196,29 @@ internal object DFGSerializer {
|
|||||||
|
|
||||||
NodeType.FUNCTION_REFERENCE -> {
|
NodeType.FUNCTION_REFERENCE -> {
|
||||||
val functionReference = it.functionReference!!
|
val functionReference = it.functionReference!!
|
||||||
DataFlowIR.Node.FunctionReference(functionSymbols[functionReference.symbol], types[functionReference.type])
|
DataFlowIR.Node.FunctionReference(functionSymbols[functionReference.symbol], types[functionReference.type], types[functionReference.returnType])
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeType.FIELD_READ -> {
|
NodeType.FIELD_READ -> {
|
||||||
val fieldRead = it.fieldRead!!
|
val fieldRead = it.fieldRead!!
|
||||||
val receiver = fieldRead.receiver?.let { deserializeEdge(it) }
|
val receiver = fieldRead.receiver?.let { deserializeEdge(it) }
|
||||||
DataFlowIR.Node.FieldRead(receiver, deserializeField(fieldRead.field), null)
|
DataFlowIR.Node.FieldRead(receiver, deserializeField(fieldRead.field), types[fieldRead.type], null)
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeType.FIELD_WRITE -> {
|
NodeType.FIELD_WRITE -> {
|
||||||
val fieldWrite = it.fieldWrite!!
|
val fieldWrite = it.fieldWrite!!
|
||||||
val receiver = fieldWrite.receiver?.let { deserializeEdge(it) }
|
val receiver = fieldWrite.receiver?.let { deserializeEdge(it) }
|
||||||
DataFlowIR.Node.FieldWrite(receiver, deserializeField(fieldWrite.field), deserializeEdge(fieldWrite.value))
|
DataFlowIR.Node.FieldWrite(receiver, deserializeField(fieldWrite.field), deserializeEdge(fieldWrite.value), types[fieldWrite.type])
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeType.ARRAY_READ -> {
|
NodeType.ARRAY_READ -> {
|
||||||
val arrayRead = it.arrayRead!!
|
val arrayRead = it.arrayRead!!
|
||||||
DataFlowIR.Node.ArrayRead(deserializeEdge(arrayRead.array), deserializeEdge(arrayRead.index), null)
|
DataFlowIR.Node.ArrayRead(deserializeEdge(arrayRead.array), deserializeEdge(arrayRead.index), types[arrayRead.type], null)
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeType.ARRAY_WRITE -> {
|
NodeType.ARRAY_WRITE -> {
|
||||||
val arrayWrite = it.arrayWrite!!
|
val arrayWrite = it.arrayWrite!!
|
||||||
DataFlowIR.Node.ArrayWrite(deserializeEdge(arrayWrite.array), deserializeEdge(arrayWrite.index), deserializeEdge(arrayWrite.value))
|
DataFlowIR.Node.ArrayWrite(deserializeEdge(arrayWrite.array), deserializeEdge(arrayWrite.index), deserializeEdge(arrayWrite.value), types[arrayWrite.type])
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeType.VARIABLE -> {
|
NodeType.VARIABLE -> {
|
||||||
|
|||||||
+19
-18
@@ -223,43 +223,43 @@ internal object DataFlowIR {
|
|||||||
|
|
||||||
object Null : Node()
|
object Null : Node()
|
||||||
|
|
||||||
open class Call(val callee: FunctionSymbol, val arguments: List<Edge>,
|
open class Call(val callee: FunctionSymbol, val arguments: List<Edge>, val returnType: Type,
|
||||||
open val irCallSite: IrFunctionAccessExpression?) : Node()
|
open val irCallSite: IrFunctionAccessExpression?) : Node()
|
||||||
|
|
||||||
class StaticCall(callee: FunctionSymbol, arguments: List<Edge>,
|
class StaticCall(callee: FunctionSymbol, arguments: List<Edge>,
|
||||||
val receiverType: Type?, irCallSite: IrFunctionAccessExpression?)
|
val receiverType: Type?, returnType: Type, irCallSite: IrFunctionAccessExpression?)
|
||||||
: Call(callee, arguments, irCallSite)
|
: Call(callee, arguments, returnType, irCallSite)
|
||||||
|
|
||||||
// TODO: It can be replaced with a pair(AllocInstance, constructor Call), remove.
|
// TODO: It can be replaced with a pair(AllocInstance, constructor Call), remove.
|
||||||
class NewObject(constructor: FunctionSymbol, arguments: List<Edge>, val constructedType: Type,
|
class NewObject(constructor: FunctionSymbol, arguments: List<Edge>, val constructedType: Type, override val irCallSite: IrConstructorCall?)
|
||||||
override val irCallSite: IrConstructorCall?)
|
: Call(constructor, arguments, constructedType, irCallSite)
|
||||||
: Call(constructor, arguments, irCallSite)
|
|
||||||
|
|
||||||
open class VirtualCall(callee: FunctionSymbol, arguments: List<Edge>,
|
open class VirtualCall(callee: FunctionSymbol, arguments: List<Edge>,
|
||||||
val receiverType: Type, override val irCallSite: IrCall?)
|
val receiverType: Type, returnType: Type, override val irCallSite: IrCall?)
|
||||||
: Call(callee, arguments, irCallSite)
|
: Call(callee, arguments, returnType, irCallSite)
|
||||||
|
|
||||||
class VtableCall(callee: FunctionSymbol, receiverType: Type, val calleeVtableIndex: Int,
|
class VtableCall(callee: FunctionSymbol, receiverType: Type, val calleeVtableIndex: Int,
|
||||||
arguments: List<Edge>, irCallSite: IrCall?)
|
arguments: List<Edge>, returnType: Type, irCallSite: IrCall?)
|
||||||
: VirtualCall(callee, arguments, receiverType, irCallSite)
|
: VirtualCall(callee, arguments, receiverType, returnType, irCallSite)
|
||||||
|
|
||||||
class ItableCall(callee: FunctionSymbol, receiverType: Type, val calleeHash: Long,
|
class ItableCall(callee: FunctionSymbol, receiverType: Type, val calleeHash: Long,
|
||||||
arguments: List<Edge>, irCallSite: IrCall?)
|
arguments: List<Edge>, returnType: Type, irCallSite: IrCall?)
|
||||||
: VirtualCall(callee, arguments, receiverType, irCallSite)
|
: VirtualCall(callee, arguments, receiverType, returnType, irCallSite)
|
||||||
|
|
||||||
class Singleton(val type: Type, val constructor: FunctionSymbol?) : Node()
|
class Singleton(val type: Type, val constructor: FunctionSymbol?) : Node()
|
||||||
|
|
||||||
class AllocInstance(val type: Type) : Node()
|
class AllocInstance(val type: Type) : Node()
|
||||||
|
|
||||||
class FunctionReference(val symbol: FunctionSymbol, val type: Type) : Node()
|
class FunctionReference(val symbol: FunctionSymbol, val type: Type, val returnType: Type) : Node()
|
||||||
|
|
||||||
class FieldRead(val receiver: Edge?, val field: Field, val ir: IrGetField?) : Node()
|
// TODO: Add type (similar to arrays)?
|
||||||
|
class FieldRead(val receiver: Edge?, val field: Field, val type: Type, val ir: IrGetField?) : Node()
|
||||||
|
|
||||||
class FieldWrite(val receiver: Edge?, val field: Field, val value: Edge) : Node()
|
class FieldWrite(val receiver: Edge?, val field: Field, val value: Edge, val type: Type) : Node()
|
||||||
|
|
||||||
class ArrayRead(val array: Edge, val index: Edge, val irCallSite: IrCall?) : Node()
|
class ArrayRead(val array: Edge, val index: Edge, val type: Type, val irCallSite: IrCall?) : Node()
|
||||||
|
|
||||||
class ArrayWrite(val array: Edge, val index: Edge, val value: Edge) : Node()
|
class ArrayWrite(val array: Edge, val index: Edge, val value: Edge, val type: Type) : Node()
|
||||||
|
|
||||||
class Variable(values: List<Edge>, val type: Type, val kind: VariableKind) : Node() {
|
class Variable(values: List<Edge>, val type: Type, val kind: VariableKind) : Node() {
|
||||||
val values = mutableListOf<Edge>().also { it += values }
|
val values = mutableListOf<Edge>().also { it += values }
|
||||||
@@ -551,7 +551,8 @@ internal object DataFlowIR {
|
|||||||
primitiveBinaryType,
|
primitiveBinaryType,
|
||||||
module,
|
module,
|
||||||
-1,
|
-1,
|
||||||
null
|
null,
|
||||||
|
takeName { primitiveBinaryType.name }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+14
-14
@@ -253,7 +253,7 @@ internal object Devirtualization {
|
|||||||
addInstantiatingClass(symbolTable.mapType(context.irBuiltIns.stringType))
|
addInstantiatingClass(symbolTable.mapType(context.irBuiltIns.stringType))
|
||||||
}
|
}
|
||||||
// Traverse call graph from the roots.
|
// Traverse call graph from the roots.
|
||||||
rootSet.forEach { dfs(it) }
|
rootSet.forEach { dfs(it, it.returnParameter.type) }
|
||||||
return instantiatingClasses
|
return instantiatingClasses
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,7 +282,7 @@ internal object Devirtualization {
|
|||||||
|
|
||||||
else -> error("Unreachable")
|
else -> error("Unreachable")
|
||||||
}
|
}
|
||||||
dfs(callee)
|
dfs(callee, virtualCall.returnType)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkSupertypes(type: DataFlowIR.Type.Declared,
|
private fun checkSupertypes(type: DataFlowIR.Type.Declared,
|
||||||
@@ -317,13 +317,13 @@ internal object Devirtualization {
|
|||||||
.forEach { checkSupertypes(it, inheritor, seenTypes) }
|
.forEach { checkSupertypes(it, inheritor, seenTypes) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun dfs(symbol: DataFlowIR.FunctionSymbol) {
|
private fun dfs(symbol: DataFlowIR.FunctionSymbol, returnType: DataFlowIR.Type) {
|
||||||
val resolvedFunctionSymbol = symbol.resolved()
|
val resolvedFunctionSymbol = symbol.resolved()
|
||||||
if (resolvedFunctionSymbol is DataFlowIR.FunctionSymbol.External) {
|
if (resolvedFunctionSymbol is DataFlowIR.FunctionSymbol.External) {
|
||||||
|
|
||||||
DEBUG_OUTPUT(1) { println("Function $resolvedFunctionSymbol is external") }
|
DEBUG_OUTPUT(1) { println("Function $resolvedFunctionSymbol is external") }
|
||||||
|
|
||||||
val resolvedReturnType = symbol.returnParameter.type.resolved()
|
val resolvedReturnType = returnType.resolved()
|
||||||
if (resolvedReturnType.isFinal) {
|
if (resolvedReturnType.isFinal) {
|
||||||
|
|
||||||
DEBUG_OUTPUT(1) { println("Adding return type as it is final") }
|
DEBUG_OUTPUT(1) { println("Adding return type as it is final") }
|
||||||
@@ -346,12 +346,12 @@ internal object Devirtualization {
|
|||||||
when (node) {
|
when (node) {
|
||||||
is DataFlowIR.Node.NewObject -> {
|
is DataFlowIR.Node.NewObject -> {
|
||||||
addInstantiatingClass(node.constructedType)
|
addInstantiatingClass(node.constructedType)
|
||||||
dfs(node.callee)
|
dfs(node.callee, node.constructedType)
|
||||||
}
|
}
|
||||||
|
|
||||||
is DataFlowIR.Node.Singleton -> {
|
is DataFlowIR.Node.Singleton -> {
|
||||||
addInstantiatingClass(node.type)
|
addInstantiatingClass(node.type)
|
||||||
node.constructor?.let { dfs(it) }
|
node.constructor?.let { dfs(it, node.type) }
|
||||||
}
|
}
|
||||||
|
|
||||||
is DataFlowIR.Node.AllocInstance -> {
|
is DataFlowIR.Node.AllocInstance -> {
|
||||||
@@ -361,10 +361,10 @@ internal object Devirtualization {
|
|||||||
is DataFlowIR.Node.Const -> addInstantiatingClass(node.type)
|
is DataFlowIR.Node.Const -> addInstantiatingClass(node.type)
|
||||||
|
|
||||||
is DataFlowIR.Node.StaticCall ->
|
is DataFlowIR.Node.StaticCall ->
|
||||||
dfs(node.callee)
|
dfs(node.callee, node.returnType)
|
||||||
|
|
||||||
is DataFlowIR.Node.FunctionReference ->
|
is DataFlowIR.Node.FunctionReference ->
|
||||||
dfs(node.symbol)
|
dfs(node.symbol, node.returnType)
|
||||||
|
|
||||||
is DataFlowIR.Node.FieldRead ->
|
is DataFlowIR.Node.FieldRead ->
|
||||||
if (entryPoint == null && node.field.type.isFinal)
|
if (entryPoint == null && node.field.type.isFinal)
|
||||||
@@ -889,7 +889,7 @@ internal object Devirtualization {
|
|||||||
function.parameters[node.index]
|
function.parameters[node.index]
|
||||||
|
|
||||||
is DataFlowIR.Node.StaticCall ->
|
is DataFlowIR.Node.StaticCall ->
|
||||||
doCall(node.callee, node.arguments, node.callee.returnParameter.type.resolved(),
|
doCall(node.callee, node.arguments, node.returnType.resolved(),
|
||||||
node.receiverType?.resolved())
|
node.receiverType?.resolved())
|
||||||
|
|
||||||
is DataFlowIR.Node.NewObject -> {
|
is DataFlowIR.Node.NewObject -> {
|
||||||
@@ -933,7 +933,7 @@ internal object Devirtualization {
|
|||||||
println()
|
println()
|
||||||
}
|
}
|
||||||
|
|
||||||
val returnType = node.callee.returnParameter.type.resolved()
|
val returnType = node.returnType.resolved()
|
||||||
val receiverNode = edgeToConstraintNode(node.arguments[0])
|
val receiverNode = edgeToConstraintNode(node.arguments[0])
|
||||||
if (receiverType == DataFlowIR.Type.Virtual)
|
if (receiverType == DataFlowIR.Type.Virtual)
|
||||||
constraintGraph.virtualNode.addEdge(receiverNode)
|
constraintGraph.virtualNode.addEdge(receiverNode)
|
||||||
@@ -983,20 +983,20 @@ internal object Devirtualization {
|
|||||||
}
|
}
|
||||||
|
|
||||||
is DataFlowIR.Node.FieldRead ->
|
is DataFlowIR.Node.FieldRead ->
|
||||||
fieldNode(node.field)
|
doCast(function, fieldNode(node.field), node.type.resolved())
|
||||||
|
|
||||||
is DataFlowIR.Node.FieldWrite -> {
|
is DataFlowIR.Node.FieldWrite -> {
|
||||||
val fieldNode = fieldNode(node.field)
|
val fieldNode = fieldNode(node.field)
|
||||||
edgeToConstraintNode(node.value).addEdge(fieldNode)
|
doCast(function, edgeToConstraintNode(node.value), node.type.resolved()).addEdge(fieldNode)
|
||||||
constraintGraph.voidNode
|
constraintGraph.voidNode
|
||||||
}
|
}
|
||||||
|
|
||||||
is DataFlowIR.Node.ArrayRead ->
|
is DataFlowIR.Node.ArrayRead ->
|
||||||
fieldNode(constraintGraph.arrayItemField)
|
doCast(function, fieldNode(constraintGraph.arrayItemField), node.type.resolved())
|
||||||
|
|
||||||
is DataFlowIR.Node.ArrayWrite -> {
|
is DataFlowIR.Node.ArrayWrite -> {
|
||||||
val fieldNode = fieldNode(constraintGraph.arrayItemField)
|
val fieldNode = fieldNode(constraintGraph.arrayItemField)
|
||||||
edgeToConstraintNode(node.value).addEdge(fieldNode)
|
doCast(function, edgeToConstraintNode(node.value), node.type.resolved()).addEdge(fieldNode)
|
||||||
constraintGraph.voidNode
|
constraintGraph.voidNode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user