[IR] Drop ir.ir2cfg module
#KTI-952 Fixed #KT-65773 Related
This commit is contained in:
committed by
Space Team
parent
6fb6f04509
commit
cbabfc0fe2
@@ -1,18 +0,0 @@
|
||||
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("jps-compatible")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(project(":compiler:util"))
|
||||
api(project(":compiler:frontend"))
|
||||
api(project(":compiler:ir.tree"))
|
||||
}
|
||||
|
||||
optInToUnsafeDuringIrConstructionAPI()
|
||||
|
||||
sourceSets {
|
||||
"main" { projectDefault() }
|
||||
"test" {}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* 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.builders
|
||||
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir2cfg.graph.BasicBlock
|
||||
|
||||
interface BasicBlockBuilder {
|
||||
|
||||
val incoming: BlockConnectorBuilder?
|
||||
|
||||
fun add(element: IrStatement)
|
||||
|
||||
val last: IrStatement?
|
||||
|
||||
fun build(): BasicBlock
|
||||
}
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* 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.builders
|
||||
|
||||
import org.jetbrains.kotlin.ir2cfg.graph.BasicBlock
|
||||
import org.jetbrains.kotlin.ir2cfg.graph.BlockConnector
|
||||
|
||||
interface BlockConnectorBuilder {
|
||||
|
||||
fun addNext(basicBlock: BasicBlock)
|
||||
|
||||
fun addPrevious(basicBlock: BasicBlock)
|
||||
|
||||
fun build(): BlockConnector
|
||||
}
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* 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.builders
|
||||
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir2cfg.graph.ControlFlowGraph
|
||||
|
||||
interface ControlFlowGraphBuilder {
|
||||
// Add element to the builder pointer
|
||||
fun add(element: IrStatement)
|
||||
|
||||
// Move builder pointer to element without changing graph
|
||||
fun move(to: IrStatement)
|
||||
|
||||
// Connect builder pointer with the given element and move pointer to this element
|
||||
fun jump(to: IrStatement)
|
||||
|
||||
// Connect from with to and move pointer to the destination
|
||||
fun jump(to: IrStatement, from: IrStatement)
|
||||
|
||||
// Build CFG from builder
|
||||
fun build(): ControlFlowGraph
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* 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.IrStatement
|
||||
import org.jetbrains.kotlin.ir2cfg.graph.BasicBlock
|
||||
import org.jetbrains.kotlin.ir2cfg.graph.BlockConnector
|
||||
|
||||
class BasicBlockImpl(override val elements: List<IrStatement>) : BasicBlock {
|
||||
|
||||
override var incoming: BlockConnector? = null
|
||||
internal set(arg) {
|
||||
if (field != null) throw AssertionError("Incoming connector cannot be changed after being set")
|
||||
field = arg
|
||||
}
|
||||
|
||||
override var outgoing: BlockConnector? = null
|
||||
internal set(arg) {
|
||||
if (field != null) throw AssertionError("Outgoing connector cannot be changed after being set")
|
||||
field = arg
|
||||
}
|
||||
}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* 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.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir2cfg.graph.BasicBlock
|
||||
import org.jetbrains.kotlin.ir2cfg.graph.BlockConnector
|
||||
import org.jetbrains.kotlin.ir2cfg.graph.ControlFlowGraph
|
||||
|
||||
class ControlFlowGraphImpl(
|
||||
override val function: IrFunction,
|
||||
override val blocks: List<BasicBlock>,
|
||||
override val connectors: List<BlockConnector>
|
||||
) : ControlFlowGraph
|
||||
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* 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.IrStatement
|
||||
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<IrStatement, BasicBlockBuilder>()
|
||||
|
||||
private var currentBlockBuilder: BasicBlockBuilder? = null
|
||||
|
||||
private val blocks = mutableListOf<BasicBlock>()
|
||||
|
||||
private val connectorBuilderMap = mutableMapOf<IrStatement, BlockConnectorBuilder>()
|
||||
|
||||
private fun createBlockBuilder(after: BlockConnectorBuilder?): BasicBlockBuilder {
|
||||
val result = GeneralBlockBuilder(after)
|
||||
currentBlockBuilder = result
|
||||
return result
|
||||
}
|
||||
|
||||
private fun BasicBlockBuilder.shiftTo(element: IrStatement) {
|
||||
blockBuilderMap.remove(last)
|
||||
add(element)
|
||||
blockBuilderMap[element] = this
|
||||
}
|
||||
|
||||
override fun add(element: IrStatement) {
|
||||
val blockBuilder = currentBlockBuilder ?: createBlockBuilder(connectorBuilderMap[element])
|
||||
blockBuilder.shiftTo(element)
|
||||
}
|
||||
|
||||
override fun move(to: IrStatement) {
|
||||
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: IrStatement) {
|
||||
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: IrStatement, from: IrStatement) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
-201
@@ -1,201 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.ir2cfg.generators
|
||||
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.types.isNothing
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.ir2cfg.graph.ControlFlowGraph
|
||||
import org.jetbrains.kotlin.ir2cfg.nodes.MergeCfgElement
|
||||
|
||||
class FunctionGenerator(val function: IrFunction) {
|
||||
|
||||
val builder = FunctionBuilder(function)
|
||||
|
||||
val exit = MergeCfgElement(function, "Function exit")
|
||||
|
||||
val loopEntries = mutableMapOf<IrLoop, IrStatement>()
|
||||
|
||||
val loopExits = mutableMapOf<IrLoop, IrStatement>()
|
||||
|
||||
fun generate(): ControlFlowGraph {
|
||||
val visitor = FunctionVisitor()
|
||||
function.accept(visitor, true)
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
inner class FunctionVisitor : IrElementVisitor<IrStatement?, Boolean> {
|
||||
|
||||
private inline fun <reified IE : IrElement> IE.process(includeSelf: Boolean = true) = this.accept(this@FunctionVisitor, includeSelf)
|
||||
|
||||
override fun visitFunction(declaration: IrFunction, data: Boolean): IrStatement? {
|
||||
if (data) {
|
||||
builder.add(declaration)
|
||||
}
|
||||
val result = declaration.body?.process() ?: if (data) declaration else null
|
||||
if (result != null && !result.isNothing()) {
|
||||
builder.jump(exit, from = result)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun IrStatementContainer.process(): IrStatement? {
|
||||
var result: IrStatement? = null
|
||||
for (statement in statements) {
|
||||
result = statement.process()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun IrElement?.isNothing() = this is IrExpression && type.isNothing()
|
||||
|
||||
override fun visitBlockBody(body: IrBlockBody, data: Boolean): IrStatement? {
|
||||
return body.process()
|
||||
}
|
||||
|
||||
override fun visitContainerExpression(expression: IrContainerExpression, data: Boolean): IrStatement? {
|
||||
return expression.process() ?: expression
|
||||
}
|
||||
|
||||
override fun visitVariable(declaration: IrVariable, data: Boolean): IrStatement? {
|
||||
declaration.initializer?.process()
|
||||
return if (data) {
|
||||
builder.add(declaration)
|
||||
declaration
|
||||
} else null
|
||||
}
|
||||
|
||||
override fun visitReturn(expression: IrReturn, data: Boolean): IrStatement? {
|
||||
expression.value.process()
|
||||
if (data) {
|
||||
builder.add(expression)
|
||||
}
|
||||
builder.jump(exit)
|
||||
return expression
|
||||
}
|
||||
|
||||
override fun visitExpressionBody(body: IrExpressionBody, data: Boolean): IrStatement? {
|
||||
return body.expression.process()
|
||||
}
|
||||
|
||||
override fun visitExpression(expression: IrExpression, data: Boolean): IrStatement? {
|
||||
if (data) {
|
||||
builder.add(expression)
|
||||
}
|
||||
return expression
|
||||
}
|
||||
|
||||
override fun visitWhen(expression: IrWhen, data: Boolean): IrStatement? {
|
||||
if (data) {
|
||||
builder.add(expression)
|
||||
}
|
||||
val whenExit = MergeCfgElement(expression, "When exit")
|
||||
val branches = expression.branches
|
||||
for (branch in branches) {
|
||||
val condition = branch.condition
|
||||
condition.process(includeSelf = false)
|
||||
builder.jump(condition)
|
||||
}
|
||||
for (branch in branches) {
|
||||
val result = branch.result
|
||||
builder.move(branch.condition)
|
||||
if (!result.process().isNothing()) {
|
||||
builder.jump(whenExit)
|
||||
} else {
|
||||
builder.move(branch.condition)
|
||||
}
|
||||
}
|
||||
return whenExit
|
||||
}
|
||||
|
||||
override fun visitWhileLoop(loop: IrWhileLoop, data: Boolean): IrStatement? {
|
||||
if (data) {
|
||||
builder.add(loop)
|
||||
}
|
||||
val exit = MergeCfgElement(loop, "While exit")
|
||||
loopExits[loop] = exit
|
||||
val entry = MergeCfgElement(loop, "While entry")
|
||||
loopEntries[loop] = entry
|
||||
builder.jump(entry)
|
||||
val condition = loop.condition
|
||||
condition.process(includeSelf = false)
|
||||
builder.jump(condition)
|
||||
val body = loop.body
|
||||
if (!body?.process().isNothing()) {
|
||||
builder.jump(entry)
|
||||
}
|
||||
builder.jump(exit, from = condition)
|
||||
return exit
|
||||
}
|
||||
|
||||
override fun visitDoWhileLoop(loop: IrDoWhileLoop, data: Boolean): IrStatement? {
|
||||
if (data) {
|
||||
builder.add(loop)
|
||||
}
|
||||
val exit = MergeCfgElement(loop, "Do..while exit")
|
||||
loopExits[loop] = exit
|
||||
val entry = MergeCfgElement(loop, "Do..while entry")
|
||||
loopEntries[loop] = entry
|
||||
builder.jump(entry)
|
||||
val body = loop.body
|
||||
val condition = loop.condition
|
||||
if (!body?.process().isNothing()) {
|
||||
condition.process(includeSelf = false)
|
||||
builder.jump(condition)
|
||||
builder.jump(entry, from = condition)
|
||||
builder.jump(exit, from = condition)
|
||||
}
|
||||
builder.move(exit)
|
||||
return exit
|
||||
}
|
||||
|
||||
override fun visitBreak(jump: IrBreak, data: Boolean): IrStatement? {
|
||||
if (data) {
|
||||
builder.add(jump)
|
||||
}
|
||||
builder.jump(loopExits[jump.loop] ?: throw AssertionError("Loop exit not found for ${jump.loop.dump()}"))
|
||||
return jump
|
||||
}
|
||||
|
||||
override fun visitContinue(jump: IrContinue, data: Boolean): IrStatement? {
|
||||
if (data) {
|
||||
builder.add(jump)
|
||||
}
|
||||
builder.jump(loopEntries[jump.loop] ?: throw AssertionError("Loop entry not found for ${jump.loop.dump()}"))
|
||||
return jump
|
||||
}
|
||||
|
||||
override fun visitMemberAccess(expression: IrMemberAccessExpression<*>, data: Boolean): IrStatement? {
|
||||
expression.dispatchReceiver?.process()
|
||||
expression.extensionReceiver?.process()
|
||||
val callee = expression.symbol.owner as IrFunction
|
||||
for (valueParameter in callee.valueParameters) {
|
||||
expression.getValueArgument(valueParameter.index)?.process()
|
||||
}
|
||||
if (data) {
|
||||
builder.add(expression)
|
||||
}
|
||||
return expression
|
||||
}
|
||||
|
||||
override fun visitTypeOperator(expression: IrTypeOperatorCall, data: Boolean): IrStatement? {
|
||||
expression.argument.process()
|
||||
if (data) {
|
||||
builder.add(expression)
|
||||
}
|
||||
return expression
|
||||
}
|
||||
|
||||
override fun visitElement(element: IrElement, data: Boolean): IrStatement? {
|
||||
TODO("not implemented")
|
||||
}
|
||||
}
|
||||
}
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* 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.IrStatement
|
||||
import org.jetbrains.kotlin.ir2cfg.builders.BasicBlockBuilder
|
||||
import org.jetbrains.kotlin.ir2cfg.builders.BlockConnectorBuilder
|
||||
|
||||
class GeneralBlockBuilder(override val incoming: BlockConnectorBuilder?) : BasicBlockBuilder {
|
||||
|
||||
private val elements = mutableListOf<IrStatement>()
|
||||
|
||||
override fun add(element: IrStatement) {
|
||||
elements.add(element)
|
||||
}
|
||||
|
||||
override val last: IrStatement?
|
||||
get() = elements.lastOrNull()
|
||||
|
||||
override fun build() = BasicBlockImpl(elements.toList())
|
||||
}
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* 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.IrStatement
|
||||
import org.jetbrains.kotlin.ir2cfg.builders.BlockConnectorBuilder
|
||||
import org.jetbrains.kotlin.ir2cfg.graph.BasicBlock
|
||||
|
||||
class GeneralConnectorBuilder(private val element: IrStatement) : BlockConnectorBuilder {
|
||||
|
||||
private val next = linkedSetOf<BasicBlock>()
|
||||
|
||||
private val previous = linkedSetOf<BasicBlock>()
|
||||
|
||||
override fun addNext(basicBlock: BasicBlock) {
|
||||
next.add(basicBlock)
|
||||
}
|
||||
|
||||
override fun addPrevious(basicBlock: BasicBlock) {
|
||||
previous.add(basicBlock)
|
||||
}
|
||||
|
||||
override fun build() = when {
|
||||
next.size <= 1 -> JoinBlockConnector(previous.toList(), element, next.firstOrNull())
|
||||
previous.size == 1 -> SplitBlockConnector(previous.single(), element, next.toList())
|
||||
else -> throw AssertionError("Connector should have either exactly one previous block or no more than one next block, " +
|
||||
"actual previous = ${previous.size}, next = ${next.size}")
|
||||
}
|
||||
}
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* 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.IrStatement
|
||||
import org.jetbrains.kotlin.ir2cfg.graph.BasicBlock
|
||||
import org.jetbrains.kotlin.ir2cfg.graph.BlockConnector
|
||||
|
||||
class JoinBlockConnector(
|
||||
override val previousBlocks: List<BasicBlock>,
|
||||
override val element: IrStatement,
|
||||
next: BasicBlock?
|
||||
) : BlockConnector {
|
||||
|
||||
override val nextBlocks = listOfNotNull(next)
|
||||
}
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* 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.IrStatement
|
||||
import org.jetbrains.kotlin.ir2cfg.graph.BasicBlock
|
||||
import org.jetbrains.kotlin.ir2cfg.graph.BlockConnector
|
||||
|
||||
class SplitBlockConnector(
|
||||
previous: BasicBlock,
|
||||
override val element: IrStatement,
|
||||
override val nextBlocks: List<BasicBlock>
|
||||
) : BlockConnector {
|
||||
|
||||
override val previousBlocks = listOf(previous)
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* 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.graph
|
||||
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
|
||||
interface BasicBlock : CfgNode {
|
||||
|
||||
val elements: List<IrStatement>
|
||||
|
||||
val incoming: BlockConnector?
|
||||
|
||||
val outgoing: BlockConnector?
|
||||
|
||||
override val predecessors: List<CfgNode>
|
||||
get() = listOfNotNull(incoming)
|
||||
|
||||
override val successors: List<CfgNode>
|
||||
get() = listOfNotNull(outgoing)
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* 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.graph
|
||||
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
|
||||
interface BlockConnector : CfgNode {
|
||||
|
||||
val previousBlocks: List<BasicBlock>
|
||||
|
||||
val element: IrStatement
|
||||
|
||||
val nextBlocks: List<BasicBlock>
|
||||
|
||||
override val predecessors: List<CfgNode>
|
||||
get() = previousBlocks
|
||||
|
||||
override val successors: List<CfgNode>
|
||||
get() = nextBlocks
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* 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.graph
|
||||
|
||||
interface CfgNode {
|
||||
|
||||
val predecessors: List<CfgNode>
|
||||
|
||||
val successors: List<CfgNode>
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* 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.graph
|
||||
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
|
||||
interface ControlFlowGraph {
|
||||
|
||||
val function: IrFunction
|
||||
|
||||
// First block is the entry point
|
||||
val blocks: List<BasicBlock>
|
||||
|
||||
val connectors: List<BlockConnector>
|
||||
|
||||
val nodes: List<CfgNode>
|
||||
get() = blocks + connectors
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* 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.nodes
|
||||
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
|
||||
interface CfgIrElement : IrStatement
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* 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.nodes
|
||||
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
|
||||
class MergeCfgElement(val from: IrElement, val name: String) : CfgIrElement {
|
||||
override val startOffset = from.startOffset
|
||||
override val endOffset = from.endOffset
|
||||
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D) = visitor.visitElement(this, data)
|
||||
|
||||
override fun <D> transform(transformer: IrElementTransformer<D>, data: D): IrElement = accept(transformer, data)
|
||||
|
||||
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) = Unit
|
||||
|
||||
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) = Unit
|
||||
|
||||
override fun toString() = "$name: ${from.dump()}"
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* 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.util
|
||||
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.ir2cfg.graph.BasicBlock
|
||||
import org.jetbrains.kotlin.ir2cfg.graph.BlockConnector
|
||||
import org.jetbrains.kotlin.ir2cfg.graph.ControlFlowGraph
|
||||
import org.jetbrains.kotlin.ir2cfg.nodes.MergeCfgElement
|
||||
|
||||
private fun IrElement.cfgDump() = when (this) {
|
||||
is MergeCfgElement -> "$this"
|
||||
else -> dump()
|
||||
}
|
||||
|
||||
fun BasicBlock.dump(builder: StringBuilder = StringBuilder(), indent: String = ""): String {
|
||||
for ((index, element) in elements.withIndex()) {
|
||||
builder.append(indent)
|
||||
builder.append(String.format("%3d ", index + 1))
|
||||
val dump = element.cfgDump()
|
||||
builder.appendLine(dump.lines().first())
|
||||
}
|
||||
return builder.toString()
|
||||
}
|
||||
|
||||
fun BlockConnector.dump(builder: StringBuilder = StringBuilder(), indent: String = ""): String {
|
||||
builder.append(indent)
|
||||
val dump = element.cfgDump()
|
||||
builder.appendLine(dump.lines().first())
|
||||
return builder.toString()
|
||||
}
|
||||
|
||||
fun ControlFlowGraph.dump(): String {
|
||||
val connectorIndex = hashMapOf<BlockConnector, Int>()
|
||||
for ((index, connector) in connectors.withIndex()) {
|
||||
connectorIndex[connector] = index
|
||||
}
|
||||
val blockIndex = hashMapOf<BasicBlock, Int>()
|
||||
for ((index, block) in blocks.withIndex()) {
|
||||
blockIndex[block] = index
|
||||
}
|
||||
val builder = StringBuilder()
|
||||
for ((index, block) in blocks.withIndex()) {
|
||||
builder.appendLine("BB $index")
|
||||
val incoming = block.incoming
|
||||
if (incoming != null) {
|
||||
builder.appendLine(incoming.previousBlocks.joinToString(prefix = "INCOMING <- BB ") { blockIndex[it].toString() })
|
||||
incoming.dump(builder, " ")
|
||||
}
|
||||
builder.appendLine("CONTENT")
|
||||
block.dump(builder, " ")
|
||||
val outgoing = block.outgoing
|
||||
if (outgoing != null) {
|
||||
if (outgoing.nextBlocks.isEmpty()) {
|
||||
builder.appendLine("OUTGOING -> NONE")
|
||||
}
|
||||
else {
|
||||
builder.appendLine(outgoing.nextBlocks.joinToString(prefix = "OUTGOING -> BB ") { blockIndex[it].toString() })
|
||||
}
|
||||
outgoing.dump(builder, " ")
|
||||
}
|
||||
}
|
||||
return builder.toString()
|
||||
}
|
||||
Reference in New Issue
Block a user