This commit is contained in:
Igor Chevdar
2021-01-12 19:23:13 +05:00
committed by Nikolay Krasko
parent aed23ff098
commit 1222b72dcd
4 changed files with 45 additions and 20 deletions
@@ -5,35 +5,46 @@
package org.jetbrains.kotlin.backend.konan.lower package org.jetbrains.kotlin.backend.konan.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.ir.Symbols import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.backend.common.lower.IrBuildingTransformer
import org.jetbrains.kotlin.backend.common.lower.at import org.jetbrains.kotlin.backend.common.lower.at
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.renderCompilerError import org.jetbrains.kotlin.backend.konan.renderCompilerError
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationBase
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.util.file
import org.jetbrains.kotlin.ir.util.irCall import org.jetbrains.kotlin.ir.util.irCall
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
/** /**
* This pass runs after inlining and performs the following additional transformations over some operations: * This pass runs after inlining and performs the following additional transformations over some operations:
* - Convert immutableBlobOf() arguments to special IrConst. * - Convert immutableBlobOf() arguments to special IrConst.
* - Convert `obj::class` and `Class::class` to calls. * - Convert `obj::class` and `Class::class` to calls.
*/ */
internal class PostInlineLowering(val context: Context) : FileLoweringPass { internal class PostInlineLowering(val context: Context) : BodyLoweringPass {
private val symbols get() = context.ir.symbols private val symbols get() = context.ir.symbols
override fun lower(irFile: IrFile) { override fun lower(irBody: IrBody, container: IrDeclaration) {
irFile.transformChildrenVoid(object : IrBuildingTransformer(context) { val irFile = container.file
irBody.transformChildren(object : IrElementTransformer<IrBuilderWithScope> {
override fun visitDeclaration(declaration: IrDeclarationBase, data: IrBuilderWithScope) =
super.visitDeclaration(declaration,
data = (declaration as? IrSymbolOwner)?.let { context.createIrBuilder(it.symbol, it.startOffset, it.endOffset) }
?: data
)
override fun visitClassReference(expression: IrClassReference): IrExpression { override fun visitClassReference(expression: IrClassReference, data: IrBuilderWithScope): IrExpression {
expression.transformChildrenVoid() expression.transformChildren(this, data)
return builder.at(expression).run { return data.at(expression).run {
(expression.symbol as? IrClassSymbol)?.let { irKClass(this@PostInlineLowering.context, it) } (expression.symbol as? IrClassSymbol)?.let { irKClass(this@PostInlineLowering.context, it) }
?: ?:
// E.g. for `T::class` in a body of an inline function itself. // E.g. for `T::class` in a body of an inline function itself.
@@ -41,10 +52,10 @@ internal class PostInlineLowering(val context: Context) : FileLoweringPass {
} }
} }
override fun visitGetClass(expression: IrGetClass): IrExpression { override fun visitGetClass(expression: IrGetClass, data: IrBuilderWithScope): IrExpression {
expression.transformChildrenVoid() expression.transformChildren(this, data)
return builder.at(expression).run { return data.at(expression).run {
irCall(symbols.kClassImplConstructor, listOf(expression.argument.type)).apply { irCall(symbols.kClassImplConstructor, listOf(expression.argument.type)).apply {
val typeInfo = irCall(symbols.getObjectTypeInfo).apply { val typeInfo = irCall(symbols.getObjectTypeInfo).apply {
putValueArgument(0, expression.argument) putValueArgument(0, expression.argument)
@@ -55,8 +66,8 @@ internal class PostInlineLowering(val context: Context) : FileLoweringPass {
} }
} }
override fun visitCall(expression: IrCall): IrExpression { override fun visitCall(expression: IrCall, data: IrBuilderWithScope): IrExpression {
expression.transformChildrenVoid(this) expression.transformChildren(this, data)
// Function inlining is changing function symbol at callsite // Function inlining is changing function symbol at callsite
// and unbound symbol replacement is happening later. // and unbound symbol replacement is happening later.
@@ -83,13 +94,16 @@ internal class PostInlineLowering(val context: Context) : FileLoweringPass {
context.irBuiltIns.stringType, context.irBuiltIns.stringType,
IrConstKind.String, builder.toString())) IrConstKind.String, builder.toString()))
} else if (Symbols.isTypeOfIntrinsic(expression.symbol)) { } else if (Symbols.isTypeOfIntrinsic(expression.symbol)) {
return with (KTypeGenerator(context, irFile, expression, needExactTypeParameters = true)) { // Inline functions themselves are not called (they have been inlined at all call sites),
builder.at(expression).irKType(expression.getTypeArgument(0)!!, leaveReifiedForLater = false) // so it is ok not to build exact type parameters for them.
val needExactTypeParameters = (container as? IrSimpleFunction)?.isInline != true
return with (KTypeGenerator(context, irFile, expression, needExactTypeParameters)) {
data.at(expression).irKType(expression.getTypeArgument(0)!!, leaveReifiedForLater = false)
} }
} }
return expression return expression
} }
}) }, data = context.createIrBuilder((container as IrSymbolOwner).symbol, irBody.startOffset, irBody.endOffset))
} }
} }
@@ -567,7 +567,8 @@ private class BackendChecker(val context: Context, val irFile: IrFile) : IrEleme
if (type !is IrSimpleType) if (type !is IrSimpleType)
return return
val classifier = type.classifier val classifier = type.classifier
if (classifier is IrTypeParameterSymbol) if (classifier is IrTypeParameterSymbol
&& !classifier.owner.isReified /* Reified may be substituted with valid types later */)
checkIrKTypeParameter(irElement, classifier.owner, seenTypeParameters) checkIrKTypeParameter(irElement, classifier.owner, seenTypeParameters)
type.arguments.forEach { type.arguments.forEach {
@@ -76,3 +76,13 @@ fun test_reifiedUpperBound() {
assertTrue((t as KTypeParameter).isReified) assertTrue((t as KTypeParameter).isReified)
assertEquals("T", (t as KTypeParameter).name) assertEquals("T", (t as KTypeParameter).name)
} }
@OptIn(kotlin.ExperimentalStdlibApi::class)
inline fun <reified T : Comparable<T>> recursionInReified() = typeOf<List<T>>()
@Test
fun test_recursionInReified() {
val l = recursionInReified<Int>()
assertEquals(List::class, l.classifier)
assertEquals(Int::class, l.arguments.single().type!!.classifier)
}
@@ -1,7 +1,7 @@
import kotlin.reflect.* import kotlin.reflect.*
@OptIn(kotlin.ExperimentalStdlibApi::class) @OptIn(kotlin.ExperimentalStdlibApi::class)
inline fun <reified T : Comparable<T>> foo() { inline fun <T : Comparable<T>> foo() {
typeOf<List<T>>() typeOf<List<T>>()
} }