diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt index b6a843903ce..3c028e61eb2 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/Ir.kt @@ -160,6 +160,14 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable): Sym symbol.descriptor to symbolTable.referenceSimpleFunction(functionDescriptor) }.toMap() + val arrayGet = array.descriptor.unsubstitutedMemberScope + .getContributedFunctions(Name.identifier("get"), NoLookupLocation.FROM_BACKEND) + .single().let { symbolTable.referenceSimpleFunction(it) } + + val arraySet = array.descriptor.unsubstitutedMemberScope + .getContributedFunctions(Name.identifier("set"), NoLookupLocation.FROM_BACKEND) + .single().let { symbolTable.referenceSimpleFunction(it) } + val valuesForEnum = symbolTable.referenceSimpleFunction( context.getInternalFunctions("valuesForEnum").single()) 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 0e73ee2e5c3..33517cf510a 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 @@ -410,6 +410,9 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag .getContributedFunctions(Name.identifier("doResume"), NoLookupLocation.FROM_BACKEND).single() private val getContinuationSymbol = context.ir.symbols.getContinuation + private val arrayGetSymbol = context.ir.symbols.arrayGet + private val arraySetSymbol = context.ir.symbols.arraySet + private inner class FunctionDFGBuilder(val expressionValuesExtractor: ExpressionValuesExtractor, val variableValues: VariableValues, val descriptor: CallableDescriptor, @@ -501,10 +504,16 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag else symbolTable.mapFunction(value.descriptor.constructors.single()) ) - is IrCall -> { - if (value.symbol == getContinuationSymbol) { - getContinuation() - } else { + is IrCall -> when (value.symbol) { + getContinuationSymbol -> getContinuation() + + arrayGetSymbol -> DataFlowIR.Node.ArrayRead(expressionToEdge(value.dispatchReceiver!!), + expressionToEdge(value.getValueArgument(0)!!), value) + + arraySetSymbol -> DataFlowIR.Node.ArrayWrite(expressionToEdge(value.dispatchReceiver!!), + expressionToEdge(value.getValueArgument(0)!!), expressionToEdge(value.getValueArgument(1)!!)) + + else -> { val callee = value.descriptor val arguments = value.getArguments() .map { expressionToEdge(it.second) } 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 2c1d49ae4f3..b53a0fc345b 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 @@ -493,6 +493,27 @@ internal object DFGSerializer { } } + class ArrayRead(val array: Edge, val index: Edge) { + + constructor(data: ArraySlice) : this(Edge(data), Edge(data)) + + fun write(result: ArraySlice) { + array.write(result) + index.write(result) + } + } + + class ArrayWrite(val array: Edge, val index: Edge, val value: Edge) { + + constructor(data: ArraySlice) : this(Edge(data), Edge(data), Edge(data)) + + fun write(result: ArraySlice) { + array.write(result) + index.write(result) + value.write(result) + } + } + class Variable(val values: Array, val temp: Boolean) { constructor(data: ArraySlice) : this(data.readArray { Edge(this) }, data.readBoolean()) @@ -514,6 +535,8 @@ internal object DFGSerializer { SINGLETON, FIELD_READ, FIELD_WRITE, + ARRAY_READ, + ARRAY_WRITE, VARIABLE } @@ -527,6 +550,8 @@ internal object DFGSerializer { var singleton : Singleton? = 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 { @@ -539,6 +564,8 @@ internal object DFGSerializer { singleton != null -> NodeType.SINGLETON fieldRead != null -> NodeType.FIELD_READ fieldWrite != null -> NodeType.FIELD_WRITE + arrayRead != null -> NodeType.ARRAY_READ + arrayWrite != null -> NodeType.ARRAY_WRITE variable != null -> NodeType.VARIABLE else -> NodeType.UNKNOWN } @@ -554,6 +581,8 @@ internal object DFGSerializer { singleton ?.write(result) fieldRead ?.write(result) fieldWrite?.write(result) + arrayRead ?.write(result) + arrayWrite?.write(result) variable ?.write(result) } @@ -585,6 +614,12 @@ internal object DFGSerializer { fun fieldWrite(receiver: Edge?, field: Field, value: Edge) = Node().also { it.fieldWrite = FieldWrite(receiver, field, value) } + fun arrayRead(array: Edge, index: Edge) = + Node().also { it.arrayRead = ArrayRead(array, index) } + + fun arrayWrite(array: Edge, index: Edge, value: Edge) = + Node().also { it.arrayWrite = ArrayWrite(array, index, value) } + fun variable(values: Array, temp: Boolean) = Node().also { it.variable = Variable(values, temp) } @@ -601,6 +636,8 @@ internal object DFGSerializer { NodeType.SINGLETON -> result.singleton = Singleton (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 -> { } } @@ -756,6 +793,12 @@ internal object DFGSerializer { is DataFlowIR.Node.FieldWrite -> Node.fieldWrite(node.receiver?.let { buildEdge(it) }, buildField(node.field), buildEdge(node.value)) + is DataFlowIR.Node.ArrayRead -> + Node.arrayRead(buildEdge(node.array), buildEdge(node.index)) + + is DataFlowIR.Node.ArrayWrite -> + Node.arrayWrite(buildEdge(node.array), buildEdge(node.index), buildEdge(node.value)) + is DataFlowIR.Node.Variable -> Node.variable(node.values.map { buildEdge(it) }.toTypedArray(), node.temp) @@ -965,6 +1008,16 @@ internal object DFGSerializer { DataFlowIR.Node.FieldWrite(receiver, deserializeField(fieldWrite.field), deserializeEdge(fieldWrite.value)) } + NodeType.ARRAY_READ -> { + val arrayRead = it.arrayRead!! + DataFlowIR.Node.ArrayRead(deserializeEdge(arrayRead.array), deserializeEdge(arrayRead.index), null) + } + + NodeType.ARRAY_WRITE -> { + val arrayWrite = it.arrayWrite!! + DataFlowIR.Node.ArrayWrite(deserializeEdge(arrayWrite.array), deserializeEdge(arrayWrite.index), deserializeEdge(arrayWrite.value)) + } + NodeType.VARIABLE -> { val variable = it.variable!! DataFlowIR.Node.Variable(variable.values.map { deserializeEdge(it) }, variable.temp) @@ -1009,6 +1062,21 @@ internal object DFGSerializer { deserializedFieldWrite.value.node = nodes[fieldWrite.value.node] } + NodeType.ARRAY_READ -> { + val deserializedArrayRead = deserializedNode as DataFlowIR.Node.ArrayRead + val arrayRead = node.arrayRead!! + deserializedArrayRead.array.node = nodes[arrayRead.array.node] + deserializedArrayRead.index.node = nodes[arrayRead.index.node] + } + + NodeType.ARRAY_WRITE -> { + val deserializedArrayWrite = deserializedNode as DataFlowIR.Node.ArrayWrite + val arrayWrite = node.arrayWrite!! + deserializedArrayWrite.array.node = nodes[arrayWrite.array.node] + deserializedArrayWrite.index.node = nodes[arrayWrite.index.node] + deserializedArrayWrite.value.node = nodes[arrayWrite.value.node] + } + NodeType.VARIABLE -> node.variable!!.values.forEachIndexed { i, value -> (deserializedNode as DataFlowIR.Node.Variable).values[i].node = nodes[value.node] 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 15ae6ddc542..1521c4467d6 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 @@ -217,6 +217,10 @@ internal object DataFlowIR { class FieldWrite(val receiver: Edge?, val field: Field, val value: Edge) : Node() + class ArrayRead(val array: Edge, val index: Edge, val callSite: IrCall?) : Node() + + class ArrayWrite(val array: Edge, val index: Edge, val value: Edge) : Node() + class Variable(values: List, val temp: Boolean) : Node() { val values = mutableListOf().also { it += values } } @@ -339,6 +343,43 @@ internal object DataFlowIR { result.toString() } + is Node.ArrayRead -> { + val result = StringBuilder() + result.appendln(" ARRAY READ") + result.append(" ARRAY #${ids[node.array.node]}") + if (node.array.castToType == null) + result.appendln() + else + result.appendln(" CASTED TO ${node.array.castToType}") + result.append(" INDEX #${ids[node.index.node]!!}") + if (node.index.castToType == null) + result.appendln() + else + result.appendln(" CASTED TO ${node.index.castToType}") + result.toString() + } + + is Node.ArrayWrite -> { + val result = StringBuilder() + result.appendln(" ARRAY WRITE") + result.append(" ARRAY #${ids[node.array.node]}") + if (node.array.castToType == null) + result.appendln() + else + result.appendln(" CASTED TO ${node.array.castToType}") + result.append(" INDEX #${ids[node.index.node]!!}") + if (node.index.castToType == null) + result.appendln() + else + result.appendln(" CASTED TO ${node.index.castToType}") + print(" VALUE #${ids[node.value.node]!!}") + if (node.value.castToType == null) + result.appendln() + else + result.appendln(" CASTED TO ${node.value.castToType}") + result.toString() + } + is Node.Variable -> { val result = StringBuilder() result.appendln(" ${if (node.temp) "TEMP VAR" else "VARIABLE"} ")