IR: Refactor IrBuiltIns to abstract it from descriptors

This commit is contained in:
Ilya Chernikov
2021-04-28 13:43:14 +02:00
committed by TeamCityServer
parent 25d2e61a82
commit dee0487185
124 changed files with 1231 additions and 970 deletions
@@ -0,0 +1,188 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
import org.jetbrains.kotlin.ir.declarations.IrFactory
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
/**
* Symbols for builtins that are available without any context and are not specific to any backend
* (but specific to the frontend)
*/
abstract class IrBuiltIns {
abstract val languageVersionSettings: LanguageVersionSettings
abstract val irFactory: IrFactory
abstract val anyType: IrType
abstract val anyClass: IrClassSymbol
abstract val anyNType: IrType
abstract val booleanType: IrType
abstract val booleanClass: IrClassSymbol
abstract val charType: IrType
abstract val charClass: IrClassSymbol
abstract val numberType: IrType
abstract val numberClass: IrClassSymbol
abstract val byteType: IrType
abstract val byteClass: IrClassSymbol
abstract val shortType: IrType
abstract val shortClass: IrClassSymbol
abstract val intType: IrType
abstract val intClass: IrClassSymbol
abstract val longType: IrType
abstract val longClass: IrClassSymbol
abstract val floatType: IrType
abstract val floatClass: IrClassSymbol
abstract val doubleType: IrType
abstract val doubleClass: IrClassSymbol
abstract val nothingType: IrType
abstract val nothingClass: IrClassSymbol
abstract val nothingNType: IrType
abstract val unitType: IrType
abstract val unitClass: IrClassSymbol
abstract val stringType: IrType
abstract val stringClass: IrClassSymbol
abstract val charSequenceClass: IrClassSymbol
abstract val collectionClass: IrClassSymbol
abstract val arrayClass: IrClassSymbol
abstract val setClass: IrClassSymbol
abstract val listClass: IrClassSymbol
abstract val mapClass: IrClassSymbol
abstract val mapEntryClass: IrClassSymbol
abstract val iterableClass: IrClassSymbol
abstract val iteratorClass: IrClassSymbol
abstract val listIteratorClass: IrClassSymbol
abstract val mutableCollectionClass: IrClassSymbol
abstract val mutableSetClass: IrClassSymbol
abstract val mutableListClass: IrClassSymbol
abstract val mutableMapClass: IrClassSymbol
abstract val mutableMapEntryClass: IrClassSymbol
abstract val mutableIterableClass: IrClassSymbol
abstract val mutableIteratorClass: IrClassSymbol
abstract val mutableListIteratorClass: IrClassSymbol
abstract val comparableClass: IrClassSymbol
abstract val throwableType: IrType
abstract val throwableClass: IrClassSymbol
abstract val kCallableClass: IrClassSymbol
abstract val kPropertyClass: IrClassSymbol
abstract val kClassClass: IrClassSymbol
abstract val kProperty0Class: IrClassSymbol
abstract val kProperty1Class: IrClassSymbol
abstract val kProperty2Class: IrClassSymbol
abstract val kMutableProperty0Class: IrClassSymbol
abstract val kMutableProperty1Class: IrClassSymbol
abstract val kMutableProperty2Class: IrClassSymbol
abstract val functionClass: IrClassSymbol
abstract val kFunctionClass: IrClassSymbol
abstract val annotationType: IrType
abstract val annotationClass: IrClassSymbol
// TODO: consider removing to get rid of descriptor-related dependencies
abstract val primitiveTypeToIrType: Map<PrimitiveType, IrType>
abstract val primitiveIrTypes: List<IrType>
abstract val primitiveIrTypesWithComparisons: List<IrType>
abstract val primitiveFloatingPointIrTypes: List<IrType>
abstract val byteArray: IrClassSymbol
abstract val charArray: IrClassSymbol
abstract val shortArray: IrClassSymbol
abstract val intArray: IrClassSymbol
abstract val longArray: IrClassSymbol
abstract val floatArray: IrClassSymbol
abstract val doubleArray: IrClassSymbol
abstract val booleanArray: IrClassSymbol
abstract val primitiveArraysToPrimitiveTypes: Map<IrClassSymbol, PrimitiveType>
abstract val primitiveArrays: Set<IrClassSymbol>
abstract val primitiveArrayElementTypes: Map<IrClassSymbol, IrType?>
abstract val primitiveArrayForType: Map<IrType?, IrClassSymbol>
abstract val unsignedArrays: Set<IrClassSymbol>
abstract val lessFunByOperandType: Map<IrClassifierSymbol, IrSimpleFunctionSymbol>
abstract val lessOrEqualFunByOperandType: Map<IrClassifierSymbol, IrSimpleFunctionSymbol>
abstract val greaterOrEqualFunByOperandType: Map<IrClassifierSymbol, IrSimpleFunctionSymbol>
abstract val greaterFunByOperandType: Map<IrClassifierSymbol, IrSimpleFunctionSymbol>
abstract val ieee754equalsFunByOperandType: Map<IrClassifierSymbol, IrSimpleFunctionSymbol>
abstract val booleanNotSymbol: IrSimpleFunctionSymbol
abstract val eqeqeqSymbol: IrSimpleFunctionSymbol
abstract val eqeqSymbol: IrSimpleFunctionSymbol
abstract val throwCceSymbol: IrSimpleFunctionSymbol
abstract val throwIseSymbol: IrSimpleFunctionSymbol
abstract val andandSymbol: IrSimpleFunctionSymbol
abstract val ororSymbol: IrSimpleFunctionSymbol
abstract val noWhenBranchMatchedExceptionSymbol: IrSimpleFunctionSymbol
abstract val illegalArgumentExceptionSymbol: IrSimpleFunctionSymbol
abstract val checkNotNullSymbol: IrSimpleFunctionSymbol
abstract val dataClassArrayMemberHashCodeSymbol: IrSimpleFunctionSymbol
abstract val dataClassArrayMemberToStringSymbol: IrSimpleFunctionSymbol
abstract fun getKPropertyClass(mutable: Boolean, n: Int): IrClassSymbol
abstract val enumClass: IrClassSymbol
abstract val intPlusSymbol: IrSimpleFunctionSymbol
abstract val intTimesSymbol: IrSimpleFunctionSymbol
abstract val extensionToString: IrSimpleFunctionSymbol
abstract val stringPlus: IrSimpleFunctionSymbol
abstract val arrayOf: IrSimpleFunctionSymbol
abstract val arrayOfNulls: IrSimpleFunctionSymbol
abstract val toUIntByExtensionReceiver: Map<IrClassifierSymbol, IrSimpleFunctionSymbol>
abstract val toULongByExtensionReceiver: Map<IrClassifierSymbol, IrSimpleFunctionSymbol>
abstract fun functionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass
abstract fun kFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass
abstract fun suspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass
abstract fun kSuspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass
abstract fun functionN(arity: Int): IrClass
abstract fun kFunctionN(arity: Int): IrClass
abstract fun suspendFunctionN(arity: Int): IrClass
abstract fun kSuspendFunctionN(arity: Int): IrClass
abstract fun findFunctions(name: Name, vararg packageNameSegments: String = arrayOf("kotlin")): Iterable<IrSimpleFunctionSymbol>
abstract fun findClass(name: Name, vararg packageNameSegments: String = arrayOf("kotlin")): IrClassSymbol?
abstract fun getBinaryOperator(name: Name, lhsType: IrType, rhsType: IrType): IrSimpleFunctionSymbol
abstract fun getUnaryOperator(name: Name, receiverType: IrType): IrSimpleFunctionSymbol
abstract val getProgressionLastElementByReturnType: Map<IrClassifierSymbol?, IrSimpleFunctionSymbol>
companion object {
val KOTLIN_INTERNAL_IR_FQN = FqName("kotlin.internal.ir")
val BUILTIN_OPERATOR = object : IrDeclarationOriginImpl("OPERATOR") {}
}
}
object BuiltInOperatorNames {
const val LESS = "less"
const val LESS_OR_EQUAL = "lessOrEqual"
const val GREATER = "greater"
const val GREATER_OR_EQUAL = "greaterOrEqual"
const val EQEQ = "EQEQ"
const val EQEQEQ = "EQEQEQ"
const val IEEE754_EQUALS = "ieee754equals"
const val THROW_CCE = "THROW_CCE"
const val THROW_ISE = "THROW_ISE"
const val NO_WHEN_BRANCH_MATCHED_EXCEPTION = "noWhenBranchMatchedException"
const val ILLEGAL_ARGUMENT_EXCEPTION = "illegalArgumentException"
const val ANDAND = "ANDAND"
const val OROR = "OROR"
}
@@ -16,10 +16,8 @@
package org.jetbrains.kotlin.ir.builders
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.declarations.IrFactory
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
interface IrGenerator {
val context: IrGeneratorContext
@@ -34,9 +32,6 @@ interface IrGeneratorContextInterface {
}
interface IrGeneratorContext : IrGeneratorContextInterface {
@ObsoleteDescriptorBasedAPI
val builtIns: KotlinBuiltIns get() = irBuiltIns.builtIns
val irFactory: IrFactory get() = irBuiltIns.irFactory
}
@@ -17,10 +17,10 @@
package org.jetbrains.kotlin.ir.declarations
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrElementBase
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.name.Name
@@ -17,9 +17,9 @@
package org.jetbrains.kotlin.ir.declarations.impl
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.name.Name
@@ -1,348 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.descriptors
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.PrimitiveType
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.TypeParameterDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
import org.jetbrains.kotlin.ir.declarations.IrFactory
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeBuilder
import org.jetbrains.kotlin.ir.types.impl.buildSimpleType
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
import org.jetbrains.kotlin.ir.types.makeNullable
import org.jetbrains.kotlin.ir.types.withHasQuestionMark
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.types.*
class IrBuiltIns(
val builtIns: KotlinBuiltIns,
private val typeTranslator: TypeTranslator,
private val symbolTable: SymbolTable
) {
val languageVersionSettings = typeTranslator.languageVersionSettings
lateinit var functionFactory: IrAbstractFunctionFactory
val irFactory: IrFactory = symbolTable.irFactory
private val builtInsModule = builtIns.builtInsModule
private val packageFragmentDescriptor = IrBuiltinsPackageFragmentDescriptorImpl(builtInsModule, KOTLIN_INTERNAL_IR_FQN)
val packageFragment = symbolTable.declareExternalPackageFragmentIfNotExists(packageFragmentDescriptor)
private fun ClassDescriptor.toIrSymbol() = symbolTable.referenceClass(this)
private fun KotlinType.toIrType() = typeTranslator.translateType(this)
private fun defineOperator(name: String, returnType: IrType, valueParameterTypes: List<IrType>): IrSimpleFunctionSymbol {
val operatorDescriptor =
IrSimpleBuiltinOperatorDescriptorImpl(packageFragmentDescriptor, Name.identifier(name), returnType.originalKotlinType!!)
for ((i, valueParameterType) in valueParameterTypes.withIndex()) {
operatorDescriptor.addValueParameter(
IrBuiltinValueParameterDescriptorImpl(
operatorDescriptor, Name.identifier("arg$i"), i, valueParameterType.originalKotlinType!!
)
)
}
val symbol = symbolTable.declareSimpleFunctionIfNotExists(operatorDescriptor) {
val operator = irFactory.createFunction(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, BUILTIN_OPERATOR, it, Name.identifier(name), DescriptorVisibilities.PUBLIC, Modality.FINAL,
returnType, isInline = false, isExternal = false, isTailrec = false, isSuspend = false,
isOperator = false, isInfix = false, isExpect = false, isFakeOverride = false
)
operator.parent = packageFragment
packageFragment.declarations += operator
operator.valueParameters = valueParameterTypes.withIndex().map { (i, valueParameterType) ->
val valueParameterDescriptor = operatorDescriptor.valueParameters[i]
val valueParameterSymbol = IrValueParameterSymbolImpl(valueParameterDescriptor)
irFactory.createValueParameter(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, BUILTIN_OPERATOR, valueParameterSymbol, Name.identifier("arg$i"), i,
valueParameterType, null, isCrossinline = false, isNoinline = false, isHidden = false, isAssignable = false
).apply {
parent = operator
}
}
operator
}
return symbol.symbol
}
private fun defineCheckNotNullOperator(): IrSimpleFunctionSymbol {
val name = Name.identifier("CHECK_NOT_NULL")
val typeParameterDescriptor: TypeParameterDescriptor
val valueParameterDescriptor: ValueParameterDescriptor
val returnKotlinType: SimpleType
val valueKotlinType: SimpleType
// Note: We still need a complete function descriptor here because `CHECK_NOT_NULL` is being substituted by psi2ir
val operatorDescriptor = SimpleFunctionDescriptorImpl.create(
packageFragmentDescriptor,
Annotations.EMPTY,
name,
CallableMemberDescriptor.Kind.SYNTHESIZED,
SourceElement.NO_SOURCE
).apply {
typeParameterDescriptor = TypeParameterDescriptorImpl.createForFurtherModification(
this, Annotations.EMPTY, false, Variance.INVARIANT, Name.identifier("T0"),
0, SourceElement.NO_SOURCE, LockBasedStorageManager.NO_LOCKS
).apply {
addUpperBound(any)
setInitialized()
}
valueKotlinType = typeParameterDescriptor.typeConstructor.makeNullableType()
valueParameterDescriptor = ValueParameterDescriptorImpl(
this, null, 0, Annotations.EMPTY, Name.identifier("arg0"), valueKotlinType,
declaresDefaultValue = false, isCrossinline = false, isNoinline = false, varargElementType = null,
source = SourceElement.NO_SOURCE
)
returnKotlinType = typeParameterDescriptor.typeConstructor.makeNonNullType()
initialize(
null, null, listOf(typeParameterDescriptor), listOf(valueParameterDescriptor), returnKotlinType,
Modality.FINAL, DescriptorVisibilities.PUBLIC
)
}
val typeParameterSymbol = IrTypeParameterSymbolImpl(typeParameterDescriptor)
val typeParameter = irFactory.createTypeParameter(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, BUILTIN_OPERATOR, typeParameterSymbol, Name.identifier("T0"), 0, true, Variance.INVARIANT
).apply {
superTypes += anyType
}
val returnIrType = IrSimpleTypeBuilder().run {
classifier = typeParameterSymbol
kotlinType = returnKotlinType
hasQuestionMark = false
buildSimpleType()
}
val valueIrType = IrSimpleTypeBuilder().run {
classifier = typeParameterSymbol
kotlinType = valueKotlinType
hasQuestionMark = true
buildSimpleType()
}
return symbolTable.declareSimpleFunctionIfNotExists(operatorDescriptor) {
val operator = irFactory.createFunction(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, BUILTIN_OPERATOR, it, name, DescriptorVisibilities.PUBLIC, Modality.FINAL, returnIrType,
isInline = false, isExternal = false, isTailrec = false, isSuspend = false, isOperator = false, isInfix = false,
isExpect = false, isFakeOverride = false
)
operator.parent = packageFragment
packageFragment.declarations += operator
val valueParameterSymbol = IrValueParameterSymbolImpl(valueParameterDescriptor)
val valueParameter = irFactory.createValueParameter(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, BUILTIN_OPERATOR, valueParameterSymbol, Name.identifier("arg0"), 0,
valueIrType, null, isCrossinline = false, isNoinline = false, isHidden = false, isAssignable = false
)
valueParameter.parent = operator
typeParameter.parent = operator
operator.valueParameters += valueParameter
operator.typeParameters += typeParameter
operator
}.symbol
}
private fun defineComparisonOperator(name: String, operandType: IrType) =
defineOperator(name, booleanType, listOf(operandType, operandType))
private fun List<IrType>.defineComparisonOperatorForEachIrType(name: String) =
associate { it.classifierOrFail to defineComparisonOperator(name, it) }
val any = builtIns.anyType
val anyType = any.toIrType()
val anyClass = builtIns.any.toIrSymbol()
val anyNType = anyType.withHasQuestionMark(true)
val bool = builtIns.booleanType
val booleanType = bool.toIrType()
val booleanClass = builtIns.boolean.toIrSymbol()
val char = builtIns.charType
val charType = char.toIrType()
val charClass = builtIns.char.toIrSymbol()
val number = builtIns.number.defaultType
val numberType = number.toIrType()
val numberClass = builtIns.number.toIrSymbol()
val byte = builtIns.byteType
val byteType = byte.toIrType()
val byteClass = builtIns.byte.toIrSymbol()
val short = builtIns.shortType
val shortType = short.toIrType()
val shortClass = builtIns.short.toIrSymbol()
val int = builtIns.intType
val intType = int.toIrType()
val intClass = builtIns.int.toIrSymbol()
val long = builtIns.longType
val longType = long.toIrType()
val longClass = builtIns.long.toIrSymbol()
val float = builtIns.floatType
val floatType = float.toIrType()
val floatClass = builtIns.float.toIrSymbol()
val double = builtIns.doubleType
val doubleType = double.toIrType()
val doubleClass = builtIns.double.toIrSymbol()
val nothing = builtIns.nothingType
val nothingType = nothing.toIrType()
val nothingClass = builtIns.nothing.toIrSymbol()
val nothingNType = nothingType.withHasQuestionMark(true)
val unit = builtIns.unitType
val unitType = unit.toIrType()
val unitClass = builtIns.unit.toIrSymbol()
val string = builtIns.stringType
val stringType = string.toIrType()
val stringClass = builtIns.string.toIrSymbol()
val iterableClass = builtIns.iterable.toIrSymbol()
val iteratorClass = builtIns.iterator.toIrSymbol()
val listIteratorClass = builtIns.listIterator.toIrSymbol()
val listClass = builtIns.list.toIrSymbol()
val collectionClass = builtIns.collection.toIrSymbol()
val setClass = builtIns.set.toIrSymbol()
val mapClass = builtIns.map.toIrSymbol()
val mapEntryClass = builtIns.mapEntry.toIrSymbol()
val arrayClass = builtIns.array.toIrSymbol()
val throwableType = builtIns.throwable.defaultType.toIrType()
val throwableClass = builtIns.throwable.toIrSymbol()
val kCallableClass = builtIns.kCallable.toIrSymbol()
val kPropertyClass = builtIns.kProperty.toIrSymbol()
val kClassClass = builtIns.kClass.toIrSymbol()
private val kProperty0Class = builtIns.kProperty0.toIrSymbol()
private val kProperty1Class = builtIns.kProperty1.toIrSymbol()
private val kProperty2Class = builtIns.kProperty2.toIrSymbol()
private val kMutableProperty0Class = builtIns.kMutableProperty0.toIrSymbol()
private val kMutableProperty1Class = builtIns.kMutableProperty1.toIrSymbol()
private val kMutableProperty2Class = builtIns.kMutableProperty2.toIrSymbol()
val functionClass = builtIns.getBuiltInClassByFqName(FqName("kotlin.Function")).toIrSymbol()
val kFunctionClass = builtIns.getBuiltInClassByFqName(FqName("kotlin.reflect.KFunction")).toIrSymbol()
fun getKPropertyClass(mutable: Boolean, n: Int): IrClassSymbol = when (n) {
0 -> if (mutable) kMutableProperty0Class else kProperty0Class
1 -> if (mutable) kMutableProperty1Class else kProperty1Class
2 -> if (mutable) kMutableProperty2Class else kProperty2Class
else -> error("No KProperty for n=$n mutable=$mutable")
}
// TODO switch to IrType
val primitiveTypes = listOf(bool, char, byte, short, int, float, long, double)
val primitiveIrTypes = listOf(booleanType, charType, byteType, shortType, intType, floatType, longType, doubleType)
private val primitiveIrTypesWithComparisons = listOf(charType, byteType, shortType, intType, floatType, longType, doubleType)
private val primitiveFloatingPointIrTypes = listOf(floatType, doubleType)
val primitiveArrays = PrimitiveType.values().map { builtIns.getPrimitiveArrayClassDescriptor(it).toIrSymbol() }
val primitiveArrayElementTypes = primitiveArrays.zip(primitiveIrTypes).toMap()
val primitiveArrayForType = primitiveArrayElementTypes.asSequence().associate { it.value to it.key }
val primitiveTypeToIrType = mapOf(
PrimitiveType.BOOLEAN to booleanType,
PrimitiveType.CHAR to charType,
PrimitiveType.BYTE to byteType,
PrimitiveType.SHORT to shortType,
PrimitiveType.INT to intType,
PrimitiveType.FLOAT to floatType,
PrimitiveType.LONG to longType,
PrimitiveType.DOUBLE to doubleType
)
val lessFunByOperandType = primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(OperatorNames.LESS)
val lessOrEqualFunByOperandType = primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(OperatorNames.LESS_OR_EQUAL)
val greaterOrEqualFunByOperandType = primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(OperatorNames.GREATER_OR_EQUAL)
val greaterFunByOperandType = primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(OperatorNames.GREATER)
val ieee754equalsFunByOperandType =
primitiveFloatingPointIrTypes.map {
it.classifierOrFail to defineOperator(OperatorNames.IEEE754_EQUALS, booleanType, listOf(it.makeNullable(), it.makeNullable()))
}.toMap()
private val booleanNot = builtIns.boolean.unsubstitutedMemberScope.getContributedFunctions(Name.identifier("not"), NoLookupLocation.FROM_BACKEND).single()
val booleanNotSymbol = symbolTable.referenceSimpleFunction(booleanNot)
val eqeqeqSymbol = defineOperator(OperatorNames.EQEQEQ, booleanType, listOf(anyNType, anyNType))
val eqeqSymbol = defineOperator(OperatorNames.EQEQ, booleanType, listOf(anyNType, anyNType))
val throwCceSymbol = defineOperator(OperatorNames.THROW_CCE, nothingType, listOf())
val throwIseSymbol = defineOperator(OperatorNames.THROW_ISE, nothingType, listOf())
val andandSymbol = defineOperator(OperatorNames.ANDAND, booleanType, listOf(booleanType, booleanType))
val ororSymbol = defineOperator(OperatorNames.OROR, booleanType, listOf(booleanType, booleanType))
val noWhenBranchMatchedExceptionSymbol = defineOperator(OperatorNames.NO_WHEN_BRANCH_MATCHED_EXCEPTION, nothingType, listOf())
val illegalArgumentExceptionSymbol = defineOperator(OperatorNames.ILLEGAL_ARGUMENT_EXCEPTION, nothingType, listOf(stringType))
val checkNotNullSymbol = defineCheckNotNullOperator()
private fun TypeConstructor.makeNonNullType() = KotlinTypeFactory.simpleType(Annotations.EMPTY, this, listOf(), false)
private fun TypeConstructor.makeNullableType() = KotlinTypeFactory.simpleType(Annotations.EMPTY, this, listOf(), true)
val dataClassArrayMemberHashCodeSymbol = defineOperator("dataClassArrayMemberHashCode", intType, listOf(anyType))
val dataClassArrayMemberToStringSymbol = defineOperator("dataClassArrayMemberToString", stringType, listOf(anyNType))
fun function(n: Int): IrClassSymbol = functionFactory.functionN(n).symbol
fun suspendFunction(n: Int): IrClassSymbol = functionFactory.suspendFunctionN(n).symbol
companion object {
val KOTLIN_INTERNAL_IR_FQN = FqName("kotlin.internal.ir")
val BUILTIN_OPERATOR = object : IrDeclarationOriginImpl("OPERATOR") {}
}
object OperatorNames {
const val LESS = "less"
const val LESS_OR_EQUAL = "lessOrEqual"
const val GREATER = "greater"
const val GREATER_OR_EQUAL = "greaterOrEqual"
const val EQEQ = "EQEQ"
const val EQEQEQ = "EQEQEQ"
const val IEEE754_EQUALS = "ieee754equals"
const val THROW_CCE = "THROW_CCE"
const val THROW_ISE = "THROW_ISE"
const val NO_WHEN_BRANCH_MATCHED_EXCEPTION = "noWhenBranchMatchedException"
const val ILLEGAL_ARGUMENT_EXCEPTION = "illegalArgumentException"
const val ANDAND = "ANDAND"
const val OROR = "OROR"
}
}
@@ -0,0 +1,520 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.descriptors
import org.jetbrains.kotlin.builtins.BuiltInsPackageFragment
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.builtins.UnsignedType
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.TypeParameterDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.BuiltInOperatorNames
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFactory
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeBuilder
import org.jetbrains.kotlin.ir.types.impl.buildSimpleType
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.referenceClassifier
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
@ObsoleteDescriptorBasedAPI
class IrBuiltInsOverDescriptors(
val builtIns: KotlinBuiltIns,
private val typeTranslator: TypeTranslator,
private val symbolTable: SymbolTable
) : IrBuiltIns() {
override val languageVersionSettings = typeTranslator.languageVersionSettings
private var _functionFactory: IrAbstractDescriptorBasedFunctionFactory? = null
var functionFactory: IrAbstractDescriptorBasedFunctionFactory
get() =
synchronized(this) {
if (_functionFactory == null) {
_functionFactory = IrDescriptorBasedFunctionFactory(this, symbolTable)
}
_functionFactory!!
}
set(value) {
synchronized(this) {
if (_functionFactory != null) {
error("functionFactory already set")
} else {
_functionFactory = value
}
}
}
override val irFactory: IrFactory = symbolTable.irFactory
private val builtInsModule = builtIns.builtInsModule
private val packageFragmentDescriptor = IrBuiltinsPackageFragmentDescriptorImpl(builtInsModule, KOTLIN_INTERNAL_IR_FQN)
val packageFragment =
IrExternalPackageFragmentImpl(symbolTable.referenceExternalPackageFragment(packageFragmentDescriptor), KOTLIN_INTERNAL_IR_FQN)
private fun ClassDescriptor.toIrSymbol() = symbolTable.referenceClass(this)
private fun KotlinType.toIrType() = typeTranslator.translateType(this)
private fun defineOperator(name: String, returnType: IrType, valueParameterTypes: List<IrType>): IrSimpleFunctionSymbol {
val operatorDescriptor =
IrSimpleBuiltinOperatorDescriptorImpl(packageFragmentDescriptor, Name.identifier(name), returnType.originalKotlinType!!)
for ((i, valueParameterType) in valueParameterTypes.withIndex()) {
operatorDescriptor.addValueParameter(
IrBuiltinValueParameterDescriptorImpl(
operatorDescriptor, Name.identifier("arg$i"), i, valueParameterType.originalKotlinType!!
)
)
}
val symbol = symbolTable.declareSimpleFunctionIfNotExists(operatorDescriptor) {
val operator = irFactory.createFunction(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, BUILTIN_OPERATOR, it, Name.identifier(name), DescriptorVisibilities.PUBLIC, Modality.FINAL,
returnType, isInline = false, isExternal = false, isTailrec = false, isSuspend = false,
isOperator = false, isInfix = false, isExpect = false, isFakeOverride = false
)
operator.parent = packageFragment
packageFragment.declarations += operator
operator.valueParameters = valueParameterTypes.withIndex().map { (i, valueParameterType) ->
val valueParameterDescriptor = operatorDescriptor.valueParameters[i]
val valueParameterSymbol = IrValueParameterSymbolImpl(valueParameterDescriptor)
irFactory.createValueParameter(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, BUILTIN_OPERATOR, valueParameterSymbol, Name.identifier("arg$i"), i,
valueParameterType, null, isCrossinline = false, isNoinline = false, isHidden = false, isAssignable = false
).apply {
parent = operator
}
}
operator
}
return symbol.symbol
}
private fun defineCheckNotNullOperator(): IrSimpleFunctionSymbol {
val name = Name.identifier("CHECK_NOT_NULL")
val typeParameterDescriptor: TypeParameterDescriptor
val valueParameterDescriptor: ValueParameterDescriptor
val returnKotlinType: SimpleType
val valueKotlinType: SimpleType
// Note: We still need a complete function descriptor here because `CHECK_NOT_NULL` is being substituted by psi2ir
val operatorDescriptor = SimpleFunctionDescriptorImpl.create(
packageFragmentDescriptor,
Annotations.EMPTY,
name,
CallableMemberDescriptor.Kind.SYNTHESIZED,
SourceElement.NO_SOURCE
).apply {
typeParameterDescriptor = TypeParameterDescriptorImpl.createForFurtherModification(
this, Annotations.EMPTY, false, Variance.INVARIANT, Name.identifier("T0"),
0, SourceElement.NO_SOURCE, LockBasedStorageManager.NO_LOCKS
).apply {
addUpperBound(any)
setInitialized()
}
valueKotlinType = typeParameterDescriptor.typeConstructor.makeNullableType()
valueParameterDescriptor = ValueParameterDescriptorImpl(
this, null, 0, Annotations.EMPTY, Name.identifier("arg0"), valueKotlinType,
declaresDefaultValue = false, isCrossinline = false, isNoinline = false, varargElementType = null,
source = SourceElement.NO_SOURCE
)
returnKotlinType = typeParameterDescriptor.typeConstructor.makeNonNullType()
initialize(
null, null, listOf(typeParameterDescriptor), listOf(valueParameterDescriptor), returnKotlinType,
Modality.FINAL, DescriptorVisibilities.PUBLIC
)
}
val typeParameterSymbol = IrTypeParameterSymbolImpl(typeParameterDescriptor)
val typeParameter = irFactory.createTypeParameter(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, BUILTIN_OPERATOR, typeParameterSymbol, Name.identifier("T0"), 0, true, Variance.INVARIANT
).apply {
superTypes += anyType
}
val returnIrType = IrSimpleTypeBuilder().run {
classifier = typeParameterSymbol
kotlinType = returnKotlinType
hasQuestionMark = false
buildSimpleType()
}
val valueIrType = IrSimpleTypeBuilder().run {
classifier = typeParameterSymbol
kotlinType = valueKotlinType
hasQuestionMark = true
buildSimpleType()
}
return symbolTable.declareSimpleFunctionIfNotExists(operatorDescriptor) {
val operator = irFactory.createFunction(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, BUILTIN_OPERATOR, it, name, DescriptorVisibilities.PUBLIC, Modality.FINAL, returnIrType,
isInline = false, isExternal = false, isTailrec = false, isSuspend = false, isOperator = false, isInfix = false,
isExpect = false, isFakeOverride = false
)
operator.parent = packageFragment
packageFragment.declarations += operator
val valueParameterSymbol = IrValueParameterSymbolImpl(valueParameterDescriptor)
val valueParameter = irFactory.createValueParameter(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, BUILTIN_OPERATOR, valueParameterSymbol, Name.identifier("arg0"), 0,
valueIrType, null, isCrossinline = false, isNoinline = false, isHidden = false, isAssignable = false
)
valueParameter.parent = operator
typeParameter.parent = operator
operator.valueParameters += valueParameter
operator.typeParameters += typeParameter
operator
}.symbol
}
private fun defineComparisonOperator(name: String, operandType: IrType) =
defineOperator(name, booleanType, listOf(operandType, operandType))
private fun List<IrType>.defineComparisonOperatorForEachIrType(name: String) =
associate { it.classifierOrFail to defineComparisonOperator(name, it) }
val any = builtIns.anyType
override val anyType = any.toIrType()
override val anyClass = builtIns.any.toIrSymbol()
override val anyNType = anyType.withHasQuestionMark(true)
val bool = builtIns.booleanType
override val booleanType = bool.toIrType()
override val booleanClass = builtIns.boolean.toIrSymbol()
val char = builtIns.charType
override val charType = char.toIrType()
override val charClass = builtIns.char.toIrSymbol()
val number = builtIns.number.defaultType
override val numberType = number.toIrType()
override val numberClass = builtIns.number.toIrSymbol()
val byte = builtIns.byteType
override val byteType = byte.toIrType()
override val byteClass = builtIns.byte.toIrSymbol()
val short = builtIns.shortType
override val shortType = short.toIrType()
override val shortClass = builtIns.short.toIrSymbol()
val int = builtIns.intType
override val intType = int.toIrType()
override val intClass = builtIns.int.toIrSymbol()
val long = builtIns.longType
override val longType = long.toIrType()
override val longClass = builtIns.long.toIrSymbol()
val float = builtIns.floatType
override val floatType = float.toIrType()
override val floatClass = builtIns.float.toIrSymbol()
val double = builtIns.doubleType
override val doubleType = double.toIrType()
override val doubleClass = builtIns.double.toIrSymbol()
val nothing = builtIns.nothingType
override val nothingType = nothing.toIrType()
override val nothingClass = builtIns.nothing.toIrSymbol()
override val nothingNType = nothingType.withHasQuestionMark(true)
val unit = builtIns.unitType
override val unitType = unit.toIrType()
override val unitClass = builtIns.unit.toIrSymbol()
val string = builtIns.stringType
override val stringType = string.toIrType()
override val stringClass = builtIns.string.toIrSymbol()
// TODO: check if correct
override val charSequenceClass = findClass(Name.identifier("CharSequence"), "kotlin")!!
override val collectionClass = builtIns.collection.toIrSymbol()
override val setClass = builtIns.set.toIrSymbol()
override val listClass = builtIns.list.toIrSymbol()
override val mapClass = builtIns.map.toIrSymbol()
override val mapEntryClass = builtIns.mapEntry.toIrSymbol()
override val iterableClass = builtIns.iterable.toIrSymbol()
override val iteratorClass = builtIns.iterator.toIrSymbol()
override val listIteratorClass = builtIns.listIterator.toIrSymbol()
override val mutableCollectionClass = builtIns.mutableCollection.toIrSymbol()
override val mutableSetClass = builtIns.mutableSet.toIrSymbol()
override val mutableListClass = builtIns.mutableList.toIrSymbol()
override val mutableMapClass = builtIns.mutableMap.toIrSymbol()
override val mutableMapEntryClass = builtIns.mutableMapEntry.toIrSymbol()
override val mutableIterableClass = builtIns.mutableIterable.toIrSymbol()
override val mutableIteratorClass = builtIns.mutableIterator.toIrSymbol()
override val mutableListIteratorClass = builtIns.mutableListIterator.toIrSymbol()
override val comparableClass = builtIns.comparable.toIrSymbol()
override val arrayClass = builtIns.array.toIrSymbol()
override val throwableType = builtIns.throwable.defaultType.toIrType()
override val throwableClass = builtIns.throwable.toIrSymbol()
override val kCallableClass = builtIns.kCallable.toIrSymbol()
override val kPropertyClass = builtIns.kProperty.toIrSymbol()
override val kClassClass = builtIns.kClass.toIrSymbol()
override val kProperty0Class = builtIns.kProperty0.toIrSymbol()
override val kProperty1Class = builtIns.kProperty1.toIrSymbol()
override val kProperty2Class = builtIns.kProperty2.toIrSymbol()
override val kMutableProperty0Class = builtIns.kMutableProperty0.toIrSymbol()
override val kMutableProperty1Class = builtIns.kMutableProperty1.toIrSymbol()
override val kMutableProperty2Class = builtIns.kMutableProperty2.toIrSymbol()
override val functionClass = builtIns.getBuiltInClassByFqName(FqName("kotlin.Function")).toIrSymbol()
override val kFunctionClass = builtIns.getBuiltInClassByFqName(FqName("kotlin.reflect.KFunction")).toIrSymbol()
override val annotationClass: IrClassSymbol = builtIns.annotation.toIrSymbol()
override val annotationType: IrType = builtIns.annotationType.toIrType()
override fun getKPropertyClass(mutable: Boolean, n: Int): IrClassSymbol = when (n) {
0 -> if (mutable) kMutableProperty0Class else kProperty0Class
1 -> if (mutable) kMutableProperty1Class else kProperty1Class
2 -> if (mutable) kMutableProperty2Class else kProperty2Class
else -> error("No KProperty for n=$n mutable=$mutable")
}
override val primitiveTypeToIrType = mapOf(
PrimitiveType.BOOLEAN to booleanType,
PrimitiveType.CHAR to charType,
PrimitiveType.BYTE to byteType,
PrimitiveType.SHORT to shortType,
PrimitiveType.INT to intType,
PrimitiveType.FLOAT to floatType,
PrimitiveType.LONG to longType,
PrimitiveType.DOUBLE to doubleType
)
// TODO switch to IrType
val primitiveTypes = listOf(bool, char, byte, short, int, float, long, double)
override val primitiveIrTypes = listOf(booleanType, charType, byteType, shortType, intType, floatType, longType, doubleType)
override val primitiveIrTypesWithComparisons = listOf(charType, byteType, shortType, intType, floatType, longType, doubleType)
override val primitiveFloatingPointIrTypes = listOf(floatType, doubleType)
override val byteArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.BYTE).toIrSymbol()
override val charArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.CHAR).toIrSymbol()
override val shortArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.SHORT).toIrSymbol()
override val intArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.INT).toIrSymbol()
override val longArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.LONG).toIrSymbol()
override val floatArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.FLOAT).toIrSymbol()
override val doubleArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.DOUBLE).toIrSymbol()
override val booleanArray = builtIns.getPrimitiveArrayClassDescriptor(PrimitiveType.BOOLEAN).toIrSymbol()
override val primitiveArraysToPrimitiveTypes = PrimitiveType.values().associate { builtIns.getPrimitiveArrayClassDescriptor(it).toIrSymbol() to it }
override val primitiveArrays = primitiveArraysToPrimitiveTypes.keys
override val primitiveArrayElementTypes = primitiveArraysToPrimitiveTypes.mapValues { primitiveTypeToIrType[it.value] }
override val primitiveArrayForType = primitiveArrayElementTypes.asSequence().associate { it.value to it.key }
override val unsignedArrays: Set<IrClassSymbol> = UnsignedType.values().mapNotNullTo(mutableSetOf()) { unsignedType ->
builtIns.builtInsModule.findClassAcrossModuleDependencies(unsignedType.arrayClassId)?.toIrSymbol()
}
override val lessFunByOperandType = primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(BuiltInOperatorNames.LESS)
override val lessOrEqualFunByOperandType = primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(BuiltInOperatorNames.LESS_OR_EQUAL)
override val greaterOrEqualFunByOperandType = primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(BuiltInOperatorNames.GREATER_OR_EQUAL)
override val greaterFunByOperandType = primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(BuiltInOperatorNames.GREATER)
override val ieee754equalsFunByOperandType =
primitiveFloatingPointIrTypes.map {
it.classifierOrFail to defineOperator(BuiltInOperatorNames.IEEE754_EQUALS, booleanType, listOf(it.makeNullable(), it.makeNullable()))
}.toMap()
val booleanNot = builtIns.boolean.unsubstitutedMemberScope.getContributedFunctions(Name.identifier("not"), NoLookupLocation.FROM_BACKEND).single()
override val booleanNotSymbol = symbolTable.referenceSimpleFunction(booleanNot)
override val eqeqeqSymbol = defineOperator(BuiltInOperatorNames.EQEQEQ, booleanType, listOf(anyNType, anyNType))
override val eqeqSymbol = defineOperator(BuiltInOperatorNames.EQEQ, booleanType, listOf(anyNType, anyNType))
override val throwCceSymbol = defineOperator(BuiltInOperatorNames.THROW_CCE, nothingType, listOf())
override val throwIseSymbol = defineOperator(BuiltInOperatorNames.THROW_ISE, nothingType, listOf())
override val andandSymbol = defineOperator(BuiltInOperatorNames.ANDAND, booleanType, listOf(booleanType, booleanType))
override val ororSymbol = defineOperator(BuiltInOperatorNames.OROR, booleanType, listOf(booleanType, booleanType))
override val noWhenBranchMatchedExceptionSymbol = defineOperator(BuiltInOperatorNames.NO_WHEN_BRANCH_MATCHED_EXCEPTION, nothingType, listOf())
override val illegalArgumentExceptionSymbol = defineOperator(BuiltInOperatorNames.ILLEGAL_ARGUMENT_EXCEPTION, nothingType, listOf(stringType))
override val checkNotNullSymbol = defineCheckNotNullOperator()
private fun TypeConstructor.makeNonNullType() = KotlinTypeFactory.simpleType(Annotations.EMPTY, this, listOf(), false)
private fun TypeConstructor.makeNullableType() = KotlinTypeFactory.simpleType(Annotations.EMPTY, this, listOf(), true)
override val dataClassArrayMemberHashCodeSymbol = defineOperator("dataClassArrayMemberHashCode", intType, listOf(anyType))
override val dataClassArrayMemberToStringSymbol = defineOperator("dataClassArrayMemberToString", stringType, listOf(anyNType))
override val intTimesSymbol: IrSimpleFunctionSymbol =
builtIns.int.unsubstitutedMemberScope.findFirstFunction("times") {
KotlinTypeChecker.DEFAULT.equalTypes(it.valueParameters[0].type, int)
}.let { symbolTable.referenceSimpleFunction(it) }
override val intPlusSymbol: IrSimpleFunctionSymbol =
builtIns.int.unsubstitutedMemberScope.findFirstFunction("plus") {
KotlinTypeChecker.DEFAULT.equalTypes(it.valueParameters[0].type, int)
}.let { symbolTable.referenceSimpleFunction(it) }
override val arrayOf = findFunctions(Name.identifier("arrayOf")).first {
it.descriptor.extensionReceiverParameter == null && it.descriptor.dispatchReceiverParameter == null &&
it.descriptor.valueParameters.size == 1 && it.descriptor.valueParameters[0].varargElementType != null
}
override val arrayOfNulls = findFunctions(Name.identifier("arrayOfNulls")).first {
it.descriptor.extensionReceiverParameter == null && it.descriptor.dispatchReceiverParameter == null &&
it.descriptor.valueParameters.size == 1 && KotlinBuiltIns.isInt(it.descriptor.valueParameters[0].type)
}
override val enumClass = builtIns.enum.toIrSymbol()
private fun builtInsPackage(vararg packageNameSegments: String) =
builtIns.builtInsModule.getPackage(FqName.fromSegments(listOf(*packageNameSegments))).memberScope
override fun findFunctions(name: Name, vararg packageNameSegments: String): Iterable<IrSimpleFunctionSymbol> =
builtInsPackage(*packageNameSegments).getContributedFunctions(name, NoLookupLocation.FROM_BACKEND).map {
symbolTable.referenceSimpleFunction(it)
}
override fun findClass(name: Name, vararg packageNameSegments: String): IrClassSymbol? =
(builtInsPackage(*packageNameSegments).getContributedClassifier(
name,
NoLookupLocation.FROM_BACKEND
) as? ClassDescriptor)?.let { symbolTable.referenceClass(it) }
private val binaryOperatorCache = mutableMapOf<Triple<Name, IrType, IrType>, IrSimpleFunctionSymbol>()
override fun getBinaryOperator(name: Name, lhsType: IrType, rhsType: IrType): IrSimpleFunctionSymbol {
require(lhsType is IrSimpleType) { "Expected IrSimpleType in getBinaryOperator, got $lhsType" }
val classifier = lhsType.classifier
require(classifier is IrClassSymbol && classifier.isBound) {
"Expected a bound IrClassSymbol for lhsType in getBinaryOperator, got $classifier"
}
val key = Triple(name, lhsType, rhsType)
return binaryOperatorCache.getOrPut(key) {
classifier.functions.single {
val function = it.owner
function.name == name && function.valueParameters.size == 1 && function.valueParameters[0].type == rhsType
}
}
}
private val unaryOperatorCache = mutableMapOf<Pair<Name, IrType>, IrSimpleFunctionSymbol>()
override fun getUnaryOperator(name: Name, receiverType: IrType): IrSimpleFunctionSymbol {
require(receiverType is IrSimpleType) { "Expected IrSimpleType in getBinaryOperator, got $receiverType" }
val classifier = receiverType.classifier
require(classifier is IrClassSymbol && classifier.isBound) {
"Expected a bound IrClassSymbol for receiverType in getBinaryOperator, got $classifier"
}
val key = Pair(name, receiverType)
return unaryOperatorCache.getOrPut(key) {
classifier.functions.single {
val function = it.owner
function.name == name && function.valueParameters.isEmpty()
}
}
}
override val toUIntByExtensionReceiver: Map<IrClassifierSymbol, IrSimpleFunctionSymbol> =
builtInsPackage("kotlin").getContributedFunctions(
Name.identifier("toUInt"),
NoLookupLocation.FROM_BACKEND
).filter { it.containingDeclaration !is BuiltInsPackageFragment && it.extensionReceiverParameter != null }
.map {
val klass = symbolTable.referenceClassifier(it.extensionReceiverParameter!!.type.constructor.declarationDescriptor!!)
val function = symbolTable.referenceSimpleFunction(it)
klass to function
}.toMap()
override val toULongByExtensionReceiver: Map<IrClassifierSymbol, IrSimpleFunctionSymbol> =
builtInsPackage("kotlin").getContributedFunctions(
Name.identifier("toULong"),
NoLookupLocation.FROM_BACKEND
).filter { it.containingDeclaration !is BuiltInsPackageFragment && it.extensionReceiverParameter != null }
.map {
val klass = symbolTable.referenceClassifier(it.extensionReceiverParameter!!.type.constructor.declarationDescriptor!!)
val function = symbolTable.referenceSimpleFunction(it)
klass to function
}.toMap()
override val extensionToString: IrSimpleFunctionSymbol = findFunctions(Name.identifier("toString"), "kotlin").first {
val descriptor = it.descriptor
descriptor is SimpleFunctionDescriptor && descriptor.dispatchReceiverParameter == null &&
descriptor.extensionReceiverParameter != null &&
KotlinBuiltIns.isNullableAny(descriptor.extensionReceiverParameter!!.type) && descriptor.valueParameters.size == 0
}
override val stringPlus: IrSimpleFunctionSymbol = findFunctions(Name.identifier("plus"), "kotlin").first {
val descriptor = it.descriptor
descriptor is SimpleFunctionDescriptor && descriptor.dispatchReceiverParameter == null &&
descriptor.extensionReceiverParameter != null &&
KotlinBuiltIns.isStringOrNullableString(descriptor.extensionReceiverParameter!!.type) &&
descriptor.valueParameters.size == 1 &&
KotlinBuiltIns.isNullableAny(descriptor.valueParameters.first().type)
}
override fun functionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass =
functionFactory.functionN(arity, declarator)
override fun kFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass =
functionFactory.kFunctionN(arity, declarator)
override fun suspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass =
functionFactory.suspendFunctionN(arity, declarator)
override fun kSuspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass =
functionFactory.kSuspendFunctionN(arity, declarator)
override fun functionN(arity: Int): IrClass = functionFactory.functionN(arity)
override fun kFunctionN(arity: Int): IrClass = functionFactory.kFunctionN(arity)
override fun suspendFunctionN(arity: Int): IrClass = functionFactory.suspendFunctionN(arity)
override fun kSuspendFunctionN(arity: Int): IrClass = functionFactory.kSuspendFunctionN(arity)
override val getProgressionLastElementByReturnType: Map<IrClassifierSymbol?, IrSimpleFunctionSymbol> =
builtInsPackage("kotlin", "internal")
.getContributedFunctions(Name.identifier("getProgressionLastElement"), NoLookupLocation.FROM_BACKEND)
.filter { it.containingDeclaration !is BuiltInsPackageFragment }
.map { d ->
val klass = d.returnType?.constructor?.declarationDescriptor?.let { symbolTable.referenceClassifier(it) }
val function = symbolTable.referenceSimpleFunction(d)
klass to function
}
.toMap()
}
private inline fun MemberScope.findFirstFunction(name: String, predicate: (CallableMemberDescriptor) -> Boolean) =
getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).first(predicate)
@@ -5,9 +5,9 @@
package org.jetbrains.kotlin.ir.descriptors
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.StandardNames.KOTLIN_REFLECT_FQ_NAME
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.Variance
@OptIn(ObsoleteDescriptorBasedAPI::class)
abstract class IrAbstractFunctionFactory {
abstract class IrAbstractDescriptorBasedFunctionFactory {
abstract fun functionClassDescriptor(arity: Int): FunctionClassDescriptor
abstract fun kFunctionClassDescriptor(arity: Int): FunctionClassDescriptor
@@ -74,11 +74,16 @@ abstract class IrAbstractFunctionFactory {
val classOrigin = object : IrDeclarationOriginImpl("FUNCTION_INTERFACE_CLASS") {}
val memberOrigin = object : IrDeclarationOriginImpl("FUNCTION_INTERFACE_MEMBER") {}
const val offset = SYNTHETIC_OFFSET
internal fun functionClassName(isK: Boolean, isSuspend: Boolean, arity: Int): String =
"${if (isK) "K" else ""}${if (isSuspend) "Suspend" else ""}Function$arity"
}
}
@OptIn(ObsoleteDescriptorBasedAPI::class)
class IrFunctionFactory(private val irBuiltIns: IrBuiltIns, private val symbolTable: SymbolTable) : IrAbstractFunctionFactory() {
class IrDescriptorBasedFunctionFactory(
private val irBuiltIns: IrBuiltInsOverDescriptors, private val symbolTable: SymbolTable
) : IrAbstractDescriptorBasedFunctionFactory() {
// TODO: Lazieness
@@ -89,9 +94,25 @@ class IrFunctionFactory(private val irBuiltIns: IrBuiltIns, private val symbolTa
private val irFactory: IrFactory get() = symbolTable.irFactory
val functionClass = symbolTable.referenceClass(irBuiltIns.builtIns.getBuiltInClassByFqName(FqName("kotlin.Function")))
val kFunctionClass = symbolTable.referenceClass(irBuiltIns.builtIns.getBuiltInClassByFqName(FqName("kotlin.reflect.KFunction")))
override fun functionClassDescriptor(arity: Int): FunctionClassDescriptor =
irBuiltIns.builtIns.getFunction(arity) as FunctionClassDescriptor
override fun suspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor =
irBuiltIns.builtIns.getSuspendFunction(arity) as FunctionClassDescriptor
override fun kFunctionClassDescriptor(arity: Int): FunctionClassDescriptor {
val kFunctionFqn = reflectFunctionClassFqn(reflectionFunctionClassName(false, arity))
return irBuiltIns.builtIns.getBuiltInClassByFqName(kFunctionFqn) as FunctionClassDescriptor
}
override fun kSuspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor {
val kFunctionFqn = reflectFunctionClassFqn(reflectionFunctionClassName(true, arity))
return irBuiltIns.builtIns.getBuiltInClassByFqName(kFunctionFqn) as FunctionClassDescriptor
}
override fun functionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass {
return functionNMap.getOrPut(arity) {
symbolTable.declarator { symbol ->
@@ -102,9 +123,6 @@ class IrFunctionFactory(private val irBuiltIns: IrBuiltIns, private val symbolTa
}
}
override fun suspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor =
irBuiltIns.builtIns.getSuspendFunction(arity) as FunctionClassDescriptor
override fun suspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass {
return suspendFunctionNMap.getOrPut(arity) {
symbolTable.declarator { symbol ->
@@ -115,11 +133,6 @@ class IrFunctionFactory(private val irBuiltIns: IrBuiltIns, private val symbolTa
}
}
override fun kFunctionClassDescriptor(arity: Int): FunctionClassDescriptor {
val kFunctionFqn = reflectFunctionClassFqn(reflectionFunctionClassName(false, arity))
return irBuiltIns.builtIns.getBuiltInClassByFqName(kFunctionFqn) as FunctionClassDescriptor
}
override fun kFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass {
return kFunctionNMap.getOrPut(arity) {
symbolTable.declarator { symbol ->
@@ -130,11 +143,6 @@ class IrFunctionFactory(private val irBuiltIns: IrBuiltIns, private val symbolTa
}
}
override fun kSuspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor {
val kFunctionFqn = reflectFunctionClassFqn(reflectionFunctionClassName(true, arity))
return irBuiltIns.builtIns.getBuiltInClassByFqName(kFunctionFqn) as FunctionClassDescriptor
}
override fun kSuspendFunctionN(arity: Int, declarator: SymbolTable.((IrClassSymbol) -> IrClass) -> IrClass): IrClass {
return kSuspendFunctionNMap.getOrPut(arity) {
symbolTable.declarator { symbol ->
@@ -145,21 +153,11 @@ class IrFunctionFactory(private val irBuiltIns: IrBuiltIns, private val symbolTa
}
}
companion object {
private fun reflectFunctionClassFqn(shortName: Name): FqName = KOTLIN_REFLECT_FQ_NAME.child(shortName)
private fun reflectionFunctionClassName(isSuspend: Boolean, arity: Int): Name =
Name.identifier("K${if (isSuspend) "Suspend" else ""}Function$arity")
private fun functionClassName(isK: Boolean, isSuspend: Boolean, arity: Int): String =
"${if (isK) "K" else ""}${if (isSuspend) "Suspend" else ""}Function$arity"
}
private sealed class FunctionDescriptorFactory(protected val symbolTable: SymbolTable) {
abstract fun memberDescriptor(name: String, factory: (IrSimpleFunctionSymbol) -> IrSimpleFunction): IrSimpleFunctionSymbol
abstract fun FunctionDescriptor.valueParameterDescriptor(index: Int): ValueParameterDescriptor
abstract fun typeParameterDescriptor(index: Int, factory: (IrTypeParameterSymbol) -> IrTypeParameter): IrTypeParameterSymbol
abstract fun classReceiverParameterDescriptor(): ReceiverParameterDescriptor
abstract fun FunctionDescriptor.memberReceiverParameterDescriptor(): ReceiverParameterDescriptor
class RealDescriptorFactory(private val classDescriptor: ClassDescriptor, symbolTable: SymbolTable) :
FunctionDescriptorFactory(symbolTable) {
@@ -189,11 +187,6 @@ class IrFunctionFactory(private val irBuiltIns: IrBuiltIns, private val symbolTa
override fun classReceiverParameterDescriptor(): ReceiverParameterDescriptor {
return classDescriptor.thisAsReceiverParameter
}
override fun FunctionDescriptor.memberReceiverParameterDescriptor(): ReceiverParameterDescriptor {
assert(containingDeclaration === classDescriptor)
return dispatchReceiverParameter ?: error("Expected dispatch receiver at $this")
}
}
}
@@ -276,24 +269,6 @@ class IrFunctionFactory(private val irBuiltIns: IrBuiltIns, private val symbolTa
return vDeclaration
}
private fun FunctionClassDescriptor.createFunctionClass(): IrClass {
val s = symbolTable.referenceClass(this)
if (s.isBound) return s.owner
return symbolTable.declareClass(this) {
val factory = FunctionDescriptorFactory.RealDescriptorFactory(this, symbolTable)
when (functionKind) {
FunctionClassKind.Function ->
createFunctionClass(it, false, false, arity, irBuiltIns.functionClass, kotlinPackageFragment, factory)
FunctionClassKind.SuspendFunction ->
createFunctionClass(it, false, true, arity, irBuiltIns.functionClass, kotlinCoroutinesPackageFragment, factory)
FunctionClassKind.KFunction ->
createFunctionClass(it, true, false, arity, irBuiltIns.kFunctionClass, kotlinReflectPackageFragment, factory)
FunctionClassKind.KSuspendFunction ->
createFunctionClass(it, true, true, arity, irBuiltIns.kFunctionClass, kotlinReflectPackageFragment, factory)
}
}
}
private fun IrClass.createMembers(isK: Boolean, isSuspend: Boolean, descriptorFactory: FunctionDescriptorFactory) {
if (!isK) {
val invokeSymbol = descriptorFactory.memberDescriptor("invoke") {
@@ -468,3 +443,28 @@ class IrFunctionFactory(private val irBuiltIns: IrBuiltIns, private val symbolTa
return klass
}
}
private fun reflectFunctionClassFqn(shortName: Name): FqName = KOTLIN_REFLECT_FQ_NAME.child(shortName)
private fun reflectionFunctionClassName(isSuspend: Boolean, arity: Int): Name =
Name.identifier("K${if (isSuspend) "Suspend" else ""}Function$arity")
@OptIn(ObsoleteDescriptorBasedAPI::class)
fun KotlinBuiltIns.functionClassDescriptor(arity: Int): FunctionClassDescriptor =
getFunction(arity) as FunctionClassDescriptor
@OptIn(ObsoleteDescriptorBasedAPI::class)
fun KotlinBuiltIns.suspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor =
getSuspendFunction(arity) as FunctionClassDescriptor
@OptIn(ObsoleteDescriptorBasedAPI::class)
fun KotlinBuiltIns.kFunctionClassDescriptor(arity: Int): FunctionClassDescriptor {
val kFunctionFqn = reflectFunctionClassFqn(reflectionFunctionClassName(false, arity))
return getBuiltInClassByFqName(kFunctionFqn) as FunctionClassDescriptor
}
@OptIn(ObsoleteDescriptorBasedAPI::class)
fun KotlinBuiltIns.kSuspendFunctionClassDescriptor(arity: Int): FunctionClassDescriptor {
val kFunctionFqn =
reflectFunctionClassFqn(reflectionFunctionClassName(true, arity))
return getBuiltInClassByFqName(kFunctionFqn) as FunctionClassDescriptor
}
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.*
@@ -5,10 +5,11 @@
package org.jetbrains.kotlin.ir.types
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.types.AbstractTypeCheckerContext
import org.jetbrains.kotlin.types.model.*
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
open class IrTypeCheckerContext(override val typeSystemContext: IrTypeSystemContext): AbstractTypeCheckerContext() {
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.ir.types
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.ir.types
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.impl.IrCapturedType
import org.jetbrains.kotlin.ir.types.impl.buildSimpleType
@@ -10,9 +10,9 @@ import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.symbols.FqNameEqualityChecker
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.ir.types
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.FqNameEqualityChecker
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.types.isNullable
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
/**
* A platform-, frontend-independent logic for generating synthetic members of data class: equals, hashCode, toString, componentN, and copy.
@@ -139,19 +138,6 @@ abstract class DataClassMembersGenerator(
+irReturnTrue()
}
private val intClass = context.builtIns.int
private val intType = context.builtIns.intType
private val intTimesSymbol: IrSimpleFunctionSymbol =
intClass.unsubstitutedMemberScope.findFirstFunction("times") {
KotlinTypeChecker.DEFAULT.equalTypes(it.valueParameters[0].type, intType)
}.let { symbolTable.referenceSimpleFunction(it) }
private val intPlusSymbol: IrSimpleFunctionSymbol =
intClass.unsubstitutedMemberScope.findFirstFunction("plus") {
KotlinTypeChecker.DEFAULT.equalTypes(it.valueParameters[0].type, intType)
}.let { symbolTable.referenceSimpleFunction(it) }
fun generateHashCodeMethodBody(properties: List<IrProperty>) {
if (properties.isEmpty()) {
+irReturn(irInt(0))
@@ -176,8 +162,8 @@ abstract class DataClassMembersGenerator(
+irResultVar
for (property in properties.drop(1)) {
val shiftedResult = irCallOp(intTimesSymbol, irIntType, irGet(irResultVar), irInt(31))
val irRhs = irCallOp(intPlusSymbol, irIntType, shiftedResult, getHashCodeOfProperty(property))
val shiftedResult = irCallOp(context.irBuiltIns.intTimesSymbol, irIntType, irGet(irResultVar), irInt(31))
val irRhs = irCallOp(context.irBuiltIns.intPlusSymbol, irIntType, shiftedResult, getHashCodeOfProperty(property))
+irSet(irResultVar.symbol, irRhs)
}
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.lazy.*
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
import org.jetbrains.kotlin.ir.linkage.IrProvider
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
@@ -6,11 +6,11 @@
package org.jetbrains.kotlin.ir.util
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.*