IR to CFG: function generator (initial version)
This commit is contained in:
committed by
Dmitry Petrov
parent
ae96afb1dc
commit
bab0abeee6
+109
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* 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.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
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.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")
|
||||||
|
|
||||||
|
fun generate(): ControlFlowGraph {
|
||||||
|
val visitor = FunctionVisitor()
|
||||||
|
function.accept(visitor, true)
|
||||||
|
return builder.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class FunctionVisitor : IrElementVisitor<IrElement?, Boolean> {
|
||||||
|
|
||||||
|
inline fun <reified IE : IrElement> IE.process(includeSelf: Boolean = true) = this.accept(this@FunctionVisitor, includeSelf)
|
||||||
|
|
||||||
|
override fun visitFunction(declaration: IrFunction, data: Boolean): IrElement? {
|
||||||
|
if (data) {
|
||||||
|
builder.add(declaration)
|
||||||
|
}
|
||||||
|
val result = declaration.body?.process()
|
||||||
|
if (result != null && !result.isNothing()) {
|
||||||
|
builder.jump(exit, from = result)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrStatementContainer.process(): IrElement? {
|
||||||
|
var result: IrElement? = null
|
||||||
|
for (statement in statements) {
|
||||||
|
result = statement.process()
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrElement?.isNothing() = this is IrExpression && KotlinBuiltIns.isNothing(type)
|
||||||
|
|
||||||
|
override fun visitBlockBody(body: IrBlockBody, data: Boolean): IrElement? {
|
||||||
|
return body.process() ?: body
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitBlock(expression: IrBlock, data: Boolean): IrElement? {
|
||||||
|
return expression.process() ?: expression
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitVariable(declaration: IrVariable, data: Boolean): IrElement? {
|
||||||
|
declaration.initializer?.process()
|
||||||
|
return if (data) {
|
||||||
|
builder.add(declaration)
|
||||||
|
declaration
|
||||||
|
}
|
||||||
|
else null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitReturn(expression: IrReturn, data: Boolean): IrElement? {
|
||||||
|
expression.value.process()
|
||||||
|
if (data) {
|
||||||
|
builder.add(expression)
|
||||||
|
}
|
||||||
|
builder.jump(exit)
|
||||||
|
return expression
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitExpressionBody(body: IrExpressionBody, data: Boolean): IrElement? {
|
||||||
|
if (data) {
|
||||||
|
builder.add(body)
|
||||||
|
}
|
||||||
|
return body.expression.process()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitExpression(expression: IrExpression, data: Boolean): IrElement? {
|
||||||
|
if (data) {
|
||||||
|
builder.add(expression)
|
||||||
|
}
|
||||||
|
return expression
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitElement(element: IrElement, data: Boolean): IrElement? {
|
||||||
|
TODO("not implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
interface CfgIrElement : IrElement
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* 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> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) = Unit
|
||||||
|
|
||||||
|
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) = Unit
|
||||||
|
|
||||||
|
override fun toString() = "$name: ${from.dump()}"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user