New tests added
This commit is contained in:
committed by
KonstantinAnisimov
parent
39f002db81
commit
22b74c0a3a
+32
-32
@@ -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.
|
||||||
|
|||||||
@@ -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())
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user