From ae96afb1dc4e109738424f4cd6f61798681e51e2 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Fri, 23 Sep 2016 19:42:11 +0300 Subject: [PATCH] CFG: function builder --- .../ir2cfg/generators/FunctionBuilder.kt | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 compiler/ir/ir.ir2cfg/src/org/jetbrains/kotlin/ir2cfg/generators/FunctionBuilder.kt diff --git a/compiler/ir/ir.ir2cfg/src/org/jetbrains/kotlin/ir2cfg/generators/FunctionBuilder.kt b/compiler/ir/ir.ir2cfg/src/org/jetbrains/kotlin/ir2cfg/generators/FunctionBuilder.kt new file mode 100644 index 00000000000..703ebcd4193 --- /dev/null +++ b/compiler/ir/ir.ir2cfg/src/org/jetbrains/kotlin/ir2cfg/generators/FunctionBuilder.kt @@ -0,0 +1,110 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.ir2cfg.generators + +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir2cfg.builders.BasicBlockBuilder +import org.jetbrains.kotlin.ir2cfg.builders.BlockConnectorBuilder +import org.jetbrains.kotlin.ir2cfg.builders.ControlFlowGraphBuilder +import org.jetbrains.kotlin.ir2cfg.graph.BasicBlock +import org.jetbrains.kotlin.ir2cfg.graph.BlockConnector +import org.jetbrains.kotlin.ir2cfg.graph.ControlFlowGraph + +class FunctionBuilder(val function: IrFunction) : ControlFlowGraphBuilder { + + private val blockBuilderMap = mutableMapOf() + + private var currentBlockBuilder: BasicBlockBuilder? = null + + private val blocks = mutableListOf() + + private val connectorBuilderMap = mutableMapOf() + + private fun createBlockBuilder(after: BlockConnectorBuilder?): BasicBlockBuilder { + val result = GeneralBlockBuilder(after) + currentBlockBuilder = result + return result + } + + private fun BasicBlockBuilder.shiftTo(element: IrElement) { + blockBuilderMap.remove(last) + add(element) + blockBuilderMap[element] = this + } + + override fun add(element: IrElement) { + val blockBuilder = currentBlockBuilder ?: createBlockBuilder(connectorBuilderMap[element]) + blockBuilder.shiftTo(element) + } + + override fun move(to: IrElement) { + val blockBuilder = blockBuilderMap[to] + ?: connectorBuilderMap[to]?.let { createBlockBuilder(it) } + ?: throw AssertionError("Function generator may move to an element only to the end of a block or to connector") + currentBlockBuilder = blockBuilder + } + + override fun jump(to: IrElement) { + val blockBuilder = currentBlockBuilder + ?: throw AssertionError("Function generator: no default block builder for jump") + val block = blockBuilder.build() + blocks.add(block) + blockBuilderMap.values.remove(blockBuilder) + currentBlockBuilder = null + val nextConnectorBuilder = connectorBuilderMap[to] ?: GeneralConnectorBuilder(to) + nextConnectorBuilder.addPrevious(block) + val previousConnectorBuilder = blockBuilder.incoming + previousConnectorBuilder?.addNext(block) + connectorBuilderMap[to] = nextConnectorBuilder + move(to) + } + + override fun jump(to: IrElement, from: IrElement) { + currentBlockBuilder = blockBuilderMap[from] + if (currentBlockBuilder == null) { + val blockBuilder = connectorBuilderMap[from]?.let { createBlockBuilder(it) } + ?: throw AssertionError("Function generator may jump after an element only to the end of a block or to connector") + currentBlockBuilder = blockBuilder + } + jump(to) + } + + override fun build(): ControlFlowGraph { + for (blockBuilder in blockBuilderMap.values) { + if (currentBlockBuilder == blockBuilder) { + currentBlockBuilder = null + } + val block = blockBuilder.build() + blocks.add(block) + blockBuilder.incoming?.addNext(block) + } + val connectors = mutableListOf() + for (connectorBuilder in connectorBuilderMap.values) { + connectors.add(connectorBuilder.build()) + } + for (connector in connectors) { + for (previous in connector.previousBlocks) { + (previous as? BasicBlockImpl)?.outgoing = connector + } + for (next in connector.nextBlocks) { + (next as? BasicBlockImpl)?.incoming = connector + } + } + return ControlFlowGraphImpl(function, blocks, connectors) + } +}