[IR] Remove some descriptor usage from Common/JS/JVM backends
- replace descriptor-based builders with pure IR ones - fix matchers - fix Ir2Js - rewrite some inliner-helpers to pure-IR implementations
This commit is contained in:
@@ -109,7 +109,6 @@ val IrClass.isFinalClass: Boolean
|
||||
|
||||
val IrTypeParametersContainer.classIfConstructor get() = if (this is IrConstructor) parentAsClass else this
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
fun IrValueParameter.copyTo(
|
||||
irFunction: IrFunction,
|
||||
origin: IrDeclarationOrigin = this.origin,
|
||||
@@ -129,9 +128,9 @@ fun IrValueParameter.copyTo(
|
||||
isNoinline: Boolean = this.isNoinline
|
||||
): IrValueParameter {
|
||||
val descriptor = if (index < 0) {
|
||||
WrappedReceiverParameterDescriptor(this.descriptor.annotations, this.descriptor.source)
|
||||
WrappedReceiverParameterDescriptor()
|
||||
} else {
|
||||
WrappedValueParameterDescriptor(this.descriptor.annotations, this.descriptor.source)
|
||||
WrappedValueParameterDescriptor()
|
||||
}
|
||||
val symbol = IrValueParameterSymbolImpl(descriptor)
|
||||
val defaultValueCopy = defaultValue?.let { originalDefault ->
|
||||
@@ -166,12 +165,15 @@ fun IrTypeParameter.copyToWithoutSuperTypes(
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
fun IrFunction.copyReceiverParametersFrom(from: IrFunction) {
|
||||
dispatchReceiverParameter = from.dispatchReceiverParameter?.run {
|
||||
val newDescriptor = WrappedReceiverParameterDescriptor()
|
||||
factory.createValueParameter(
|
||||
startOffset, endOffset, origin, IrValueParameterSymbolImpl(descriptor), descriptor.name,
|
||||
descriptor.indexOrMinusOne, type, varargElementType, descriptor.isCrossinline,
|
||||
descriptor.isNoinline
|
||||
startOffset, endOffset, origin,
|
||||
IrValueParameterSymbolImpl(newDescriptor),
|
||||
name,
|
||||
index, type, varargElementType, isCrossinline, isNoinline
|
||||
).also { parameter ->
|
||||
parameter.parent = this@copyReceiverParametersFrom
|
||||
newDescriptor.bind(this)
|
||||
}
|
||||
}
|
||||
extensionReceiverParameter = from.extensionReceiverParameter?.copyTo(this)
|
||||
@@ -406,22 +408,23 @@ fun IrClass.createParameterDeclarations() {
|
||||
thisReceiver = buildReceiverParameter(this, IrDeclarationOrigin.INSTANCE_RECEIVER, symbol.typeWithParameters(typeParameters))
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
fun IrFunction.createDispatchReceiverParameter(origin: IrDeclarationOrigin? = null) {
|
||||
assert(dispatchReceiverParameter == null)
|
||||
|
||||
val newDescriptor = WrappedReceiverParameterDescriptor()
|
||||
dispatchReceiverParameter = factory.createValueParameter(
|
||||
startOffset, endOffset,
|
||||
origin ?: parentAsClass.origin,
|
||||
IrValueParameterSymbolImpl(parentAsClass.thisReceiver!!.descriptor),
|
||||
IrValueParameterSymbolImpl(newDescriptor),
|
||||
Name.special("<this>"),
|
||||
0,
|
||||
-1,
|
||||
parentAsClass.defaultType,
|
||||
null,
|
||||
false,
|
||||
false
|
||||
).apply {
|
||||
parent = this@createDispatchReceiverParameter
|
||||
newDescriptor.bind(this)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-6
@@ -73,23 +73,24 @@ private class ArrayConstructorTransformer(
|
||||
val invokable = expression.getValueArgument(1)!!.transform(this, null)
|
||||
val scope = (currentScope ?: createScope(container)).scope
|
||||
return context.createIrBuilder(scope.scopeOwnerSymbol).irBlock(expression.startOffset, expression.endOffset) {
|
||||
val index = irTemporaryVar(irInt(0))
|
||||
val sizeVar = irTemporary(size)
|
||||
val result = irTemporary(irCall(sizeConstructor, expression.type).apply {
|
||||
copyTypeArgumentsFrom(expression)
|
||||
val index = createTmpVariable(irInt(0), isMutable = true)
|
||||
val sizeVar = createTmpVariable(size)
|
||||
val result = createTmpVariable(irCall(sizeConstructor, expression.type).apply {
|
||||
|
||||
copyTypeArgumentsFrom(expression)
|
||||
putValueArgument(0, irGet(sizeVar))
|
||||
})
|
||||
|
||||
val lambda = invokable.asSingleArgumentLambda()
|
||||
val invoke = invokable.type.getClass()!!.functions.single { it.name == OperatorNameConventions.INVOKE }
|
||||
val invokableVar = if (lambda == null) irTemporary(invokable) else null
|
||||
val invokableVar = if (lambda == null) createTmpVariable(invokable) else null
|
||||
+irWhile().apply {
|
||||
condition = irCall(context.irBuiltIns.lessFunByOperandType[index.type.classifierOrFail]!!).apply {
|
||||
putValueArgument(0, irGet(index))
|
||||
putValueArgument(1, irGet(sizeVar))
|
||||
}
|
||||
body = irBlock {
|
||||
val tempIndex = irTemporary(irGet(index))
|
||||
val tempIndex = createTmpVariable(irGet(index))
|
||||
val value = lambda?.inline(parent, listOf(tempIndex))?.patchDeclarationParents(scope.getLocalDeclarationParent()) ?: irCallOp(
|
||||
invoke.symbol,
|
||||
invoke.returnType,
|
||||
|
||||
+1
-1
@@ -646,7 +646,7 @@ class LocalDeclarationsLowering(
|
||||
startOffset = p.startOffset
|
||||
endOffset = p.endOffset
|
||||
origin =
|
||||
if (p.descriptor is ReceiverParameterDescriptor && newDeclaration is IrConstructor) BOUND_RECEIVER_PARAMETER
|
||||
if (p is IrValueParameter && p.index < 0 && newDeclaration is IrConstructor) BOUND_RECEIVER_PARAMETER
|
||||
else BOUND_VALUE_PARAMETER
|
||||
name = suggestNameForCapturedValue(p, generatedNames)
|
||||
index = i
|
||||
|
||||
+2
-3
@@ -163,7 +163,6 @@ open class IrBuildingTransformer(private val context: BackendContext) : IrElemen
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
fun IrConstructor.callsSuper(irBuiltIns: IrBuiltIns): Boolean {
|
||||
val constructedClass = parent as IrClass
|
||||
val superClass = constructedClass.superTypes
|
||||
@@ -186,9 +185,9 @@ fun IrConstructor.callsSuper(irBuiltIns: IrBuiltIns): Boolean {
|
||||
val delegatingClass = expression.symbol.owner.parent as IrClass
|
||||
// TODO: figure out why Lazy IR multiplies Declarations for descriptors and fix it
|
||||
// It happens because of IrBuiltIns whose IrDeclarations are different for runtime and test
|
||||
if (delegatingClass.descriptor == superClass.classifierOrFail.descriptor)
|
||||
if (delegatingClass.symbol == superClass.classifierOrFail)
|
||||
callsSuper = true
|
||||
else if (delegatingClass.descriptor != constructedClass.descriptor)
|
||||
else if (delegatingClass.symbol != constructedClass.symbol)
|
||||
throw AssertionError(
|
||||
"Expected either call to another constructor of the class being constructed or" +
|
||||
" call to super class constructor. But was: $delegatingClass with '${delegatingClass.name}' name"
|
||||
|
||||
+2
-2
@@ -117,7 +117,7 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) :
|
||||
|
||||
return if (superType.isNullable() && invokable.type.isNullable()) {
|
||||
irBlock(invokable, null, superType) {
|
||||
val invokableVariable = irTemporary(invokable)
|
||||
val invokableVariable = createTmpVariable(invokable)
|
||||
val instance = irCall(implementation.constructors.single()).apply {
|
||||
putValueArgument(0, irGet(invokableVariable))
|
||||
}
|
||||
@@ -129,7 +129,7 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) :
|
||||
// otherwise, e.g. if the argument constructs an anonymous object, resulting in new-new-<init>-<init>.
|
||||
// (See KT-21781 for a similar problem with anonymous object constructor arguments.)
|
||||
irBlock(invokable, null, superType) {
|
||||
val invokableVariable = irTemporary(invokable)
|
||||
val invokableVariable = createTmpVariable(invokable)
|
||||
+irCall(implementation.constructors.single()).apply { putValueArgument(0, irGet(invokableVariable)) }
|
||||
}
|
||||
} else {
|
||||
|
||||
+30
-8
@@ -10,7 +10,14 @@ import org.jetbrains.kotlin.backend.common.*
|
||||
import org.jetbrains.kotlin.backend.common.ir.Symbols
|
||||
import org.jetbrains.kotlin.backend.common.ir.createTemporaryVariableWithWrappedDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.config.coroutinesIntrinsicsPackageFqName
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.isTopLevelInPackage
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
@@ -19,9 +26,7 @@ import org.jetbrains.kotlin.ir.builders.irReturn
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
@@ -37,17 +42,34 @@ interface InlineFunctionResolver {
|
||||
fun getFunctionDeclaration(symbol: IrFunctionSymbol): IrFunction
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
fun IrFunction.isTopLevelInPackage(name: String, packageName: String): Boolean {
|
||||
if (name != this.name.asString()) return false
|
||||
|
||||
val containingDeclaration = parent as? IrPackageFragment ?: return false
|
||||
val packageFqName = containingDeclaration.fqName.asString()
|
||||
return packageName == packageFqName
|
||||
}
|
||||
|
||||
fun IrFunction.isBuiltInIntercepted(languageVersionSettings: LanguageVersionSettings): Boolean =
|
||||
!languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines) &&
|
||||
isTopLevelInPackage("intercepted", languageVersionSettings.coroutinesIntrinsicsPackageFqName().asString())
|
||||
|
||||
fun IrFunction.isBuiltInSuspendCoroutineUninterceptedOrReturn(languageVersionSettings: LanguageVersionSettings): Boolean =
|
||||
isTopLevelInPackage(
|
||||
"suspendCoroutineUninterceptedOrReturn",
|
||||
languageVersionSettings.coroutinesIntrinsicsPackageFqName().asString()
|
||||
)
|
||||
|
||||
open class DefaultInlineFunctionResolver(open val context: CommonBackendContext) : InlineFunctionResolver {
|
||||
override fun getFunctionDeclaration(symbol: IrFunctionSymbol): IrFunction {
|
||||
val descriptor = symbol.descriptor.original
|
||||
val function = symbol.owner
|
||||
val languageVersionSettings = context.configuration.languageVersionSettings
|
||||
// TODO: Remove these hacks when coroutine intrinsics are fixed.
|
||||
return when {
|
||||
descriptor.isBuiltInIntercepted(languageVersionSettings) ->
|
||||
function.isBuiltInIntercepted(languageVersionSettings) ->
|
||||
error("Continuation.intercepted is not available with release coroutines")
|
||||
|
||||
descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(languageVersionSettings) ->
|
||||
function.isBuiltInSuspendCoroutineUninterceptedOrReturn(languageVersionSettings) ->
|
||||
context.ir.symbols.suspendCoroutineUninterceptedOrReturn.owner
|
||||
|
||||
symbol == context.ir.symbols.coroutineContextGetter ->
|
||||
@@ -246,7 +268,7 @@ class FunctionInlining(
|
||||
)
|
||||
}
|
||||
is IrSimpleFunction ->
|
||||
IrCallImpl(startOffset, endOffset, function.returnType, function.symbol)
|
||||
IrCallImpl(startOffset, endOffset, function.returnType, function.symbol, function.typeParameters.size, function.valueParameters.size)
|
||||
else ->
|
||||
error("Unknown function kind : ${function.render()}")
|
||||
}
|
||||
|
||||
+2
-5
@@ -5,12 +5,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.common.lower.matchers
|
||||
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.kotlinFqName
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
|
||||
internal interface IrFunctionMatcher : (IrFunction) -> Boolean
|
||||
|
||||
@@ -52,13 +51,11 @@ internal class ParameterCountMatcher(
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
internal class FqNameMatcher(
|
||||
val restriction: (FqName) -> Boolean
|
||||
) : IrFunctionMatcher {
|
||||
|
||||
override fun invoke(function: IrFunction): Boolean {
|
||||
return restriction(function.descriptor.fqNameSafe)
|
||||
return restriction(function.kotlinFqName)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ private class VarargTransformer(
|
||||
|
||||
// TODO: Use symbols when builtins symbol table is fixes
|
||||
val primitiveType = context.intrinsics.primitiveArrays
|
||||
.mapKeys { it.key.descriptor }[type.classifierOrNull?.descriptor]
|
||||
.mapKeys { it.key }[type.classifierOrNull]
|
||||
|
||||
val intrinsic =
|
||||
if (primitiveType != null)
|
||||
|
||||
+2
-2
@@ -188,7 +188,7 @@ fun breakCrossModuleFieldAccess(
|
||||
|
||||
return expression.symbol.owner.transformAccess {
|
||||
val getter = getter()
|
||||
IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, getter.returnType, getter.symbol)
|
||||
IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, getter.returnType, getter.symbol, getter.typeParameters.size, getter.valueParameters.size)
|
||||
} ?: expression
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ fun breakCrossModuleFieldAccess(
|
||||
|
||||
return expression.symbol.owner.transformAccess {
|
||||
val setter = setter()
|
||||
IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, setter.returnType, setter.symbol).apply {
|
||||
IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, setter.returnType, setter.symbol, setter.typeParameters.size, setter.valueParameters.size).apply {
|
||||
putValueArgument(0, expression.value)
|
||||
}
|
||||
} ?: expression
|
||||
|
||||
@@ -30,6 +30,23 @@ val IrDeclarationParent.fqNameForIrSerialization: FqName
|
||||
else -> error(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips synthetic FILE_CLASS to make top-level functions look as in kotlin source
|
||||
*/
|
||||
val IrDeclarationParent.kotlinFqName: FqName
|
||||
get() = when (this) {
|
||||
is IrPackageFragment -> this.fqName
|
||||
is IrClass -> {
|
||||
if (origin == IrDeclarationOrigin.FILE_CLASS) {
|
||||
parent.kotlinFqName
|
||||
} else {
|
||||
parent.kotlinFqName.child(nameForIrSerialization)
|
||||
}
|
||||
}
|
||||
is IrDeclaration -> this.parent.kotlinFqName.child(nameForIrSerialization)
|
||||
else -> error(this)
|
||||
}
|
||||
|
||||
val IrClass.classId: ClassId?
|
||||
get() = when (val parent = this.parent) {
|
||||
is IrClass -> parent.classId?.createNestedClassId(this.name)
|
||||
|
||||
@@ -552,7 +552,8 @@ open class DeepCopyIrTreeWithSymbols(
|
||||
expression.startOffset, expression.endOffset,
|
||||
expression.type.remapType(),
|
||||
newConstructor,
|
||||
expression.typeArgumentsCount
|
||||
expression.typeArgumentsCount,
|
||||
expression.valueArgumentsCount
|
||||
).apply {
|
||||
copyRemappedTypeArgumentsFrom(expression)
|
||||
transformValueArguments(expression)
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.util
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.MemberDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
@@ -62,6 +64,12 @@ class ExpectDeclarationRemover(val symbolTable: ReferenceSymbolTable, private va
|
||||
}
|
||||
}
|
||||
|
||||
private fun isOptionalAnnotationClass(klass: IrClass): Boolean {
|
||||
return klass.kind == ClassKind.ANNOTATION_CLASS &&
|
||||
klass.isExpect &&
|
||||
klass.annotations.hasAnnotation(ExpectedActualDeclarationChecker.OPTIONAL_EXPECTATION_FQ_NAME)
|
||||
}
|
||||
|
||||
private fun tryCopyDefaultArguments(declaration: IrValueParameter) {
|
||||
// Keep actual default value if present. They are generally not allowed but can be suppressed with
|
||||
// @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS")
|
||||
@@ -71,10 +79,10 @@ class ExpectDeclarationRemover(val symbolTable: ReferenceSymbolTable, private va
|
||||
|
||||
val function = declaration.parent as? IrFunction ?: return
|
||||
|
||||
if (function is IrConstructor &&
|
||||
ExpectedActualDeclarationChecker.isOptionalAnnotationClass(function.descriptor.constructedClass)
|
||||
) {
|
||||
return
|
||||
if (function is IrConstructor) {
|
||||
if (isOptionalAnnotationClass(function.constructedClass)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (!function.descriptor.isActual) return
|
||||
|
||||
Reference in New Issue
Block a user