Evaluation of lambda arguments
DeepCopyIrTree with IrInlineFunctionBody support
This commit is contained in:
committed by
KonstantinAnisimov
parent
1be913de63
commit
edd8489f6b
+6
-6
@@ -1387,19 +1387,19 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
var bbExit : LLVMBasicBlockRef? = null
|
var bbExit : LLVMBasicBlockRef? = null
|
||||||
var resultPhi : LLVMValueRef? = null
|
var resultPhi : LLVMValueRef? = null
|
||||||
|
|
||||||
fun getExit(): LLVMBasicBlockRef? {
|
fun getExit(): LLVMBasicBlockRef {
|
||||||
if (bbExit == null) bbExit = codegen.basicBlock("inline_body_exit")
|
if (bbExit == null) bbExit = codegen.basicBlock("inline_body_exit")
|
||||||
return bbExit
|
return bbExit!!
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getResult(): LLVMValueRef? {
|
fun getResult(): LLVMValueRef {
|
||||||
if (resultPhi == null) {
|
if (resultPhi == null) {
|
||||||
val bbCurrent = codegen.currentBlock
|
val bbCurrent = codegen.currentBlock
|
||||||
codegen.positionAtEnd(getExit()!!)
|
codegen.positionAtEnd(getExit())
|
||||||
resultPhi = codegen.phi(codegen.getLLVMType(inlineBody.type))
|
resultPhi = codegen.phi(codegen.getLLVMType(inlineBody.type))
|
||||||
codegen.positionAtEnd(bbCurrent)
|
codegen.positionAtEnd(bbCurrent)
|
||||||
}
|
}
|
||||||
return resultPhi
|
return resultPhi!!
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun genReturn(target: CallableDescriptor, value: LLVMValueRef?) {
|
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.
|
codegen.br(getExit()!!) // Generate branch on exit block.
|
||||||
|
|
||||||
if (KotlinBuiltIns.isUnit(inlineBody.type) == false) { // If function returns more then "unit"
|
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.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+37
-11
@@ -86,8 +86,8 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
fun getArguments(irCall: IrCall): List<Pair<ParameterDescriptor, IrExpression>> {
|
fun getArguments(irCall: IrCall): MutableMap<ValueDescriptor, IrExpression> {
|
||||||
val result = mutableListOf<Pair<ParameterDescriptor, IrExpression>>()
|
val result = mutableMapOf<ValueDescriptor, IrExpression>()
|
||||||
val descriptor = irCall.descriptor.original
|
val descriptor = irCall.descriptor.original
|
||||||
|
|
||||||
irCall.dispatchReceiver?.let {
|
irCall.dispatchReceiver?.let {
|
||||||
@@ -110,14 +110,13 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
fun evaluateParameters(irCall: IrCall, statements: MutableList<IrStatement>): MutableMap<ValueDescriptor, IrExpression> {
|
fun evaluateParameters(parametersOld: MutableMap<ValueDescriptor, IrExpression>,
|
||||||
|
statements: MutableList<IrStatement>): MutableMap<ValueDescriptor, IrExpression> {
|
||||||
|
|
||||||
val parametersOld = getArguments(irCall) // Create map call_site_argument -> inline_function_parameter.
|
|
||||||
val parametersNew = mutableMapOf<ValueDescriptor, IrExpression> ()
|
val parametersNew = mutableMapOf<ValueDescriptor, IrExpression> ()
|
||||||
|
|
||||||
parametersOld.forEach {
|
parametersOld.forEach {
|
||||||
val parameter = it.first.original
|
val parameter = it.key.original as ValueDescriptor
|
||||||
val argument = it.second
|
val argument = it.value
|
||||||
|
|
||||||
if (!needsEvaluation(argument)) {
|
if (!needsEvaluation(argument)) {
|
||||||
parametersNew[parameter] = argument
|
parametersNew[parameter] = argument
|
||||||
@@ -141,9 +140,9 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
|
|||||||
val functionDeclaration = context.ir.originalModuleIndex
|
val functionDeclaration = context.ir.originalModuleIndex
|
||||||
.functions[functionDescriptor.original] // Get FunctionDeclaration by FunctionDescriptor.
|
.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
|
null) as IrFunction
|
||||||
|
|
||||||
val startOffset = copyFuncDeclaration.startOffset
|
val startOffset = copyFuncDeclaration.startOffset
|
||||||
@@ -156,7 +155,8 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
|
|||||||
val inlineBody = IrInlineFunctionBody(startOffset, endOffset, returnType, null, statements)
|
val inlineBody = IrInlineFunctionBody(startOffset, endOffset, returnType, null, statements)
|
||||||
|
|
||||||
val evaluationStatements = mutableListOf<IrStatement>()
|
val evaluationStatements = mutableListOf<IrStatement>()
|
||||||
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)
|
val lambdaInliner = LambdaInliner(parameterToArgument)
|
||||||
inlineBody.transformChildrenVoid(lambdaInliner)
|
inlineBody.transformChildrenVoid(lambdaInliner)
|
||||||
|
|
||||||
@@ -340,7 +340,9 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
|
|||||||
val lambdaFunction = getLambdaFunction(lambdaArgument)
|
val lambdaFunction = getLambdaFunction(lambdaArgument)
|
||||||
if (lambdaFunction == null) return super.visitCall(irCall) // TODO
|
if (lambdaFunction == null) return super.visitCall(irCall) // TODO
|
||||||
|
|
||||||
val parameterToArgument = buildParameterToArgument(lambdaFunction, irCall)
|
val parametersOld = buildParameterToArgument(lambdaFunction, irCall)
|
||||||
|
val evaluationStatements = mutableListOf<IrStatement>()
|
||||||
|
val parameterToArgument = evaluateParameters(parametersOld, evaluationStatements)
|
||||||
|
|
||||||
val lambdaStatements = (lambdaFunction.body as IrBlockBody).statements
|
val lambdaStatements = (lambdaFunction.body as IrBlockBody).statements
|
||||||
val lambdaReturnType = lambdaFunction.descriptor.returnType!!
|
val lambdaReturnType = lambdaFunction.descriptor.returnType!!
|
||||||
@@ -348,6 +350,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
|
|||||||
|
|
||||||
val transformer = ParametersTransformer(parameterToArgument, null, lambdaStatements)
|
val transformer = ParametersTransformer(parameterToArgument, null, lambdaStatements)
|
||||||
inlineBody.accept(transformer, null) // Replace parameters with expression.
|
inlineBody.accept(transformer, null) // Replace parameters with expression.
|
||||||
|
inlineBody.statements.addAll(0, evaluationStatements)
|
||||||
|
|
||||||
return inlineBody // Replace call site with InlineFunctionBody.
|
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) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user