From 67013f8a60346f6c6d432a8d528a4adcdc208cfe Mon Sep 17 00:00:00 2001 From: Konstantin Anisimov Date: Wed, 18 Jan 2017 17:22:14 +0700 Subject: [PATCH] Two passes inline scheme implemented --- .../kotlin/backend/konan/ir/KonanIr.kt | 38 +++++++++++- .../kotlin/backend/konan/llvm/IrToBitcode.kt | 62 ++++++++++++++++++- .../backend/konan/lower/FunctionInlining.kt | 13 +--- 3 files changed, 98 insertions(+), 15 deletions(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIr.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIr.kt index 4b978c127a9..f711be1b9e2 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIr.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/KonanIr.kt @@ -1,5 +1,37 @@ package org.jetbrains.kotlin.backend.konan.ir -/** - * Created by jetbrains on 13/01/2017. - */ +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.expressions.IrBlock +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin +import org.jetbrains.kotlin.ir.expressions.impl.IrContainerExpressionBase +import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBase +import org.jetbrains.kotlin.ir.visitors.IrElementTransformer +import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import org.jetbrains.kotlin.types.KotlinType + +//-----------------------------------------------------------------------------// + +class IrInlineFunctionBody(startOffset: Int, endOffset: Int, type: KotlinType, origin: IrStatementOrigin? = null): + IrContainerExpressionBase(startOffset, endOffset, type, origin), IrBlock { + constructor(startOffset: Int, endOffset: Int, type: KotlinType, origin: IrStatementOrigin?, statements: List) : + this(startOffset, endOffset, type, origin) { + this.statements.addAll(statements) + } + + override fun accept(visitor: IrElementVisitor, data: D): R = + visitor.visitBlock(this, data) + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + statements.forEach { it.accept(visitor, data) } + } + + override fun transformChildren(transformer: IrElementTransformer, data: D) { + statements.forEachIndexed { i, irStatement -> + statements[i] = irStatement.transform(transformer, data) + } + } +} + +//-----------------------------------------------------------------------------// + diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index 8e89ee3e285..05e87172719 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -629,6 +629,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid is IrThrow -> return evaluateThrow (value) is IrTry -> return evaluateTry (value) is IrStringConcatenation -> return evaluateStringConcatenation(value) + is IrInlineFunctionBody -> return evaluateInlineFunction (value) is IrContainerExpression -> return evaluateContainerExpression(value) is IrWhileLoop -> return evaluateWhileLoop (value) is IrDoWhileLoop -> return evaluateDoWhileLoop (value) @@ -741,7 +742,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid */ private fun continuationBlock(type: KotlinType, code: (ContinuationBlock) -> Unit = {}): ContinuationBlock { - val entry = codegen.basicBlock() + val entry = codegen.basicBlock("continuation_block") codegen.appendingTo(entry) { val valuePhi = if (type.isUnit()) { @@ -1479,6 +1480,65 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid //-------------------------------------------------------------------------// + private inner class InlinedFunctionScope(val inlineBody: IrInlineFunctionBody) : InnerScopeImpl() { + + var bbExit : LLVMBasicBlockRef? = null + var resultPhi : LLVMValueRef? = null + + fun getExit(): LLVMBasicBlockRef? { + if (bbExit == null) bbExit = codegen.basicBlock("inline_body_exit") + return bbExit + } + + fun getResult(): LLVMValueRef? { + if (resultPhi == null) { + val bbCurrent = codegen.currentBlock + codegen.positionAtEnd(getExit()!!) + resultPhi = codegen.phi(codegen.getLLVMType(inlineBody.type)) + codegen.positionAtEnd(bbCurrent) + } + return resultPhi + } + + override fun genReturn(target: CallableDescriptor, value: LLVMValueRef?) { + if (KotlinBuiltIns.isUnit(inlineBody.type) == false) { + codegen.assignPhis(getResult()!! to value!!) + } + codegen.br(getExit()!!) + } + } + + //-------------------------------------------------------------------------// + + private fun evaluateInlineFunction(value: IrInlineFunctionBody): LLVMValueRef { + context.log("evaluateInlineFunction : ${value.statements.forEach { ir2string(it) }}") + + val inlinedFunctionScope = InlinedFunctionScope(value) + using(inlinedFunctionScope) { + value.statements.forEach { + generateStatement(it) + } + } + + if (!codegen.isAfterTerminator()) { // TODO should we solve this problem once and for all + if (inlinedFunctionScope.resultPhi != null) { + codegen.unreachable() + } + } + + if (inlinedFunctionScope.bbExit != null) { + codegen.positionAtEnd(inlinedFunctionScope.bbExit!!) + } + + if (inlinedFunctionScope.resultPhi != null) { + return inlinedFunctionScope.resultPhi!! + } else { + return codegen.theUnitInstanceRef.llvm + } + } + + //-------------------------------------------------------------------------// + private fun evaluateContainerExpression(value: IrContainerExpression): LLVMValueRef { context.log("evaluateContainerExpression : ${value.statements.forEach { ir2string(it) }}") diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt index b1602490b8b..4e0d9f7433e 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/FunctionInlining.kt @@ -1,15 +1,14 @@ package org.jetbrains.kotlin.backend.konan.lower import org.jetbrains.kotlin.backend.konan.Context +import org.jetbrains.kotlin.backend.konan.ir.IrInlineFunctionBody import org.jetbrains.kotlin.backend.konan.ir.getArguments import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.ParameterDescriptor import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl import org.jetbrains.kotlin.ir.util.DeepCopyIrTree import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid @@ -34,7 +33,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid( val endOffset = copyFuncDeclaration.endOffset val returnType = copyFuncDeclaration.descriptor.returnType!! val statements = body.statements - val irBlock = IrBlockImpl(startOffset, endOffset, returnType, null, statements) // Create IrBlock containing function statements. + val irBlock = IrInlineFunctionBody(startOffset, endOffset, returnType, null, statements) val parameterToExpression = expression.getArguments() // Build map parameter -> expression. val parametersTransformer = ParametersTransformer(parameterToExpression) @@ -56,14 +55,6 @@ internal class ParametersTransformer(val parameterToExpression: List