JVM_IR. Avoid unbound symbols and declarations without parent

This commit is contained in:
Georgy Bronnikov
2018-09-10 20:23:46 +03:00
parent 9b49c23668
commit a23aae590e
9 changed files with 99 additions and 59 deletions
@@ -34,7 +34,7 @@ class JvmBackendContext(
irModuleFragment: IrModuleFragment, symbolTable: SymbolTable
) : CommonBackendContext {
override val builtIns = state.module.builtIns
override val declarationFactory: JvmDeclarationFactory = JvmDeclarationFactory(psiSourceManager, builtIns, state)
override val declarationFactory: JvmDeclarationFactory = JvmDeclarationFactory(psiSourceManager, builtIns, state, symbolTable)
override val sharedVariablesManager = JvmSharedVariablesManager(builtIns, irBuiltIns)
override val reflectionTypes: ReflectionTypes by lazy(LazyThreadSafetyMode.PUBLICATION) {
@@ -33,10 +33,7 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.toIrType
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.ir.util.isInterface
import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.Name
@@ -48,7 +45,8 @@ import java.util.*
class JvmDeclarationFactory(
private val psiSourceManager: PsiSourceManager,
private val builtIns: KotlinBuiltIns,
private val state: GenerationState
private val state: GenerationState,
private val symbolTable: SymbolTable
) : DeclarationFactory {
private val singletonFieldDeclarations = HashMap<IrSymbolOwner, IrField>()
private val outerThisDeclarations = HashMap<IrClass, IrField>()
@@ -140,7 +138,11 @@ class JvmDeclarationFactory(
if (i == 0) {
IrValueParameterImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
JvmLoweredDeclarationOrigin.FIELD_FOR_OUTER_THIS, IrValueParameterSymbolImpl(v), outerThisType.toIrType()!!, null)
JvmLoweredDeclarationOrigin.FIELD_FOR_OUTER_THIS,
IrValueParameterSymbolImpl(v),
outerThisType.toIrType(symbolTable)!!,
null
)
} else {
val oldParameter = oldConstructor.valueParameters[i - 1]
IrValueParameterImpl(
@@ -210,7 +212,9 @@ class JvmDeclarationFactory(
interfaceFun.descriptor.original,
interfaceFun.parentAsClass.descriptor,
state.typeMapper
).createFunctionAndMapVariables(interfaceFun, origin = JvmLoweredDeclarationOrigin.DEFAULT_IMPLS)
).createFunctionAndMapVariables(
interfaceFun, defaultImpls, symbolTable = symbolTable, origin = JvmLoweredDeclarationOrigin.DEFAULT_IMPLS
)
}
}
@@ -219,7 +223,9 @@ class JvmDeclarationFactory(
IrClassImpl(
interfaceClass.startOffset, interfaceClass.endOffset, JvmLoweredDeclarationOrigin.DEFAULT_IMPLS,
createDefaultImplsClassDescriptor(interfaceClass.descriptor)
)
).also {
it.parent = interfaceClass
}
}
companion object {
@@ -109,7 +109,7 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa
)
val invokeFunDescriptor = context.getClass(FqName("kotlin.jvm.functions.FunctionN"))
.getFunction("invoke", listOf(expression.type.toKotlinType()))
val invokeFunSymbol = context.ir.symbols.externalSymbolTable.referenceSimpleFunction(invokeFunDescriptor)
val invokeFunSymbol = context.ir.symbols.externalSymbolTable.referenceSimpleFunction(invokeFunDescriptor.original)
IrCallImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
@@ -741,11 +741,12 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa
}
val clazzDescriptor = globalContext.getClass(FqName("java.lang.Class"))
val clazz = IrClassReferenceImpl(
val clazzSymbol = globalContext.ir.symbols.externalSymbolTable.referenceClass(clazzDescriptor)
val clazzRef = IrClassReferenceImpl(
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
clazzDescriptor.toIrType(),
clazzDescriptor,
clazzSymbol,
CrIrType(type)
)
@@ -763,17 +764,19 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa
-1, -1, globalContext.irBuiltIns.stringType,
state.moduleName
)
val function = reflectionClass.getStaticFunction("getOrCreateKotlinPackage", emptyList())
irCall(IrSimpleFunctionSymbolImpl(function), function.returnType!!.toIrType()!!).apply {
putValueArgument(0, clazz)
val functionDescriptor = reflectionClass.getStaticFunction("getOrCreateKotlinPackage", emptyList())
val functionSymbol = globalContext.ir.symbols.externalSymbolTable.referenceSimpleFunction(functionDescriptor)
irCall(functionSymbol, functionSymbol.owner.returnType).apply {
putValueArgument(0, clazzRef)
putValueArgument(1, module)
}
} else {
val function = reflectionClass.staticScope
val functionDescriptor = reflectionClass.staticScope
.getContributedFunctions(Name.identifier("getOrCreateKotlinClass"), NoLookupLocation.FROM_BACKEND)
.single { it.valueParameters.size == 1 }
irCall(IrSimpleFunctionSymbolImpl(function), function.returnType!!.toIrType()!!).apply {
putValueArgument(0, clazz)
val functionSymbol = globalContext.ir.symbols.externalSymbolTable.referenceSimpleFunction(functionDescriptor)
irCall(functionSymbol, functionSymbol.owner.returnType).apply {
putValueArgument(0, clazzRef)
}
}
}
@@ -45,15 +45,16 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
fun transform(delegatingConstructorCall: IrDelegatingConstructorCall): IrExpression
}
private val unsubstitutedArrayOfFun = context.ir.symbols.arrayOf.descriptor
private val arrayOfFun = context.ir.symbols.arrayOf.owner
private val unsubstitutedArrayOfFunDescriptor = arrayOfFun.descriptor
private fun createArrayOfExpression(arrayElementType: KotlinType, arrayElements: List<IrExpression>): IrExpression {
val typeParameter0 = unsubstitutedArrayOfFun.typeParameters[0]
val typeParameter0 = unsubstitutedArrayOfFunDescriptor.typeParameters[0]
val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameter0.typeConstructor to TypeProjectionImpl(arrayElementType)))
val substitutedArrayOfFun = unsubstitutedArrayOfFun.substitute(typeSubstitutor)!!
val substitutedArrayOfDescriptor = unsubstitutedArrayOfFunDescriptor.substitute(typeSubstitutor)!!
val valueParameter0 = substitutedArrayOfFun.valueParameters[0]
val valueParameter0 = substitutedArrayOfDescriptor.valueParameters[0]
val arg0VarargType = valueParameter0.type
val arg0VarargElementType = valueParameter0.varargElementType!!
val arg0 =
@@ -62,10 +63,12 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
return IrCallImpl(
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
substitutedArrayOfFun.returnType!!.toIrType()!!,
substitutedArrayOfFun,
substitutedArrayOfFun.typeParametersCount
substitutedArrayOfDescriptor.returnType!!.toIrType()!!,
arrayOfFun.symbol,
substitutedArrayOfDescriptor,
arrayOfFun.typeParameters.size
).apply {
putTypeArgument(0, arrayElementType.toIrType()!!)
putValueArgument(0, arg0)
}
}
@@ -186,23 +189,24 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
return enumEntryClass
}
private fun createFieldForEnumEntry(enumEntry: IrEnumEntry) =
context.declarationFactory.getFieldForEnumEntry(enumEntry, enumEntry.initializerExpression!!.type).also {
private fun createFieldForEnumEntry(enumEntry: IrEnumEntry): IrField {
return context.declarationFactory.getFieldForEnumEntry(enumEntry, enumEntry.initializerExpression!!.type).also {
it.initializer = IrExpressionBodyImpl(enumEntry.initializerExpression!!)
enumEntryFields.add(it)
enumEntriesByField[it] = enumEntry
}
}
private fun setupSynthesizedEnumClassMembers() {
val irField = createSyntheticValuesFieldDeclaration()
irClass.declarations.add(irField)
valuesFunction = findFunctionDescriptorForMemberWithSyntheticBodyKind(IrSyntheticBodyKind.ENUM_VALUES)
valueOfFunction = findFunctionDescriptorForMemberWithSyntheticBodyKind(IrSyntheticBodyKind.ENUM_VALUEOF)
valuesFunction = findFunctionForMemberWithSyntheticBodyKind(IrSyntheticBodyKind.ENUM_VALUES)
valueOfFunction = findFunctionForMemberWithSyntheticBodyKind(IrSyntheticBodyKind.ENUM_VALUEOF)
}
private fun findFunctionDescriptorForMemberWithSyntheticBodyKind(kind: IrSyntheticBodyKind): IrFunction =
private fun findFunctionForMemberWithSyntheticBodyKind(kind: IrSyntheticBodyKind): IrFunction =
irClass.declarations.asSequence().filterIsInstance<IrFunction>()
.first {
it.body.let { body ->
@@ -221,7 +225,10 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
createSyntheticValuesFieldDescriptor(valuesArrayType),
valuesArrayType.toIrType()!!,
IrExpressionBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irValuesInitializer)
).also { valuesField = it }
).also {
it.parent = irClass
valuesField = it
}
}
private fun createSyntheticValuesFieldInitializerExpression(): IrExpression =
@@ -458,19 +465,21 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
}
private fun createEnumValueOfBody(): IrBody {
val unsubstitutedValueOf = context.irBuiltIns.enumValueOf
val typeParameterT = unsubstitutedValueOf.typeParameters[0]
val unsubstitutedValueOfDescriptor = context.irBuiltIns.enumValueOf
val valueOfSymbol = context.irBuiltIns.enumValueOfSymbol
val typeParameterT = unsubstitutedValueOfDescriptor.typeParameters[0]
val enumClassType = irClass.descriptor.defaultType
val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(enumClassType)))
val substitutedValueOf = unsubstitutedValueOf.substitute(typeSubstitutor)!!
val substitutedValueOfDescriptor = unsubstitutedValueOfDescriptor.substitute(typeSubstitutor)!!
val irValueOfCall =
IrCallImpl(
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
substitutedValueOf.returnType!!.toIrType()!!,
substitutedValueOf,
substitutedValueOf.typeParametersCount
substitutedValueOfDescriptor.returnType!!.toIrType()!!,
valueOfSymbol,
substitutedValueOfDescriptor,
substitutedValueOfDescriptor.typeParametersCount
)
irValueOfCall.putValueArgument(
0, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valueOfFunction.valueParameters[0].symbol)
@@ -491,11 +500,14 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
}
private fun createEnumValuesBody(valuesField: IrField): IrBody {
val cloneFun = valuesField.type.toKotlinType().memberScope.findSingleFunction(Name.identifier("clone"))
val cloneFunDescriptor = valuesField.type.toKotlinType().memberScope.findSingleFunction(Name.identifier("clone")).original
val cloneFun = context.ir.symbols.externalSymbolTable.referenceSimpleFunction(cloneFunDescriptor).owner
val irCloneValues = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, cloneFun.returnType!!.toIrType()!!, cloneFun, 0).apply {
dispatchReceiver = IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valuesField.symbol, valuesField.symbol.owner.type)
}
val irCloneValues =
IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, cloneFun.returnType, cloneFun.symbol, cloneFunDescriptor, 0).apply {
dispatchReceiver =
IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valuesField.symbol, valuesField.symbol.owner.type)
}
return IrBlockBodyImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
@@ -514,4 +526,4 @@ class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass {
}
}
}
@@ -15,12 +15,10 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
import org.jetbrains.kotlin.ir.util.isInterface
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
@@ -111,17 +109,20 @@ internal fun createStaticFunctionWithReceivers(
internal fun FunctionDescriptor.createFunctionAndMapVariables(
oldFunction: IrFunction,
parentClass: IrDeclarationParent,
visibility: Visibility = oldFunction.visibility,
symbolTable: SymbolTable? = null,
origin: IrDeclarationOrigin = oldFunction.origin
) =
IrFunctionImpl(
oldFunction.startOffset, oldFunction.endOffset, origin, IrSimpleFunctionSymbolImpl(this),
visibility = visibility
).apply {
parent = parentClass
body = oldFunction.body
returnType = oldFunction.returnType
createParameterDeclarations()
// TODO: do we really need descriptor here? This workaround is about coping `dispatchReceiver` descriptor
createParameterDeclarations(symbolTable)
// TODO: do we really need descriptor here? This workaround is about copying `dispatchReceiver` descriptor
val mapping: Map<ValueDescriptor, IrValueParameter> =
(listOfNotNull(oldFunction.dispatchReceiverParameter!!.descriptor, oldFunction.extensionReceiverParameter?.descriptor) + oldFunction.valueParameters.map { it.descriptor })
.zip(valueParameters).toMap()
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType
@@ -50,7 +51,8 @@ class ObjectClassLowering(val context: JvmBackendContext) : IrElementTransformer
val publicInstanceField = context.declarationFactory.getFieldForObjectInstance(irClass)
val constructor = irClass.descriptor.unsubstitutedPrimaryConstructor
?: throw AssertionError("Object should have a primary constructor: ${irClass.descriptor}")
?: throw AssertionError("Object should have a primary constructor: ${irClass.descriptor}")
val constructorSymbol = context.ir.symbols.externalSymbolTable.referenceConstructor(constructor)
val publicInstanceOwner = if (irClass.descriptor.isCompanionObject) parentScope!!.irElement as IrDeclarationContainer else irClass
if (isCompanionObjectInInterfaceNotIntrinsic(irClass.descriptor)) {
@@ -62,12 +64,18 @@ class ObjectClassLowering(val context: JvmBackendContext) : IrElementTransformer
CallableMemberDescriptor.Kind.SYNTHESIZED,
false
) as PropertyDescriptor
privateInstance.name
val field = createInstanceFieldWithInitializer(IrFieldSymbolImpl(privateInstance), constructor, irClass, irClass.defaultType)
val fieldSymbol = context.ir.symbols.externalSymbolTable.referenceField(privateInstance)
val field = createInstanceFieldWithInitializer(
fieldSymbol,
constructorSymbol,
irClass,
irClass.defaultType
)
publicInstanceField.initializer =
IrExpressionBodyImpl(IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, field.symbol, irClass.defaultType))
} else {
val constructorCall = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irClass.defaultType, constructor, 0)
val constructorCall =
IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irClass.defaultType, constructorSymbol, constructorSymbol.descriptor, 0)
publicInstanceField.initializer = IrExpressionBodyImpl(constructorCall)
}
@@ -77,13 +85,13 @@ class ObjectClassLowering(val context: JvmBackendContext) : IrElementTransformer
private fun createInstanceFieldWithInitializer(
fieldSymbol: IrFieldSymbol,
constructor: ClassConstructorDescriptor,
constructorSymbol: IrConstructorSymbol,
instanceOwner: IrDeclarationContainer,
objectType: IrType
): IrField =
createFieldWithCustomInitializer(
fieldSymbol,
IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, objectType, constructor, 0),
IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, objectType, constructorSymbol, constructorSymbol.descriptor, 0),
instanceOwner,
objectType
)
@@ -41,7 +41,7 @@ class StaticDefaultFunctionLowering(val state: GenerationState) : IrElementTrans
declaration.dispatchReceiverParameter!!.descriptor.type
)
// NOTE: Fix it
newFunction.createFunctionAndMapVariables(declaration, Visibilities.PUBLIC)
newFunction.createFunctionAndMapVariables(declaration, declaration.parent, Visibilities.PUBLIC)
} else {
super.visitFunction(declaration)
}
@@ -16,6 +16,6 @@
package org.jetbrains.kotlin.ir.declarations
interface IrTypeParametersContainer : IrDeclaration {
interface IrTypeParametersContainer : IrDeclaration, IrDeclarationParent {
val typeParameters: MutableList<IrTypeParameter>
}
@@ -142,13 +142,13 @@ fun IrExpression.isNullConst() = this is IrConst<*> && this.kind == IrConstKind.
fun IrMemberAccessExpression.usesDefaultArguments(): Boolean =
this.descriptor.valueParameters.any { this.getValueArgument(it) == null }
fun IrFunction.createParameterDeclarations() {
fun IrFunction.createParameterDeclarations(symbolTable: SymbolTable? = null) {
fun ParameterDescriptor.irValueParameter() = IrValueParameterImpl(
innerStartOffset(this), innerEndOffset(this),
IrDeclarationOrigin.DEFINED,
this,
type.toIrType()!!,
(this as? ValueParameterDescriptor)?.varargElementType?.toIrType()
type.toIrType(symbolTable)!!,
(this as? ValueParameterDescriptor)?.varargElementType?.toIrType(symbolTable)
).also {
it.parent = this@createParameterDeclarations
}
@@ -331,6 +331,16 @@ val IrClass.isObject get() = kind == ClassKind.OBJECT
val IrDeclaration.parentAsClass get() = parent as IrClass
tailrec fun IrElement.getPackageFragment(): IrPackageFragment? {
if (this is IrPackageFragment) return this
val vParent = (this as? IrDeclaration)?.parent
return when (vParent) {
is IrPackageFragment -> vParent
is IrClass -> vParent.getPackageFragment()
else -> null
}
}
fun IrAnnotationContainer.hasAnnotation(name: FqName) =
annotations.any {
it.symbol.owner.parentAsClass.descriptor.fqNameSafe == name