DFG: Supported IrFunctionReference
This commit is contained in:
+17
@@ -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 {
|
} else {
|
||||||
var function = moduleDFG.functions[symbol]
|
var function = moduleDFG.functions[symbol]
|
||||||
var local = true
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+6
-2
@@ -545,8 +545,12 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
|||||||
when (value) {
|
when (value) {
|
||||||
is IrGetValue -> getNode(value)
|
is IrGetValue -> getNode(value)
|
||||||
|
|
||||||
is IrVararg,
|
is IrVararg -> DataFlowIR.Node.Const(symbolTable.mapType(value.type))
|
||||||
is IrFunctionReference -> 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<*> ->
|
is IrConst<*> ->
|
||||||
if (value.value == null)
|
if (value.value == null)
|
||||||
|
|||||||
+58
-32
@@ -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) {
|
class FieldRead(val receiver: Edge?, val field: Field) {
|
||||||
|
|
||||||
constructor(data: ArraySlice) : this(data.readNullable { Edge(this) }, Field(data))
|
constructor(data: ArraySlice) : this(data.readNullable { Edge(this) }, Field(data))
|
||||||
@@ -594,6 +604,7 @@ internal object DFGSerializer {
|
|||||||
ITABLE_CALL,
|
ITABLE_CALL,
|
||||||
SINGLETON,
|
SINGLETON,
|
||||||
ALLOC_INSTANCE,
|
ALLOC_INSTANCE,
|
||||||
|
FUNCTION_REFERENCE,
|
||||||
FIELD_READ,
|
FIELD_READ,
|
||||||
FIELD_WRITE,
|
FIELD_WRITE,
|
||||||
ARRAY_READ,
|
ARRAY_READ,
|
||||||
@@ -611,21 +622,23 @@ internal object DFGSerializer {
|
|||||||
var itableCall : ItableCall? = null
|
var itableCall : ItableCall? = null
|
||||||
var singleton : Singleton? = null
|
var singleton : Singleton? = null
|
||||||
var allocInstance: AllocInstance? = null
|
var allocInstance: AllocInstance? = null
|
||||||
var fieldRead : FieldRead? = null
|
var functionReference: FunctionReference? = null
|
||||||
var fieldWrite : FieldWrite? = null
|
var fieldRead : FieldRead? = null
|
||||||
var arrayRead : ArrayRead? = null
|
var fieldWrite : FieldWrite? = null
|
||||||
var arrayWrite : ArrayWrite? = null
|
var arrayRead : ArrayRead? = null
|
||||||
var variable : Variable? = null
|
var arrayWrite : ArrayWrite? = null
|
||||||
|
var variable : Variable? = null
|
||||||
|
|
||||||
val type get() = when {
|
val type get() = when {
|
||||||
parameter != null -> NodeType.PARAMETER
|
parameter != null -> NodeType.PARAMETER
|
||||||
const != null -> NodeType.CONST
|
const != null -> NodeType.CONST
|
||||||
staticCall != null -> NodeType.STATIC_CALL
|
staticCall != null -> NodeType.STATIC_CALL
|
||||||
newObject != null -> NodeType.NEW_OBJECT
|
newObject != null -> NodeType.NEW_OBJECT
|
||||||
vtableCall != null -> NodeType.VTABLE_CALL
|
vtableCall != null -> NodeType.VTABLE_CALL
|
||||||
itableCall != null -> NodeType.ITABLE_CALL
|
itableCall != null -> NodeType.ITABLE_CALL
|
||||||
singleton != null -> NodeType.SINGLETON
|
singleton != null -> NodeType.SINGLETON
|
||||||
allocInstance != null -> NodeType.ALLOC_INSTANCE
|
allocInstance != null -> NodeType.ALLOC_INSTANCE
|
||||||
|
functionReference != null -> NodeType.FUNCTION_REFERENCE
|
||||||
fieldRead != null -> NodeType.FIELD_READ
|
fieldRead != null -> NodeType.FIELD_READ
|
||||||
fieldWrite != null -> NodeType.FIELD_WRITE
|
fieldWrite != null -> NodeType.FIELD_WRITE
|
||||||
arrayRead != null -> NodeType.ARRAY_READ
|
arrayRead != null -> NodeType.ARRAY_READ
|
||||||
@@ -637,19 +650,20 @@ internal object DFGSerializer {
|
|||||||
|
|
||||||
fun write(result: ArraySlice) {
|
fun write(result: ArraySlice) {
|
||||||
result.writeByte(type.ordinal.toByte())
|
result.writeByte(type.ordinal.toByte())
|
||||||
parameter ?.write(result)
|
parameter ?.write(result)
|
||||||
const ?.write(result)
|
const ?.write(result)
|
||||||
staticCall ?.write(result)
|
staticCall ?.write(result)
|
||||||
newObject ?.write(result)
|
newObject ?.write(result)
|
||||||
vtableCall ?.write(result)
|
vtableCall ?.write(result)
|
||||||
itableCall ?.write(result)
|
itableCall ?.write(result)
|
||||||
singleton ?.write(result)
|
singleton ?.write(result)
|
||||||
allocInstance?.write(result)
|
allocInstance ?.write(result)
|
||||||
fieldRead ?.write(result)
|
functionReference?.write(result)
|
||||||
fieldWrite ?.write(result)
|
fieldRead ?.write(result)
|
||||||
arrayRead ?.write(result)
|
fieldWrite ?.write(result)
|
||||||
arrayWrite ?.write(result)
|
arrayRead ?.write(result)
|
||||||
variable ?.write(result)
|
arrayWrite ?.write(result)
|
||||||
|
variable ?.write(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -679,6 +693,9 @@ 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) =
|
||||||
|
Node().also { it.functionReference = FunctionReference(symbol, type) }
|
||||||
|
|
||||||
fun fieldRead(receiver: Edge?, field: Field) =
|
fun fieldRead(receiver: Edge?, field: Field) =
|
||||||
Node().also { it.fieldRead = FieldRead(receiver, field) }
|
Node().also { it.fieldRead = FieldRead(receiver, field) }
|
||||||
|
|
||||||
@@ -707,12 +724,13 @@ internal object DFGSerializer {
|
|||||||
NodeType.ITABLE_CALL -> result.itableCall = ItableCall (data)
|
NodeType.ITABLE_CALL -> result.itableCall = ItableCall (data)
|
||||||
NodeType.SINGLETON -> result.singleton = Singleton (data)
|
NodeType.SINGLETON -> result.singleton = Singleton (data)
|
||||||
NodeType.ALLOC_INSTANCE -> result.allocInstance = AllocInstance(data)
|
NodeType.ALLOC_INSTANCE -> result.allocInstance = AllocInstance(data)
|
||||||
NodeType.FIELD_READ -> result.fieldRead = FieldRead (data)
|
NodeType.FUNCTION_REFERENCE -> result.functionReference = FunctionReference(data)
|
||||||
NodeType.FIELD_WRITE -> result.fieldWrite = FieldWrite (data)
|
NodeType.FIELD_READ -> result.fieldRead = FieldRead (data)
|
||||||
NodeType.ARRAY_READ -> result.arrayRead = ArrayRead (data)
|
NodeType.FIELD_WRITE -> result.fieldWrite = FieldWrite (data)
|
||||||
NodeType.ARRAY_WRITE -> result.arrayWrite = ArrayWrite (data)
|
NodeType.ARRAY_READ -> result.arrayRead = ArrayRead (data)
|
||||||
NodeType.VARIABLE -> result.variable = Variable (data)
|
NodeType.ARRAY_WRITE -> result.arrayWrite = ArrayWrite (data)
|
||||||
else -> { }
|
NodeType.VARIABLE -> result.variable = Variable (data)
|
||||||
|
else -> { }
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -913,6 +931,9 @@ internal object DFGSerializer {
|
|||||||
is DataFlowIR.Node.AllocInstance ->
|
is DataFlowIR.Node.AllocInstance ->
|
||||||
Node.allocInst(typeMap[node.type]!!)
|
Node.allocInst(typeMap[node.type]!!)
|
||||||
|
|
||||||
|
is DataFlowIR.Node.FunctionReference ->
|
||||||
|
Node.functionReference(functionSymbolMap[node.symbol]!!, typeMap[node.type]!!)
|
||||||
|
|
||||||
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))
|
||||||
|
|
||||||
@@ -1162,6 +1183,11 @@ internal object DFGSerializer {
|
|||||||
DataFlowIR.Node.AllocInstance(types[it.allocInstance!!.type])
|
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 -> {
|
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) }
|
||||||
|
|||||||
+5
@@ -254,6 +254,8 @@ internal object DataFlowIR {
|
|||||||
|
|
||||||
class AllocInstance(val type: Type) : Node()
|
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 FieldRead(val receiver: Edge?, val field: Field, 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) : Node()
|
||||||
@@ -302,6 +304,9 @@ internal object DataFlowIR {
|
|||||||
is Node.AllocInstance ->
|
is Node.AllocInstance ->
|
||||||
" ALLOC INSTANCE ${node.type}\n"
|
" ALLOC INSTANCE ${node.type}\n"
|
||||||
|
|
||||||
|
is Node.FunctionReference ->
|
||||||
|
" FUNCTION REFERENCE ${node.symbol}\n"
|
||||||
|
|
||||||
is Node.StaticCall -> {
|
is Node.StaticCall -> {
|
||||||
val result = StringBuilder()
|
val result = StringBuilder()
|
||||||
result.appendln(" STATIC CALL ${node.callee}")
|
result.appendln(" STATIC CALL ${node.callee}")
|
||||||
|
|||||||
+7
@@ -358,6 +358,9 @@ internal object Devirtualization {
|
|||||||
is DataFlowIR.Node.StaticCall ->
|
is DataFlowIR.Node.StaticCall ->
|
||||||
dfs(node.callee)
|
dfs(node.callee)
|
||||||
|
|
||||||
|
is DataFlowIR.Node.FunctionReference ->
|
||||||
|
dfs(node.symbol)
|
||||||
|
|
||||||
is DataFlowIR.Node.FieldRead ->
|
is DataFlowIR.Node.FieldRead ->
|
||||||
if (entryPoint == null && node.field.type.isFinal)
|
if (entryPoint == null && node.field.type.isFinal)
|
||||||
addInstantiatingClass(node.field.type)
|
addInstantiatingClass(node.field.type)
|
||||||
@@ -963,6 +966,10 @@ internal object Devirtualization {
|
|||||||
concreteClass(node.type.resolved())
|
concreteClass(node.type.resolved())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is DataFlowIR.Node.FunctionReference -> {
|
||||||
|
concreteClass(node.type.resolved())
|
||||||
|
}
|
||||||
|
|
||||||
is DataFlowIR.Node.FieldRead ->
|
is DataFlowIR.Node.FieldRead ->
|
||||||
fieldNode(node.field)
|
fieldNode(node.field)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user