CFG: function builder
This commit is contained in:
committed by
Dmitry Petrov
parent
59cdcdba28
commit
ae96afb1dc
@@ -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<IrElement, BasicBlockBuilder>()
|
||||
|
||||
private var currentBlockBuilder: BasicBlockBuilder? = null
|
||||
|
||||
private val blocks = mutableListOf<BasicBlock>()
|
||||
|
||||
private val connectorBuilderMap = mutableMapOf<IrElement, BlockConnectorBuilder>()
|
||||
|
||||
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<BlockConnector>()
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user