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