diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGBuilder.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGBuilder.kt index 95187018d51..e677e567670 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGBuilder.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGBuilder.kt @@ -542,9 +542,14 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag is IrGetValue -> getNode(value) is IrVararg, - is IrConst<*>, is IrFunctionReference -> DataFlowIR.Node.Const(symbolTable.mapType(value.type)) + is IrConst<*> -> + if (value.value == null) + DataFlowIR.Node.Null + else + DataFlowIR.Node.Const(symbolTable.mapType(value.type)) + is IrGetObjectValue -> DataFlowIR.Node.Singleton( symbolTable.mapType(value.type), if (value.type.isNothing()) // is not a singleton though its instance is get with operation. diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGSerializer.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGSerializer.kt index 02429789bd1..d7f58475f20 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGSerializer.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DFGSerializer.kt @@ -587,6 +587,7 @@ internal object DFGSerializer { UNKNOWN, PARAMETER, CONST, + NULL, STATIC_CALL, NEW_OBJECT, VTABLE_CALL, @@ -603,6 +604,7 @@ internal object DFGSerializer { class Node { var parameter : Parameter? = null var const : Const? = null + var nil : Boolean = false var staticCall : StaticCall? = null var newObject : NewObject? = null var vtableCall : VtableCall? = null @@ -629,6 +631,7 @@ internal object DFGSerializer { arrayRead != null -> NodeType.ARRAY_READ arrayWrite != null -> NodeType.ARRAY_WRITE variable != null -> NodeType.VARIABLE + nil -> NodeType.NULL else -> NodeType.UNKNOWN } @@ -656,6 +659,8 @@ internal object DFGSerializer { fun const(type: Int) = Node().also { it.const = Const(type) } + fun nil() = Node().also { it.nil = true } + fun staticCall(call: Call, receiverType: Int?) = Node().also { it.staticCall = StaticCall(call, receiverType) } @@ -695,6 +700,7 @@ internal object DFGSerializer { when (type) { NodeType.PARAMETER -> result.parameter = Parameter (data) NodeType.CONST -> result.const = Const (data) + NodeType.NULL -> result.nil = true NodeType.STATIC_CALL -> result.staticCall = StaticCall (data) NodeType.NEW_OBJECT -> result.newObject = NewObject (data) NodeType.VTABLE_CALL -> result.vtableCall = VtableCall (data) @@ -887,6 +893,8 @@ internal object DFGSerializer { is DataFlowIR.Node.Const -> Node.const(typeMap[node.type]!!) + DataFlowIR.Node.Null -> Node.nil() + is DataFlowIR.Node.StaticCall -> Node.staticCall(buildCall(node), node.receiverType?.let { typeMap[it]!! }) @@ -1106,6 +1114,8 @@ internal object DFGSerializer { NodeType.CONST -> DataFlowIR.Node.Const(types[it.const!!.type]) + NodeType.NULL -> DataFlowIR.Node.Null + NodeType.STATIC_CALL -> { val staticCall = it.staticCall!! val call = deserializeCall(staticCall.call) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt index e5739b8cb01..f93715fe7b2 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt @@ -223,6 +223,8 @@ internal object DataFlowIR { class Const(val type: Type) : Node() + object Null : Node() + open class Call(val callee: FunctionSymbol, val arguments: List, open val irCallSite: IrFunctionAccessExpression?) : Node() @@ -286,6 +288,9 @@ internal object DataFlowIR { is Node.Const -> " CONST ${node.type}\n" + Node.Null -> + " NULL\n" + is Node.Parameter -> " PARAM ${node.index}\n" diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt index ca082f9454f..0888bf8f981 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt @@ -866,6 +866,8 @@ internal object Devirtualization { is DataFlowIR.Node.Const -> sourceNode(concreteType(node.type.resolved())) { "Const\$${function.symbol}" } + DataFlowIR.Node.Null -> constraintGraph.voidNode + is DataFlowIR.Node.Parameter -> function.parameters[node.index] diff --git a/backend.native/tests/build.gradle b/backend.native/tests/build.gradle index bea48f4335a..e61e371bd9f 100644 --- a/backend.native/tests/build.gradle +++ b/backend.native/tests/build.gradle @@ -2233,6 +2233,11 @@ task args0(type: RunStandaloneKonanTest) { source = "runtime/basic/args0.kt" } +task devirtualization_lateinitInterface(type: RunStandaloneKonanTest) { + goldValue = "42\n" + source = "codegen/devirtualization/lateinitInterface.kt" +} + task multiargs(type: RunStandaloneKonanTest) { arguments = ["AAA", "BB", "C"] multiRuns = true diff --git a/backend.native/tests/codegen/devirtualization/lateinitInterface.kt b/backend.native/tests/codegen/devirtualization/lateinitInterface.kt new file mode 100644 index 00000000000..1bb5bd22980 --- /dev/null +++ b/backend.native/tests/codegen/devirtualization/lateinitInterface.kt @@ -0,0 +1,14 @@ +interface I { + fun foo(): Int +} + +class A : I { + override fun foo() = 42 +} + +fun main(args: Array) { + lateinit var a: I + if (args.size == 0) + a = A() + println(a.foo()) +} \ No newline at end of file