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 e5e073f2f18..691b1d4ef42 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 @@ -1387,19 +1387,19 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid var bbExit : LLVMBasicBlockRef? = null var resultPhi : LLVMValueRef? = null - fun getExit(): LLVMBasicBlockRef? { + fun getExit(): LLVMBasicBlockRef { if (bbExit == null) bbExit = codegen.basicBlock("inline_body_exit") - return bbExit + return bbExit!! } - fun getResult(): LLVMValueRef? { + fun getResult(): LLVMValueRef { if (resultPhi == null) { val bbCurrent = codegen.currentBlock - codegen.positionAtEnd(getExit()!!) + codegen.positionAtEnd(getExit()) resultPhi = codegen.phi(codegen.getLLVMType(inlineBody.type)) codegen.positionAtEnd(bbCurrent) } - return resultPhi + return resultPhi!! } override fun genReturn(target: CallableDescriptor, value: LLVMValueRef?) { @@ -1411,7 +1411,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid codegen.br(getExit()!!) // Generate branch on exit block. if (KotlinBuiltIns.isUnit(inlineBody.type) == false) { // If function returns more then "unit" - codegen.assignPhis(getResult()!! to value!!) // Assign return value to result PHI node. + codegen.assignPhis(getResult() to value!!) // Assign return value to result PHI node. } } } 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 4d1e02071de..cc67547d500 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 @@ -86,8 +86,8 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid( //-------------------------------------------------------------------------// - fun getArguments(irCall: IrCall): List> { - val result = mutableListOf>() + fun getArguments(irCall: IrCall): MutableMap { + val result = mutableMapOf() val descriptor = irCall.descriptor.original irCall.dispatchReceiver?.let { @@ -110,14 +110,13 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid( //-------------------------------------------------------------------------// - fun evaluateParameters(irCall: IrCall, statements: MutableList): MutableMap { + fun evaluateParameters(parametersOld: MutableMap, + statements: MutableList): MutableMap { - val parametersOld = getArguments(irCall) // Create map call_site_argument -> inline_function_parameter. val parametersNew = mutableMapOf () - parametersOld.forEach { - val parameter = it.first.original - val argument = it.second + val parameter = it.key.original as ValueDescriptor + val argument = it.value if (!needsEvaluation(argument)) { parametersNew[parameter] = argument @@ -141,9 +140,9 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid( val functionDeclaration = context.ir.originalModuleIndex .functions[functionDescriptor.original] // Get FunctionDeclaration by FunctionDescriptor. - if (functionDeclaration == null) return irCall // Function is declared in another module. + if (functionDeclaration == null) return super.visitCall(irCall) // Function is declared in another module. - val copyFuncDeclaration = functionDeclaration.accept(DeepCopyIrTree(), // Create copy of the function. + val copyFuncDeclaration = functionDeclaration.accept(InlineCopyIr(), // Create copy of the function. null) as IrFunction val startOffset = copyFuncDeclaration.startOffset @@ -156,7 +155,8 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid( val inlineBody = IrInlineFunctionBody(startOffset, endOffset, returnType, null, statements) val evaluationStatements = mutableListOf() - val parameterToArgument = evaluateParameters(irCall, evaluationStatements) + val parametersOld = getArguments(irCall) // Create map call_site_argument -> inline_function_parameter. + val parameterToArgument = evaluateParameters(parametersOld, evaluationStatements) val lambdaInliner = LambdaInliner(parameterToArgument) inlineBody.transformChildrenVoid(lambdaInliner) @@ -340,7 +340,9 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid( val lambdaFunction = getLambdaFunction(lambdaArgument) if (lambdaFunction == null) return super.visitCall(irCall) // TODO - val parameterToArgument = buildParameterToArgument(lambdaFunction, irCall) + val parametersOld = buildParameterToArgument(lambdaFunction, irCall) + val evaluationStatements = mutableListOf() + val parameterToArgument = evaluateParameters(parametersOld, evaluationStatements) val lambdaStatements = (lambdaFunction.body as IrBlockBody).statements val lambdaReturnType = lambdaFunction.descriptor.returnType!! @@ -348,6 +350,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid( val transformer = ParametersTransformer(parameterToArgument, null, lambdaStatements) inlineBody.accept(transformer, null) // Replace parameters with expression. + inlineBody.statements.addAll(0, evaluationStatements) return inlineBody // Replace call site with InlineFunctionBody. } @@ -361,5 +364,28 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid( } } +//-----------------------------------------------------------------------------// + +class InlineCopyIr() : DeepCopyIrTree() { + + override fun visitBlock(expression: IrBlock): IrBlock { + + if (expression is IrInlineFunctionBody) + return IrInlineFunctionBody( + expression.startOffset, expression.endOffset, + expression.type, + mapStatementOrigin(expression.origin), + expression.statements.map { it.transform(this, null) } + ) + + return IrBlockImpl( + expression.startOffset, expression.endOffset, + expression.type, + mapStatementOrigin(expression.origin), + expression.statements.map { it.transform(this, null) } + ) + } +} +