DFG: Supported IrFunctionReference

This commit is contained in:
Igor Chevdar
2019-03-25 17:27:03 +03:00
parent 7bf16abf66
commit c5430769de
5 changed files with 93 additions and 34 deletions
@@ -124,6 +124,13 @@ internal class CallGraphBuilder(val context: Context,
}
}
}
body.nodes.filterIsInstance<DataFlowIR.Node.FunctionReference>()
.forEach {
val callee = it.symbol.resolved()
if (callee is DataFlowIR.FunctionSymbol.Declared
&& !directEdges.containsKey(callee))
dfs(callee)
}
} else {
var function = moduleDFG.functions[symbol]
var local = true
@@ -160,6 +167,16 @@ internal class CallGraphBuilder(val context: Context,
}
}
}
body.nodes.filterIsInstance<DataFlowIR.Node.FunctionReference>()
.forEach {
val callee = it.symbol.resolved()
if (moduleDFG.functions.containsKey(callee))
addNode(callee)
if (callee is DataFlowIR.FunctionSymbol.Declared
&& !visitedFunctions.contains(callee))
dfs(callee)
}
}
}
}
@@ -545,8 +545,12 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
when (value) {
is IrGetValue -> getNode(value)
is IrVararg,
is IrFunctionReference -> DataFlowIR.Node.Const(symbolTable.mapType(value.type))
is IrVararg -> DataFlowIR.Node.Const(symbolTable.mapType(value.type))
is IrFunctionReference -> {
val callee = value.symbol.owner
DataFlowIR.Node.FunctionReference(symbolTable.mapFunction(callee), symbolTable.mapType(value.type))
}
is IrConst<*> ->
if (value.value == null)
@@ -530,6 +530,16 @@ internal object DFGSerializer {
}
}
class FunctionReference(val symbol: Int, val type: Int) {
constructor(data: ArraySlice) : this(data.readInt(), data.readInt())
fun write(result: ArraySlice) {
result.writeInt(symbol)
result.writeInt(type)
}
}
class FieldRead(val receiver: Edge?, val field: Field) {
constructor(data: ArraySlice) : this(data.readNullable { Edge(this) }, Field(data))
@@ -594,6 +604,7 @@ internal object DFGSerializer {
ITABLE_CALL,
SINGLETON,
ALLOC_INSTANCE,
FUNCTION_REFERENCE,
FIELD_READ,
FIELD_WRITE,
ARRAY_READ,
@@ -611,21 +622,23 @@ internal object DFGSerializer {
var itableCall : ItableCall? = null
var singleton : Singleton? = null
var allocInstance: AllocInstance? = null
var fieldRead : FieldRead? = null
var fieldWrite : FieldWrite? = null
var arrayRead : ArrayRead? = null
var arrayWrite : ArrayWrite? = null
var variable : Variable? = null
var functionReference: FunctionReference? = null
var fieldRead : FieldRead? = null
var fieldWrite : FieldWrite? = null
var arrayRead : ArrayRead? = null
var arrayWrite : ArrayWrite? = null
var variable : Variable? = null
val type get() = when {
parameter != null -> NodeType.PARAMETER
const != null -> NodeType.CONST
staticCall != null -> NodeType.STATIC_CALL
newObject != null -> NodeType.NEW_OBJECT
vtableCall != null -> NodeType.VTABLE_CALL
itableCall != null -> NodeType.ITABLE_CALL
singleton != null -> NodeType.SINGLETON
allocInstance != null -> NodeType.ALLOC_INSTANCE
parameter != null -> NodeType.PARAMETER
const != null -> NodeType.CONST
staticCall != null -> NodeType.STATIC_CALL
newObject != null -> NodeType.NEW_OBJECT
vtableCall != null -> NodeType.VTABLE_CALL
itableCall != null -> NodeType.ITABLE_CALL
singleton != null -> NodeType.SINGLETON
allocInstance != null -> NodeType.ALLOC_INSTANCE
functionReference != null -> NodeType.FUNCTION_REFERENCE
fieldRead != null -> NodeType.FIELD_READ
fieldWrite != null -> NodeType.FIELD_WRITE
arrayRead != null -> NodeType.ARRAY_READ
@@ -637,19 +650,20 @@ internal object DFGSerializer {
fun write(result: ArraySlice) {
result.writeByte(type.ordinal.toByte())
parameter ?.write(result)
const ?.write(result)
staticCall ?.write(result)
newObject ?.write(result)
vtableCall ?.write(result)
itableCall ?.write(result)
singleton ?.write(result)
allocInstance?.write(result)
fieldRead ?.write(result)
fieldWrite ?.write(result)
arrayRead ?.write(result)
arrayWrite ?.write(result)
variable ?.write(result)
parameter ?.write(result)
const ?.write(result)
staticCall ?.write(result)
newObject ?.write(result)
vtableCall ?.write(result)
itableCall ?.write(result)
singleton ?.write(result)
allocInstance ?.write(result)
functionReference?.write(result)
fieldRead ?.write(result)
fieldWrite ?.write(result)
arrayRead ?.write(result)
arrayWrite ?.write(result)
variable ?.write(result)
}
companion object {
@@ -679,6 +693,9 @@ 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 fieldRead(receiver: Edge?, field: Field) =
Node().also { it.fieldRead = FieldRead(receiver, field) }
@@ -707,12 +724,13 @@ internal object DFGSerializer {
NodeType.ITABLE_CALL -> result.itableCall = ItableCall (data)
NodeType.SINGLETON -> result.singleton = Singleton (data)
NodeType.ALLOC_INSTANCE -> result.allocInstance = AllocInstance(data)
NodeType.FIELD_READ -> result.fieldRead = FieldRead (data)
NodeType.FIELD_WRITE -> result.fieldWrite = FieldWrite (data)
NodeType.ARRAY_READ -> result.arrayRead = ArrayRead (data)
NodeType.ARRAY_WRITE -> result.arrayWrite = ArrayWrite (data)
NodeType.VARIABLE -> result.variable = Variable (data)
else -> { }
NodeType.FUNCTION_REFERENCE -> result.functionReference = FunctionReference(data)
NodeType.FIELD_READ -> result.fieldRead = FieldRead (data)
NodeType.FIELD_WRITE -> result.fieldWrite = FieldWrite (data)
NodeType.ARRAY_READ -> result.arrayRead = ArrayRead (data)
NodeType.ARRAY_WRITE -> result.arrayWrite = ArrayWrite (data)
NodeType.VARIABLE -> result.variable = Variable (data)
else -> { }
}
return result
}
@@ -913,6 +931,9 @@ internal object DFGSerializer {
is DataFlowIR.Node.AllocInstance ->
Node.allocInst(typeMap[node.type]!!)
is DataFlowIR.Node.FunctionReference ->
Node.functionReference(functionSymbolMap[node.symbol]!!, typeMap[node.type]!!)
is DataFlowIR.Node.FieldRead ->
Node.fieldRead(node.receiver?.let { buildEdge(it) }, buildField(node.field))
@@ -1162,6 +1183,11 @@ internal object DFGSerializer {
DataFlowIR.Node.AllocInstance(types[it.allocInstance!!.type])
}
NodeType.FUNCTION_REFERENCE -> {
val functionReference = it.functionReference!!
DataFlowIR.Node.FunctionReference(functionSymbols[functionReference.symbol], types[functionReference.type])
}
NodeType.FIELD_READ -> {
val fieldRead = it.fieldRead!!
val receiver = fieldRead.receiver?.let { deserializeEdge(it) }
@@ -254,6 +254,8 @@ internal object DataFlowIR {
class AllocInstance(val type: Type) : Node()
class FunctionReference(val symbol: FunctionSymbol, val type: Type) : Node()
class FieldRead(val receiver: Edge?, val field: Field, val ir: IrGetField?) : Node()
class FieldWrite(val receiver: Edge?, val field: Field, val value: Edge) : Node()
@@ -302,6 +304,9 @@ internal object DataFlowIR {
is Node.AllocInstance ->
" ALLOC INSTANCE ${node.type}\n"
is Node.FunctionReference ->
" FUNCTION REFERENCE ${node.symbol}\n"
is Node.StaticCall -> {
val result = StringBuilder()
result.appendln(" STATIC CALL ${node.callee}")
@@ -358,6 +358,9 @@ internal object Devirtualization {
is DataFlowIR.Node.StaticCall ->
dfs(node.callee)
is DataFlowIR.Node.FunctionReference ->
dfs(node.symbol)
is DataFlowIR.Node.FieldRead ->
if (entryPoint == null && node.field.type.isFinal)
addInstantiatingClass(node.field.type)
@@ -963,6 +966,10 @@ internal object Devirtualization {
concreteClass(node.type.resolved())
}
is DataFlowIR.Node.FunctionReference -> {
concreteClass(node.type.resolved())
}
is DataFlowIR.Node.FieldRead ->
fieldNode(node.field)