New tests added

This commit is contained in:
Konstantin Anisimov
2017-03-14 17:19:06 +07:00
committed by KonstantinAnisimov
parent 39f002db81
commit 22b74c0a3a
4 changed files with 72 additions and 32 deletions
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
import org.jetbrains.kotlin.ir.util.DeepCopyIrTree import org.jetbrains.kotlin.ir.util.DeepCopyIrTree
import org.jetbrains.kotlin.ir.util.getArguments import org.jetbrains.kotlin.ir.util.getArguments
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
//-----------------------------------------------------------------------------// //-----------------------------------------------------------------------------//
@@ -70,7 +71,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
val functionDescriptor = expression.descriptor as FunctionDescriptor val functionDescriptor = expression.descriptor as FunctionDescriptor
if (functionDescriptor.isInline) { if (functionDescriptor.isInline) {
val inlineFunctionBody = inlineFunction(expression) val inlineFunctionBody = inlineFunction(expression)
// inlineFunctionBody.accept(this, null) // // inlineFunctionBody.transformChildrenVoid(this) // TODO
return inlineFunctionBody // Return newly created IrInlineBody instead of IrCall. return inlineFunctionBody // Return newly created IrInlineBody instead of IrCall.
} }
@@ -86,9 +87,9 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
.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 irCall // Function is declared in another module.
print(" inline file: ${currentFile!!.fileEntry.name} ") // TODO debug output // print(" inline file: ${currentFile!!.fileEntry.name} ") // TODO debug output
print("function: ${currentFunction!!.descriptor.name} ") // TODO debug output // print("function: ${currentFunction!!.descriptor.name} ") // TODO debug output
println("call: ${functionDescriptor.name} ${irCall.startOffset}") // TODO debug output // println("call: ${functionDescriptor.name} ${irCall.startOffset}") // TODO debug output
val copyFuncDeclaration = functionDeclaration.accept(DeepCopyIrTree(), // Create copy of the function. val copyFuncDeclaration = functionDeclaration.accept(DeepCopyIrTree(), // Create copy of the function.
null) as IrFunction null) as IrFunction
@@ -102,17 +103,16 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
val statements = blockBody.statements val statements = blockBody.statements
val inlineBody = IrInlineFunctionBody(startOffset, endOffset, returnType, null, statements) val inlineBody = IrInlineFunctionBody(startOffset, endOffset, returnType, null, statements)
val parameterToArgument: MutableList <Pair <ValueDescriptor, IrExpression>> = irCall.getArguments().toMutableList() val parameterToArgument: MutableList <Pair <ValueDescriptor, IrExpression>> = irCall.getArguments().toMutableList()
val typeArgsMap = (irCall as IrMemberAccessExpressionBase).typeArguments // If there are no type args - do nothing. val lambdaInliner = LambdaInliner(parameterToArgument)
inlineBody.transformChildrenVoid(lambdaInliner)
val typeArgsMap = (irCall as IrMemberAccessExpressionBase).typeArguments
val statementsBuf = mutableListOf<IrStatement>() val statementsBuf = mutableListOf<IrStatement>()
val transformer = ParametersTransformer(parameterToArgument, typeArgsMap, statementsBuf) val transformer = ParametersTransformer(parameterToArgument, typeArgsMap, statementsBuf)
inlineBody.accept(transformer, null) // Replace parameters with expression. inlineBody.transformChildrenVoid(transformer) // Replace parameters with expression.
inlineBody.statements.addAll(0, statementsBuf) inlineBody.statements.addAll(0, statementsBuf)
val lambdaInliner = LambdaInliner(parameterToArgument)
inlineBody.accept(lambdaInliner, null)
return inlineBody return inlineBody
} }
@@ -251,51 +251,51 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
//---------------------------------------------------------------------// //---------------------------------------------------------------------//
fun getLambdaFunction(lambdaArgument: IrExpression): IrFunction? { fun getLambdaFunction(lambdaArgument: IrExpression): IrFunction? {
if (lambdaArgument !is IrBlock) return null if (lambdaArgument !is IrBlock) return null
if (lambdaArgument.origin != IrStatementOrigin.ANONYMOUS_FUNCTION && if (lambdaArgument.origin != IrStatementOrigin.ANONYMOUS_FUNCTION &&
lambdaArgument.origin != IrStatementOrigin.LAMBDA) { lambdaArgument.origin != IrStatementOrigin.LAMBDA) {
return null return null
} }
// TODO: the following checks must be asserts, however it is not sane until the bugs are fixed. // TODO: the following checks must be asserts, however it is not sane until the bugs are fixed.
val statements = lambdaArgument.statements val statements = lambdaArgument.statements
if (statements.size != 2) return null if (statements.size != 2) return null
val irFunction = statements[0] val irFunction = statements[0]
if (irFunction !is IrFunction) return null // TODO if (irFunction !is IrFunction) return null // TODO
val irCallableReference = statements[1] val irCallableReference = statements[1]
if (irCallableReference !is IrCallableReference || if (irCallableReference !is IrCallableReference ||
irCallableReference.descriptor.original != irFunction.descriptor || irCallableReference.descriptor.original != irFunction.descriptor ||
irCallableReference.getArguments().isNotEmpty()) { irCallableReference.getArguments().isNotEmpty()) {
return null return null
} }
return irFunction return irFunction
} }
//---------------------------------------------------------------------// //---------------------------------------------------------------------//
fun inlineLambda(irCall: IrCall): IrExpression { fun inlineLambda(irCall: IrCall): IrExpression {
val dispatchReceiver = irCall.dispatchReceiver as IrGetValue // val dispatchReceiver = irCall.dispatchReceiver as IrGetValue //
val substitute = substituteMap.find { // Find expression to replace this parameter. val substitute = substituteMap.find { // Find expression to replace this parameter.
it.first == dispatchReceiver.descriptor it.first == dispatchReceiver.descriptor
} }
if (substitute == null) return super.visitCall(irCall) // It is not function parameter - nothing to substitute. if (substitute == null) return super.visitCall(irCall) // It is not function parameter - nothing to substitute.
val lambdaArgument = substitute.second val lambdaArgument = substitute.second
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 parameters = lambdaFunction.descriptor.valueParameters // Get lambda function parameters. val parameters = lambdaFunction.descriptor.valueParameters // Get lambda function parameters.
val substituteMap = parameters.map { // Iterate parameters. val substituteMap = parameters.map { // Iterate parameters.
val parameter = it as ValueDescriptor val parameter = it as ValueDescriptor
val argument = irCall.getValueArgument(it.index) // Get corresponding argument. val argument = irCall.getValueArgument(it.index) // Get corresponding argument.
parameter to argument!! // Create (parameter -> argument) pair. parameter to argument!! // Create (parameter -> argument) pair.
+10
View File
@@ -1454,6 +1454,11 @@ task inline10(type: RunKonanTest) {
source = "codegen/inline/inline10.kt" source = "codegen/inline/inline10.kt"
} }
task inline13(type: RunKonanTest) {
goldValue = "true\n"
source = "codegen/inline/inline13.kt"
}
task inline14(type: RunKonanTest) { task inline14(type: RunKonanTest) {
goldValue = "9\n" goldValue = "9\n"
source = "codegen/inline/inline14.kt" source = "codegen/inline/inline14.kt"
@@ -1498,6 +1503,11 @@ task inline21(type: RunKonanTest) {
source = "codegen/inline/inline21.kt" source = "codegen/inline/inline21.kt"
} }
task inline22(type: RunKonanTest) {
goldValue = "14\n"
source = "codegen/inline/inline22.kt"
}
kotlinNativeInterop { kotlinNativeInterop {
sysstat { sysstat {
pkg 'sysstat' pkg 'sysstat'
@@ -0,0 +1,15 @@
open class A<T1>()
class B<T2>() : A<T2>()
@Suppress("NOTHING_TO_INLINE")
inline fun <reified T: A<*>> foo(f: Any?): Boolean {
return f is T?
}
fun bar(): Boolean {
return foo<B<Int>>(B<Int>())
}
fun main(args: Array<String>) {
println(bar().toString())
}
@@ -0,0 +1,15 @@
inline fun foo2(i2: Int): Int {
return i2 + 3
}
inline fun foo1(i1: Int): Int {
return foo2(i1)
}
fun bar(): Int {
return foo1(11)
}
fun main(args: Array<String>) {
println(bar().toString())
}