Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.jetbrains.kotlin.fir.backend.IrBuiltInsOverFir.kt Maven / Gradle / Ivy
/*
* 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.fir.backend
import org.jetbrains.kotlin.backend.common.ir.addDispatchReceiver
import org.jetbrains.kotlin.backend.common.serialization.signature.PublicIdSignatureComputer
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.builtins.UnsignedType
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.ir.BuiltInOperatorNames
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.declarations.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.util.OperatorNameConventions
import kotlin.reflect.KProperty
class IrBuiltInsOverFir(
private val components: Fir2IrComponents,
override val languageVersionSettings: LanguageVersionSettings,
private val moduleDescriptor: FirModuleDescriptor,
irMangler: KotlinMangler.IrMangler,
private val tryLoadBuiltInsFirst: Boolean = false
) : IrBuiltIns() {
override val irFactory: IrFactory = components.symbolTable.irFactory
private val kotlinPackage = StandardClassIds.BASE_KOTLIN_PACKAGE
private val kotlinInternalPackage = StandardClassIds.BASE_INTERNAL_PACKAGE
override val operatorsPackageFragment = createPackage(KOTLIN_INTERNAL_IR_FQN)
private val kotlinIrPackage = createPackage(kotlinPackage)
private val kotlinInternalIrPackage = createPackage(kotlinInternalPackage)
private val irSignatureBuilder = PublicIdSignatureComputer(irMangler)
override val booleanNotSymbol: IrSimpleFunctionSymbol by lazy {
boolean.ensureLazyContentsCreated()
booleanClass.owner.functions.first { it.name == OperatorNameConventions.NOT && it.returnType == booleanType }.symbol
}
private val any by createClass(kotlinIrPackage, IdSignatureValues.any, build = { modality = Modality.OPEN }) {
createConstructor()
createMemberFunction(
OperatorNameConventions.EQUALS, booleanType, "other" to anyNType,
modality = Modality.OPEN, isOperator = true, isIntrinsicConst = false
)
createMemberFunction("hashCode", intType, modality = Modality.OPEN, isIntrinsicConst = false)
createMemberFunction("toString", stringType, modality = Modality.OPEN, isIntrinsicConst = false)
}
override val anyClass: IrClassSymbol get() = any.klass
override val anyType: IrType get() = any.type
override val anyNType by lazy { anyType.makeNullable() }
private val number by createClass(kotlinIrPackage, IdSignatureValues.number, build = { modality = Modality.ABSTRACT }) {
configureSuperTypes()
for (targetPrimitive in primitiveIrTypesWithComparisons) {
createMemberFunction("to${targetPrimitive.classFqName!!.shortName().asString()}", targetPrimitive, modality = Modality.ABSTRACT)
}
finalizeClassDefinition()
}
override val numberClass: IrClassSymbol get() = number.klass
override val numberType: IrType get() = number.type
private val nothing by createClass(kotlinIrPackage, IdSignatureValues.nothing)
override val nothingClass: IrClassSymbol get() = nothing.klass
override val nothingType: IrType get() = nothing.type
override val nothingNType: IrType by lazy { nothingType.makeNullable() }
private val unit by createClass(kotlinIrPackage, IdSignatureValues.unit, build = { kind = ClassKind.OBJECT; modality = Modality.FINAL })
override val unitClass: IrClassSymbol get() = unit.klass
override val unitType: IrType get() = unit.type
private val boolean by createClass(kotlinIrPackage, IdSignatureValues._boolean) {
configureSuperTypes()
// TODO: dangerous dependency on call sequence, consider making extended BuiltInsClass to trigger lazy initialization
createMemberFunction(OperatorNameConventions.NOT, booleanType, isOperator = true).symbol
createMemberFunction(OperatorNameConventions.AND, booleanType, "other" to booleanType) { isInfix = true }
createMemberFunction(OperatorNameConventions.OR, booleanType, "other" to booleanType) { isInfix = true }
createMemberFunction(OperatorNameConventions.XOR, booleanType, "other" to booleanType) { isInfix = true }
createMemberFunction(
OperatorNameConventions.COMPARE_TO,
intType,
"other" to booleanType,
modality = Modality.OPEN,
isOperator = true
)
createIntrinsicConstOfToStringAndEquals()
finalizeClassDefinition()
}
override val booleanType: IrType get() = boolean.type
override val booleanClass: IrClassSymbol get() = boolean.klass
private val char by createClass(kotlinIrPackage, IdSignatureValues._char) {
configureSuperTypes(number)
createStandardNumericAndCharMembers(charType)
createMemberFunction(OperatorNameConventions.COMPARE_TO, intType, "other" to charType, modality = Modality.OPEN, isOperator = true)
createMemberFunction(OperatorNameConventions.PLUS, charType, "other" to intType, isOperator = true)
createMemberFunction(OperatorNameConventions.MINUS, charType, "other" to intType, isOperator = true)
createMemberFunction(OperatorNameConventions.MINUS, intType, "other" to charType, isOperator = true)
val charRange = referenceClassByClassId(StandardClassIds.CharRange)!!.owner.defaultType
createMemberFunction(OperatorNameConventions.RANGE_TO, charRange, "other" to charType, isIntrinsicConst = false)
createMemberFunction(OperatorNameConventions.RANGE_UNTIL, charRange, "other" to charType, isIntrinsicConst = false)
createIntrinsicConstOfToStringAndEquals()
finalizeClassDefinition()
}
override val charClass: IrClassSymbol get() = char.klass
override val charType: IrType get() = char.type
private val byte by kotlinIrPackage.createNumberClass(IdSignatureValues._byte)
override val byteType: IrType get() = byte.type
override val byteClass: IrClassSymbol get() = byte.klass
private val short by kotlinIrPackage.createNumberClass(IdSignatureValues._short)
override val shortType: IrType get() = short.type
override val shortClass: IrClassSymbol get() = short.klass
private val int by kotlinIrPackage.createNumberClass(IdSignatureValues._int)
override val intType: IrType get() = int.type
override val intClass: IrClassSymbol get() = int.klass
private val long by kotlinIrPackage.createNumberClass(IdSignatureValues._long)
override val longType: IrType get() = long.type
override val longClass: IrClassSymbol get() = long.klass
private val float by kotlinIrPackage.createNumberClass(IdSignatureValues._float)
override val floatType: IrType get() = float.type
override val floatClass: IrClassSymbol get() = float.klass
private val double by kotlinIrPackage.createNumberClass(IdSignatureValues._double)
override val doubleType: IrType get() = double.type
override val doubleClass: IrClassSymbol get() = double.klass
private val charSequence by createClass(
kotlinIrPackage, IdSignatureValues.charSequence,
build = { kind = ClassKind.INTERFACE; modality = Modality.OPEN }
) {
configureSuperTypes()
createProperty("length", intType, modality = Modality.ABSTRACT)
createMemberFunction(OperatorNameConventions.GET, charType, "index" to intType, modality = Modality.ABSTRACT, isOperator = true, isIntrinsicConst = false)
createMemberFunction("subSequence", defaultType, "startIndex" to intType, "endIndex" to intType, modality = Modality.ABSTRACT, isIntrinsicConst = false)
finalizeClassDefinition()
}
override val charSequenceClass: IrClassSymbol get() = charSequence.klass
private val string by createClass(kotlinIrPackage, IdSignatureValues.string) {
configureSuperTypes(charSequence)
createProperty("length", intType, modality = Modality.OPEN, isIntrinsicConst = true)
createMemberFunction(OperatorNameConventions.GET, charType, "index" to intType, modality = Modality.OPEN, isOperator = true)
createMemberFunction(
"subSequence",
charSequenceClass.defaultType,
"startIndex" to intType,
"endIndex" to intType,
modality = Modality.OPEN,
isIntrinsicConst = false
)
createMemberFunction(
OperatorNameConventions.COMPARE_TO,
intType,
"other" to defaultType,
modality = Modality.OPEN,
isOperator = true
)
createMemberFunction(OperatorNameConventions.PLUS, defaultType, "other" to anyNType, isOperator = true)
createIntrinsicConstOfToStringAndEquals()
finalizeClassDefinition()
}
override val stringClass: IrClassSymbol get() = string.klass
override val stringType: IrType get() = string.type
private val intrinsicConstAnnotationFqName = kotlinInternalPackage.child(Name.identifier("IntrinsicConstEvaluation"))
private val intrinsicConst = kotlinInternalIrPackage.createClass(intrinsicConstAnnotationFqName).apply {
owner.createConstructor()
owner.finalizeClassDefinition()
}
private val intrinsicConstAnnotation: IrConstructorCall = run {
val constructor = intrinsicConst.constructors.single()
IrConstructorCallImpl.Companion.fromSymbolOwner(intrinsicConst.defaultType, constructor)
}
private val array by createClass(kotlinIrPackage, IdSignatureValues.array) {
configureSuperTypes()
val typeParameter = addTypeParameter("T", anyNType)
addArrayMembers(typeParameter.defaultType)
finalizeClassDefinition()
}
override val arrayClass: IrClassSymbol get() = array.klass
private val intRangeType by lazy { referenceClassByClassId(StandardClassIds.IntRange)!!.owner.defaultType }
private val longRangeType by lazy { referenceClassByClassId(StandardClassIds.LongRange)!!.owner.defaultType }
private val annotation by loadClass(StandardClassIds.Annotation)
override val annotationClass: IrClassSymbol get() = annotation.klass
override val annotationType: IrType get() = annotation.type
private val collection by loadClass(StandardClassIds.Collection)
override val collectionClass: IrClassSymbol get() = collection.klass
private val set by loadClass(StandardClassIds.Set)
override val setClass: IrClassSymbol get() = set.klass
private val list by loadClass(StandardClassIds.List)
override val listClass: IrClassSymbol get() = list.klass
private val map by loadClass(StandardClassIds.Map)
override val mapClass: IrClassSymbol get() = map.klass
private val mapEntry by BuiltInsClass({ true to referenceClassByClassId(StandardClassIds.MapEntry)!! })
override val mapEntryClass: IrClassSymbol get() = mapEntry.klass
private val iterable by loadClass(StandardClassIds.Iterable)
override val iterableClass: IrClassSymbol get() = iterable.klass
private val iterator by loadClass(StandardClassIds.Iterator)
override val iteratorClass: IrClassSymbol get() = iterator.klass
private val listIterator by loadClass(StandardClassIds.ListIterator)
override val listIteratorClass: IrClassSymbol get() = listIterator.klass
private val mutableCollection by loadClass(StandardClassIds.MutableCollection)
override val mutableCollectionClass: IrClassSymbol get() = mutableCollection.klass
private val mutableSet by loadClass(StandardClassIds.MutableSet)
override val mutableSetClass: IrClassSymbol get() = mutableSet.klass
private val mutableList by loadClass(StandardClassIds.MutableList)
override val mutableListClass: IrClassSymbol get() = mutableList.klass
private val mutableMap by loadClass(StandardClassIds.MutableMap)
override val mutableMapClass: IrClassSymbol get() = mutableMap.klass
private val mutableMapEntry by BuiltInsClass({ true to referenceClassByClassId(StandardClassIds.MutableMapEntry)!! })
override val mutableMapEntryClass: IrClassSymbol get() = mutableMapEntry.klass
private val mutableIterable by loadClass(StandardClassIds.MutableIterable)
override val mutableIterableClass: IrClassSymbol get() = mutableIterable.klass
private val mutableIterator by loadClass(StandardClassIds.MutableIterator)
override val mutableIteratorClass: IrClassSymbol get() = mutableIterator.klass
private val mutableListIterator by loadClass(StandardClassIds.MutableListIterator)
override val mutableListIteratorClass: IrClassSymbol get() = mutableListIterator.klass
private val comparable by loadClass(StandardClassIds.Comparable)
override val comparableClass: IrClassSymbol get() = comparable.klass
override val throwableType: IrType by lazy { throwableClass.defaultType }
private val throwable by loadClass(StandardClassIds.Throwable)
override val throwableClass: IrClassSymbol get() = throwable.klass
private val kCallable by loadClass(StandardClassIds.KCallable)
override val kCallableClass: IrClassSymbol get() = kCallable.klass
private val kProperty by loadClass(StandardClassIds.KProperty)
override val kPropertyClass: IrClassSymbol get() = kProperty.klass
private val kClass by loadClass(StandardClassIds.KClass)
override val kClassClass: IrClassSymbol get() = kClass.klass
private val kProperty0 by loadClass(StandardClassIds.KProperty0)
override val kProperty0Class: IrClassSymbol get() = kProperty0.klass
private val kProperty1 by loadClass(StandardClassIds.KProperty1)
override val kProperty1Class: IrClassSymbol get() = kProperty1.klass
private val kProperty2 by loadClass(StandardClassIds.KProperty2)
override val kProperty2Class: IrClassSymbol get() = kProperty2.klass
private val kMutableProperty0 by loadClass(StandardClassIds.KMutableProperty0)
override val kMutableProperty0Class: IrClassSymbol get() = kMutableProperty0.klass
private val kMutableProperty1 by loadClass(StandardClassIds.KMutableProperty1)
override val kMutableProperty1Class: IrClassSymbol get() = kMutableProperty1.klass
private val kMutableProperty2 by loadClass(StandardClassIds.KMutableProperty2)
override val kMutableProperty2Class: IrClassSymbol get() = kMutableProperty2.klass
private val function by loadClass(StandardClassIds.Function)
override val functionClass: IrClassSymbol get() = function.klass
private val kFunction by loadClass(StandardClassIds.KFunction)
override val kFunctionClass: IrClassSymbol get() = kFunction.klass
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.LONG to longType,
PrimitiveType.FLOAT to floatType,
PrimitiveType.DOUBLE to doubleType
)
private val primitiveIntegralIrTypes = listOf(byteType, shortType, intType, longType)
override val primitiveFloatingPointIrTypes = listOf(floatType, doubleType)
private val primitiveNumericIrTypes = primitiveIntegralIrTypes + primitiveFloatingPointIrTypes
override val primitiveIrTypesWithComparisons = listOf(charType) + primitiveNumericIrTypes
override val primitiveIrTypes = listOf(booleanType) + primitiveIrTypesWithComparisons
private val baseIrTypes = primitiveIrTypes + stringType
private fun getPrimitiveArithmeticOperatorResultType(target: IrType, arg: IrType) =
when {
arg == doubleType -> arg
target in primitiveFloatingPointIrTypes -> target
arg in primitiveFloatingPointIrTypes -> arg
target == longType -> target
arg == longType -> arg
else -> intType
}
private val _booleanArray by createPrimitiveArrayClass(kotlinIrPackage, PrimitiveType.BOOLEAN)
private val _charArray by createPrimitiveArrayClass(kotlinIrPackage, PrimitiveType.CHAR)
private val _byteArray by createPrimitiveArrayClass(kotlinIrPackage, PrimitiveType.BYTE)
private val _shortArray by createPrimitiveArrayClass(kotlinIrPackage, PrimitiveType.SHORT)
private val _intArray by createPrimitiveArrayClass(kotlinIrPackage, PrimitiveType.INT)
private val _longArray by createPrimitiveArrayClass(kotlinIrPackage, PrimitiveType.LONG)
private val _floatArray by createPrimitiveArrayClass(kotlinIrPackage, PrimitiveType.FLOAT)
private val _doubleArray by createPrimitiveArrayClass(kotlinIrPackage, PrimitiveType.DOUBLE)
override val booleanArray: IrClassSymbol get() = _booleanArray.klass
override val charArray: IrClassSymbol get() = _charArray.klass
override val byteArray: IrClassSymbol get() = _byteArray.klass
override val shortArray: IrClassSymbol get() = _shortArray.klass
override val intArray: IrClassSymbol get() = _intArray.klass
override val longArray: IrClassSymbol get() = _longArray.klass
override val floatArray: IrClassSymbol get() = _floatArray.klass
override val doubleArray: IrClassSymbol get() = _doubleArray.klass
override val primitiveArraysToPrimitiveTypes: Map by lazy {
mapOf(
booleanArray to PrimitiveType.BOOLEAN,
charArray to PrimitiveType.CHAR,
byteArray to PrimitiveType.BYTE,
shortArray to PrimitiveType.SHORT,
intArray to PrimitiveType.INT,
longArray to PrimitiveType.LONG,
floatArray to PrimitiveType.FLOAT,
doubleArray to PrimitiveType.DOUBLE
)
}
override val primitiveTypesToPrimitiveArrays get() = primitiveArraysToPrimitiveTypes.map { (k, v) -> v to k }.toMap()
override val primitiveArrayElementTypes get() = primitiveArraysToPrimitiveTypes.mapValues { primitiveTypeToIrType[it.value] }
override val primitiveArrayForType get() = primitiveArrayElementTypes.asSequence().associate { it.value to it.key }
private val _ieee754equalsFunByOperandType = mutableMapOf()
override val ieee754equalsFunByOperandType: MutableMap
get() = _ieee754equalsFunByOperandType
override lateinit var eqeqeqSymbol: IrSimpleFunctionSymbol private set
override lateinit var eqeqSymbol: IrSimpleFunctionSymbol private set
override lateinit var throwCceSymbol: IrSimpleFunctionSymbol private set
override lateinit var throwIseSymbol: IrSimpleFunctionSymbol private set
override lateinit var andandSymbol: IrSimpleFunctionSymbol private set
override lateinit var ororSymbol: IrSimpleFunctionSymbol private set
override lateinit var noWhenBranchMatchedExceptionSymbol: IrSimpleFunctionSymbol private set
override lateinit var illegalArgumentExceptionSymbol: IrSimpleFunctionSymbol private set
override lateinit var dataClassArrayMemberHashCodeSymbol: IrSimpleFunctionSymbol private set
override lateinit var dataClassArrayMemberToStringSymbol: IrSimpleFunctionSymbol private set
override lateinit var checkNotNullSymbol: IrSimpleFunctionSymbol private set
override val arrayOfNulls: IrSimpleFunctionSymbol by lazy {
findFunctions(kotlinPackage, Name.identifier("arrayOfNulls")).first {
it.owner.dispatchReceiverParameter == null && it.owner.valueParameters.size == 1 &&
it.owner.valueParameters[0].type == intType
}
}
override val linkageErrorSymbol: IrSimpleFunctionSymbol
get() = TODO("Not yet implemented")
override lateinit var lessFunByOperandType: Map private set
override lateinit var lessOrEqualFunByOperandType: Map private set
override lateinit var greaterOrEqualFunByOperandType: Map private set
override lateinit var greaterFunByOperandType: Map private set
init {
with(this.operatorsPackageFragment) {
fun addBuiltinOperatorSymbol(
name: String,
returnType: IrType,
vararg valueParameterTypes: Pair,
isIntrinsicConst: Boolean = false,
builder: IrSimpleFunction.() -> Unit = {}
) =
createFunction(name, returnType, valueParameterTypes, origin = BUILTIN_OPERATOR, isIntrinsicConst = isIntrinsicConst).also {
declarations.add(it)
it.builder()
}.also {
it.parent = operatorsPackageFragment
components.symbolTable.declareSimpleFunctionWithSignature(irSignatureBuilder.computeSignature(it), it.symbol)
}.symbol
primitiveFloatingPointIrTypes.forEach { fpType ->
_ieee754equalsFunByOperandType[fpType.classifierOrFail] = addBuiltinOperatorSymbol(
BuiltInOperatorNames.IEEE754_EQUALS,
booleanType,
"arg0" to fpType.makeNullable(),
"arg1" to fpType.makeNullable(),
isIntrinsicConst = true
)
}
eqeqeqSymbol =
addBuiltinOperatorSymbol(BuiltInOperatorNames.EQEQEQ, booleanType, "" to anyNType, "" to anyNType)
eqeqSymbol =
addBuiltinOperatorSymbol(BuiltInOperatorNames.EQEQ, booleanType, "" to anyNType, "" to anyNType, isIntrinsicConst = true)
throwCceSymbol = addBuiltinOperatorSymbol(BuiltInOperatorNames.THROW_CCE, nothingType)
throwIseSymbol = addBuiltinOperatorSymbol(BuiltInOperatorNames.THROW_ISE, nothingType)
andandSymbol =
addBuiltinOperatorSymbol(BuiltInOperatorNames.ANDAND, booleanType, "" to booleanType, "" to booleanType, isIntrinsicConst = true)
ororSymbol =
addBuiltinOperatorSymbol(BuiltInOperatorNames.OROR, booleanType, "" to booleanType, "" to booleanType, isIntrinsicConst = true)
noWhenBranchMatchedExceptionSymbol =
addBuiltinOperatorSymbol(BuiltInOperatorNames.NO_WHEN_BRANCH_MATCHED_EXCEPTION, nothingType)
illegalArgumentExceptionSymbol =
addBuiltinOperatorSymbol(BuiltInOperatorNames.ILLEGAL_ARGUMENT_EXCEPTION, nothingType, "" to stringType)
dataClassArrayMemberHashCodeSymbol = addBuiltinOperatorSymbol("dataClassArrayMemberHashCode", intType, "" to anyType)
dataClassArrayMemberToStringSymbol = addBuiltinOperatorSymbol("dataClassArrayMemberToString", stringType, "" to anyNType)
checkNotNullSymbol = run {
val typeParameter: IrTypeParameter = irFactory.createTypeParameter(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, BUILTIN_OPERATOR, IrTypeParameterSymbolImpl(), Name.identifier("T0"), 0, true,
Variance.INVARIANT
).apply {
superTypes = listOf(anyType)
}
createFunction(
"CHECK_NOT_NULL",
IrSimpleTypeImpl(typeParameter.symbol, SimpleTypeNullability.DEFINITELY_NOT_NULL, emptyList(), emptyList()),
arrayOf("" to IrSimpleTypeImpl(typeParameter.symbol, hasQuestionMark = true, emptyList(), emptyList())),
origin = BUILTIN_OPERATOR
).also {
it.typeParameters = listOf(typeParameter)
typeParameter.parent = it
declarations.add(it)
it.parent = operatorsPackageFragment
components.symbolTable.declareSimpleFunctionWithSignature(irSignatureBuilder.computeSignature(it), it.symbol)
}.symbol
}
fun List.defineComparisonOperatorForEachIrType(name: String) =
associate { it.classifierOrFail to addBuiltinOperatorSymbol(name, booleanType, "" to it, "" to it, isIntrinsicConst = true) }
lessFunByOperandType = primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(BuiltInOperatorNames.LESS)
lessOrEqualFunByOperandType =
primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(BuiltInOperatorNames.LESS_OR_EQUAL)
greaterOrEqualFunByOperandType =
primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(BuiltInOperatorNames.GREATER_OR_EQUAL)
greaterFunByOperandType = primitiveIrTypesWithComparisons.defineComparisonOperatorForEachIrType(BuiltInOperatorNames.GREATER)
}
}
override val unsignedTypesToUnsignedArrays: Map by lazy {
UnsignedType.values().mapNotNull { unsignedType ->
val array = referenceClassByClassId(unsignedType.arrayClassId)
if (array == null) null else unsignedType to array
}.toMap()
}
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")
}
private val enum by loadClass(StandardClassIds.Enum)
override val enumClass: IrClassSymbol get() = enum.klass
override val intPlusSymbol: IrSimpleFunctionSymbol
get() = intClass.functions.single {
it.owner.name == OperatorNameConventions.PLUS && it.owner.valueParameters[0].type == intType
}
override val intTimesSymbol: IrSimpleFunctionSymbol
get() = intClass.functions.single {
it.owner.name == OperatorNameConventions.TIMES && it.owner.valueParameters[0].type == intType
}
override val intXorSymbol: IrSimpleFunctionSymbol
get() = intClass.functions.single {
it.owner.name == OperatorNameConventions.XOR && it.owner.valueParameters[0].type == intType
}
override val extensionToString: IrSimpleFunctionSymbol by lazy {
findFunctions(kotlinPackage, OperatorNameConventions.TO_STRING).single { function ->
function.owner.extensionReceiverParameter?.let { receiver -> receiver.type == anyNType } ?: false
}
}
override val memberToString: IrSimpleFunctionSymbol by lazy {
findBuiltInClassMemberFunctions(anyClass, OperatorNameConventions.TO_STRING).single { function ->
function.owner.valueParameters.isEmpty()
}
}
override val extensionStringPlus: IrSimpleFunctionSymbol by lazy {
findFunctions(kotlinPackage, OperatorNameConventions.PLUS).single { function ->
val isStringExtension =
function.owner.extensionReceiverParameter?.let { receiver -> receiver.type == stringType.makeNullable() }
?: false
isStringExtension && function.owner.valueParameters.size == 1 && function.owner.valueParameters[0].type == anyNType
}
}
override val memberStringPlus: IrSimpleFunctionSymbol by lazy {
findBuiltInClassMemberFunctions(stringClass, OperatorNameConventions.PLUS).single { function ->
function.owner.valueParameters.size == 1 && function.owner.valueParameters[0].type == anyNType
}
}
private class KotlinPackageFuns(
val arrayOf: IrSimpleFunctionSymbol,
)
private val kotlinBuiltinFunctions by lazy {
fun IrClassSymbol.addPackageFun(
name: String,
returnType: IrType,
vararg argumentTypes: Pair,
builder: IrSimpleFunction.() -> Unit
) =
owner.createFunction(name, returnType, argumentTypes).also {
it.builder()
this.owner.declarations.add(it)
it.parent = kotlinIrPackage
components.symbolTable.declareSimpleFunctionWithSignature(irSignatureBuilder.computeSignature(it), it.symbol)
}.symbol
val kotlinKt = kotlinIrPackage.createClass(kotlinPackage.child(Name.identifier("KotlinKt")))
KotlinPackageFuns(
arrayOf = kotlinKt.addPackageFun("arrayOf", arrayClass.defaultType) arrayOf@{
addTypeParameter("T", anyNType)
addValueParameter {
this.name = Name.identifier("elements")
this.type = arrayClass.defaultType
this.varargElementType = typeParameters[0].defaultType
this.origin = [email protected]
}
}
)
}
override val arrayOf: IrSimpleFunctionSymbol get() = kotlinBuiltinFunctions.arrayOf
private fun getFunctionsByKey(
name: Name,
vararg packageNameSegments: String,
makeKey: (IrSimpleFunctionSymbol) -> T?
): Map {
val result = mutableMapOf()
for (fn in findFunctions(name, *packageNameSegments)) {
makeKey(fn)?.let { key ->
result[key] = fn
}
}
return result
}
override fun getNonBuiltInFunctionsByExtensionReceiver(
name: Name, vararg packageNameSegments: String
): Map =
getFunctionsByKey(name, *packageNameSegments) { fn ->
fn.owner.extensionReceiverParameter?.type?.classifierOrNull
}
override fun getNonBuiltinFunctionsByReturnType(
name: Name, vararg packageNameSegments: String
): Map =
getFunctionsByKey(name, *packageNameSegments) { fn ->
fn.owner.returnType.classOrNull
}
private val functionNMap = mutableMapOf()
private val kFunctionNMap = mutableMapOf()
private val suspendFunctionNMap = mutableMapOf()
private val kSuspendFunctionNMap = mutableMapOf()
override fun functionN(arity: Int): IrClass = functionNMap.getOrPut(arity) {
referenceClassByClassId(StandardClassIds.FunctionN(arity))!!.owner
}
override fun kFunctionN(arity: Int): IrClass = kFunctionNMap.getOrPut(arity) {
referenceClassByClassId(StandardClassIds.KFunctionN(arity))!!.owner
}
override fun suspendFunctionN(arity: Int): IrClass = suspendFunctionNMap.getOrPut(arity) {
referenceClassByClassId(StandardClassIds.SuspendFunctionN(arity))!!.owner
}
override fun kSuspendFunctionN(arity: Int): IrClass = kSuspendFunctionNMap.getOrPut(arity) {
referenceClassByClassId(StandardClassIds.KSuspendFunctionN(arity))!!.owner
}
override fun findFunctions(name: Name, vararg packageNameSegments: String): Iterable =
findFunctions(FqName.fromSegments(packageNameSegments.asList()), name)
override fun findFunctions(name: Name, packageFqName: FqName): Iterable =
findFunctions(packageFqName, name)
override fun findClass(name: Name, vararg packageNameSegments: String): IrClassSymbol? =
referenceClassByFqname(FqName.fromSegments(packageNameSegments.asList()), name)
override fun findClass(name: Name, packageFqName: FqName): IrClassSymbol? =
referenceClassByFqname(packageFqName, name)
private fun referenceClassByFqname(packageName: FqName, identifier: Name) =
referenceClassByClassId(ClassId(packageName, identifier))
private val builtInClasses by lazy {
setOf(anyClass)
}
override fun findBuiltInClassMemberFunctions(builtInClass: IrClassSymbol, name: Name): Iterable {
require(builtInClass in builtInClasses)
return builtInClass.functions.filter { it.owner.name == name }.asIterable()
}
override fun getBinaryOperator(name: Name, lhsType: IrType, rhsType: IrType): IrSimpleFunctionSymbol {
val definingClass = lhsType.getMaybeBuiltinClass() ?: error("Defining class not found: $lhsType")
return definingClass.functions.single { function ->
function.name == name && function.valueParameters.size == 1 && function.valueParameters[0].type == rhsType
}.symbol
}
override fun getUnaryOperator(name: Name, receiverType: IrType): IrSimpleFunctionSymbol {
val definingClass = receiverType.getMaybeBuiltinClass() ?: error("Defining class not found: $receiverType")
return definingClass.functions.single { function ->
function.name == name && function.valueParameters.isEmpty()
}.symbol
}
// ---------------
class BuiltInClassValue(
private val generatedClass: IrClassSymbol,
private var lazyContents: (IrClass.() -> Unit)?
) {
fun ensureLazyContentsCreated() {
if (lazyContents != null) synchronized(this) {
lazyContents?.invoke(generatedClass.owner)
lazyContents = null
}
}
val klass: IrClassSymbol
get() {
ensureLazyContentsCreated()
return generatedClass
}
val type: IrType get() = generatedClass.defaultType
}
private inner class BuiltInsClass(
private var generator: (() -> Pair)?,
private var lazyContents: (IrClass.() -> Unit)? = null
) {
private var value: BuiltInClassValue? = null
operator fun getValue(thisRef: Any?, property: KProperty<*>): BuiltInClassValue = value ?: run {
synchronized(this) {
if (value == null) {
val (isLoaded, symbol) = generator!!()
value = BuiltInClassValue(symbol, if (isLoaded) null else lazyContents)
generator = null
lazyContents = null
}
}
value!!
}
}
private fun loadClass(classId: ClassId) = BuiltInsClass({ true to referenceClassByClassId(classId)!! })
private fun createClass(
parent: IrDeclarationParent,
signature: IdSignature.CommonSignature,
build: IrClassBuilder.() -> Unit = {},
lazyContents: (IrClass.() -> Unit) = { finalizeClassDefinition() }
) = BuiltInsClass(
generator = {
val loaded = if (tryLoadBuiltInsFirst) {
referenceClassByClassId(ClassId(parent.kotlinFqName, Name.identifier(signature.shortName)))
} else null
(loaded != null) to (loaded ?: components.symbolTable.declareClass(
signature,
{ IrClassPublicSymbolImpl(signature) },
{ symbol ->
IrClassBuilder().run {
name = Name.identifier(signature.shortName)
origin = IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB
build()
irFactory.createClass(
startOffset, endOffset, origin, symbol, name, kind, visibility, modality,
isCompanion, isInner, isData, isExternal, isValue, isExpect, isFun
)
}.also {
it.parent = parent
it.createImplicitParameterDeclarationWithWrappedDescriptor()
components.symbolTable.declareClassWithSignature(irSignatureBuilder.computeSignature(it), it.symbol)
}
}
).symbol)
},
lazyContents = lazyContents
)
private fun referenceClassByFqname(topLevelFqName: FqName) =
referenceClassByClassId(ClassId.topLevel(topLevelFqName))
private fun referenceClassByClassId(classId: ClassId): IrClassSymbol? {
val firSymbol = components.session.symbolProvider.getClassLikeSymbolByClassId(classId) ?: return null
val firClassSymbol = firSymbol as? FirClassSymbol ?: return null
return components.classifierStorage.getIrClassSymbol(firClassSymbol)
}
private fun IrType.getMaybeBuiltinClass(): IrClass? {
val lhsClassFqName = classFqName!!
return baseIrTypes.find { it.classFqName == lhsClassFqName }?.getClass()
?: referenceClassByFqname(lhsClassFqName)?.owner
}
private fun createPackage(fqName: FqName): IrExternalPackageFragment =
IrExternalPackageFragmentImpl.createEmptyExternalPackageFragment(moduleDescriptor, fqName)
private fun IrDeclarationParent.createClass(
fqName: FqName,
vararg supertypes: IrType,
classKind: ClassKind = ClassKind.CLASS,
classModality: Modality = Modality.OPEN,
builderBlock: IrClassBuilder.() -> Unit = {},
block: IrClass.() -> Unit = {}
): IrClassSymbol {
val signature = getPublicSignature(fqName.parent(), fqName.shortName().asString())
return this.createClass(
signature, *supertypes,
classKind = classKind, classModality = classModality, builderBlock = builderBlock, block = block
)
}
private fun IrDeclarationParent.createClass(
signature: IdSignature.CommonSignature,
vararg supertypes: IrType,
classKind: ClassKind = ClassKind.CLASS,
classModality: Modality = Modality.OPEN,
builderBlock: IrClassBuilder.() -> Unit = {},
block: IrClass.() -> Unit = {}
): IrClassSymbol = components.symbolTable.declareClass(
signature,
{ IrClassPublicSymbolImpl(signature) },
{ symbol ->
IrClassBuilder().run {
name = Name.identifier(signature.shortName)
kind = classKind
modality = classModality
origin = IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB
builderBlock()
irFactory.createClass(
startOffset, endOffset, origin, symbol, name, kind, visibility, modality,
isCompanion, isInner, isData, isExternal, isValue, isExpect, isFun
)
}.also {
it.parent = this
it.createImplicitParameterDeclarationWithWrappedDescriptor()
it.block()
it.superTypes = supertypes.asList()
}
}
).symbol
private fun IrClass.createConstructor(
origin: IrDeclarationOrigin = object : IrDeclarationOriginImpl("BUILTIN_CLASS_CONSTRUCTOR") {},
isPrimary: Boolean = true,
visibility: DescriptorVisibility = DescriptorVisibilities.PUBLIC,
build: IrConstructor.() -> Unit = {}
): IrConstructorSymbol {
val name = SpecialNames.INIT
val ctor = irFactory.createConstructor(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, IrConstructorSymbolImpl(), name, visibility, defaultType,
isInline = false, isExternal = false, isPrimary = isPrimary, isExpect = false
)
ctor.parent = this
ctor.build()
declarations.add(ctor)
components.symbolTable.declareConstructorWithSignature(
irSignatureBuilder.computeSignature(ctor), ctor.symbol
)
return ctor.symbol
}
private fun IrClass.forEachSuperClass(body: IrClass.() -> Unit) {
for (st in superTypes) {
st.getClass()?.let {
it.body()
it.forEachSuperClass(body)
}
}
}
private fun IrClass.createMemberFunction(
name: String, returnType: IrType, vararg valueParameterTypes: Pair,
origin: IrDeclarationOrigin = object : IrDeclarationOriginImpl("BUILTIN_CLASS_METHOD") {},
modality: Modality = Modality.FINAL,
isOperator: Boolean = false,
isIntrinsicConst: Boolean = true,
build: IrFunctionBuilder.() -> Unit = {}
) = parent.createFunction(
name, returnType, valueParameterTypes, origin, modality, isOperator, isIntrinsicConst, build
).also { fn ->
fn.addDispatchReceiver { type = [email protected] }
declarations.add(fn)
fn.parent = this@createMemberFunction
if (isIntrinsicConst) {
fn.annotations += intrinsicConstAnnotation
}
// very simple and fragile logic, but works for all current usages
// TODO: replace with correct logic or explicit specification if cases become more complex
forEachSuperClass {
functions.find {
it.name == fn.name && it.typeParameters.count() == fn.typeParameters.count() &&
it.valueParameters.count() == fn.valueParameters.count() &&
it.valueParameters.zip(fn.valueParameters).all { (l, r) -> l.type == r.type }
}?.let {
fn.overriddenSymbols += it.symbol
}
}
components.symbolTable.declareSimpleFunctionWithSignature(
irSignatureBuilder.computeSignature(fn), fn.symbol
)
}
private fun IrClass.createMemberFunction(
name: Name, returnType: IrType, vararg valueParameterTypes: Pair,
origin: IrDeclarationOrigin = object : IrDeclarationOriginImpl("BUILTIN_CLASS_METHOD") {},
modality: Modality = Modality.FINAL,
isOperator: Boolean = false,
isIntrinsicConst: Boolean = true,
build: IrFunctionBuilder.() -> Unit = {}
) =
createMemberFunction(
name.asString(), returnType, *valueParameterTypes,
origin = origin, modality = modality, isOperator = isOperator, isIntrinsicConst = isIntrinsicConst, build = build
)
private fun IrClass.configureSuperTypes(vararg superTypes: BuiltInClassValue, defaultAny: Boolean = true) {
for (superType in superTypes) {
superType.ensureLazyContentsCreated()
}
if (!defaultAny || superTypes.contains(any) || this.superTypes.contains(anyType)) {
this.superTypes += superTypes.map { it.type }
} else {
any.ensureLazyContentsCreated()
this.superTypes += superTypes.map { it.type } + anyType
}
}
private fun IrClass.finalizeClassDefinition() {
addFakeOverrides(IrTypeSystemContextImpl(this@IrBuiltInsOverFir))
}
private fun IrDeclarationParent.createFunction(
name: String,
returnType: IrType,
valueParameterTypes: Array>,
origin: IrDeclarationOrigin = IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB,
modality: Modality = Modality.FINAL,
isOperator: Boolean = false,
isIntrinsicConst: Boolean = false,
build: IrFunctionBuilder.() -> Unit = {}
) = irFactory.buildFun {
this.name = Name.identifier(name)
this.returnType = returnType
this.origin = origin
this.modality = modality
this.isOperator = isOperator
build()
}.also { fn ->
valueParameterTypes.forEachIndexed { index, (pName, irType) ->
fn.addValueParameter(Name.identifier(pName.ifBlank { "arg$index" }), irType, origin)
}
if (isIntrinsicConst) {
fn.annotations += intrinsicConstAnnotation
}
fn.parent = this@createFunction
}
private fun IrClass.addArrayMembers(elementType: IrType) {
addConstructor {
origin = object : IrDeclarationOriginImpl("BUILTIN_CLASS_CONSTRUCTOR") {}
returnType = defaultType
isPrimary = true
}.also {
it.addValueParameter("size", intType, object : IrDeclarationOriginImpl("BUILTIN_CLASS_CONSTRUCTOR") {})
}
createMemberFunction(OperatorNameConventions.GET, elementType, "index" to intType, isOperator = true, isIntrinsicConst = false)
createMemberFunction(OperatorNameConventions.SET, unitType, "index" to intType, "value" to elementType, isOperator = true, isIntrinsicConst = false)
createProperty("size", intType)
}
private fun IrClass.createProperty(
propertyName: String, returnType: IrType,
modality: Modality = Modality.FINAL,
isConst: Boolean = false, withGetter: Boolean = true, withField: Boolean = false, isIntrinsicConst: Boolean = false,
fieldInit: IrExpression? = null,
builder: IrProperty.() -> Unit = {}
) {
addProperty {
this.name = Name.identifier(propertyName)
this.isConst = isConst
this.modality = modality
}.also { property ->
// very simple and fragile logic, but works for all current usages
// TODO: replace with correct logic or explicit specification if cases become more complex
forEachSuperClass {
properties.find { it.name == property.name }?.let {
property.overriddenSymbols += it.symbol
}
}
if (isIntrinsicConst) {
property.annotations += intrinsicConstAnnotation
}
if (withGetter) {
property.addGetter {
this.returnType = returnType
this.modality = modality
this.isOperator = false
}.also { getter ->
getter.addDispatchReceiver { type = [email protected] }
getter.overriddenSymbols = property.overriddenSymbols.mapNotNull { it.owner.getter?.symbol }
}
}
if (withField || fieldInit != null) {
property.addBackingField {
this.type = returnType
this.isFinal = isConst
}.also {
if (fieldInit != null) {
it.initializer = irFactory.createExpressionBody(0, 0) {
expression = fieldInit
}
}
}
}
property.builder()
components.symbolTable.declarePropertyWithSignature(
irSignatureBuilder.computeSignature(property), property.symbol
)
property.getter?.let {
components.symbolTable.declareSimpleFunctionWithSignature(
irSignatureBuilder.computeSignature(it), it.symbol
)
}
property.backingField?.let {
components.symbolTable.declareFieldWithSignature(
irSignatureBuilder.computeSignature(it), it.symbol
)
}
}
}
private class NumericConstantsExpressions(
val min: IrConst,
val max: IrConst,
val sizeBytes: IrConst,
val sizeBits: IrConst
)
private fun getNumericConstantsExpressions(type: IrType): NumericConstantsExpressions<*> {
val so = UNDEFINED_OFFSET
val eo = UNDEFINED_OFFSET
return when (type.getPrimitiveType()) {
PrimitiveType.CHAR -> NumericConstantsExpressions(
IrConstImpl.char(so, eo, type, Char.MIN_VALUE), IrConstImpl.char(so, eo, type, Char.MAX_VALUE),
IrConstImpl.int(so, eo, intType, Char.SIZE_BYTES), IrConstImpl.int(so, eo, intType, Char.SIZE_BITS)
)
PrimitiveType.BYTE -> NumericConstantsExpressions(
IrConstImpl.byte(so, eo, type, Byte.MIN_VALUE), IrConstImpl.byte(so, eo, type, Byte.MAX_VALUE),
IrConstImpl.int(so, eo, intType, Byte.SIZE_BYTES), IrConstImpl.int(so, eo, intType, Byte.SIZE_BITS)
)
PrimitiveType.SHORT -> NumericConstantsExpressions(
IrConstImpl.short(so, eo, type, Short.MIN_VALUE), IrConstImpl.short(so, eo, type, Short.MAX_VALUE),
IrConstImpl.int(so, eo, intType, Short.SIZE_BYTES), IrConstImpl.int(so, eo, intType, Short.SIZE_BITS)
)
PrimitiveType.INT -> NumericConstantsExpressions(
IrConstImpl.int(so, eo, type, Int.MIN_VALUE), IrConstImpl.int(so, eo, type, Int.MAX_VALUE),
IrConstImpl.int(so, eo, intType, Int.SIZE_BYTES), IrConstImpl.int(so, eo, intType, Int.SIZE_BITS)
)
PrimitiveType.LONG -> NumericConstantsExpressions(
IrConstImpl.long(so, eo, type, Long.MIN_VALUE), IrConstImpl.long(so, eo, type, Long.MAX_VALUE),
IrConstImpl.int(so, eo, intType, Long.SIZE_BYTES), IrConstImpl.int(so, eo, intType, Long.SIZE_BITS)
)
PrimitiveType.FLOAT -> NumericConstantsExpressions(
IrConstImpl.float(so, eo, type, Float.MIN_VALUE), IrConstImpl.float(so, eo, type, Float.MAX_VALUE),
IrConstImpl.int(so, eo, intType, Float.SIZE_BYTES), IrConstImpl.int(so, eo, intType, Float.SIZE_BITS)
)
PrimitiveType.DOUBLE -> NumericConstantsExpressions(
IrConstImpl.double(so, eo, type, Double.MIN_VALUE), IrConstImpl.double(so, eo, type, Double.MAX_VALUE),
IrConstImpl.int(so, eo, intType, Double.SIZE_BYTES), IrConstImpl.int(so, eo, intType, Double.SIZE_BITS)
)
else -> error("unsupported type")
}
}
private fun IrPackageFragment.createNumberClass(
signature: IdSignature.CommonSignature,
lazyContents: (IrClass.() -> Unit)? = null
) =
createClass(this, signature) {
configureSuperTypes(number)
val thisType = defaultType
createStandardNumericAndCharMembers(thisType)
createStandardNumericMembers(thisType)
if (thisType in primitiveIntegralIrTypes) {
createStandardRangeMembers(thisType)
}
if (thisType == intType || thisType == longType) {
createStandardBitwiseOps(thisType)
}
lazyContents?.invoke(this)
createIntrinsicConstOfToStringAndEquals()
finalizeClassDefinition()
}
private fun createPrimitiveArrayClass(
parent: IrDeclarationParent,
primitiveType: PrimitiveType,
lazyContents: (IrClass.() -> Unit)? = null
) =
createClass(
parent,
getPublicSignature(parent.kotlinFqName, primitiveType.arrayTypeName.asString()),
build = { modality = Modality.FINAL }
) {
configureSuperTypes()
addArrayMembers(primitiveTypeToIrType[primitiveType]!!)
lazyContents?.invoke(this)
finalizeClassDefinition()
}
private fun IrClass.createCompanionObject(block: IrClass.() -> Unit = {}): IrClassSymbol =
this.createClass(
kotlinFqName.child(Name.identifier("Companion")), classKind = ClassKind.OBJECT, builderBlock = {
isCompanion = true
}
).also {
it.owner.block()
declarations.add(it.owner)
}
private fun IrClass.createStandardBitwiseOps(thisType: IrType) {
for (op in arrayOf(OperatorNameConventions.AND, OperatorNameConventions.OR, OperatorNameConventions.XOR)) {
createMemberFunction(op, thisType, "other" to thisType, isOperator = true)
}
for (op in arrayOf(OperatorNameConventions.SHL, OperatorNameConventions.SHR, OperatorNameConventions.USHR)) {
createMemberFunction(op, thisType, "bitCount" to intType, isOperator = true)
}
createMemberFunction(OperatorNameConventions.INV, thisType, isOperator = true)
}
private fun IrClass.createStandardRangeMembers(thisType: IrType) {
for (argType in primitiveIntegralIrTypes) {
createMemberFunction(
OperatorNameConventions.RANGE_TO,
if (thisType == longType || argType == longType) longRangeType else intRangeType,
"other" to argType, isOperator = true, isIntrinsicConst = false
)
}
}
private fun IrClass.createStandardNumericMembers(thisType: IrType) {
for (argument in primitiveNumericIrTypes) {
createMemberFunction(
OperatorNameConventions.COMPARE_TO, intType, "other" to argument,
modality = if (argument == thisType) Modality.OPEN else Modality.FINAL,
isOperator = true
)
val targetArithmeticReturnType = getPrimitiveArithmeticOperatorResultType(thisType, argument)
for (op in arrayOf(
OperatorNameConventions.PLUS,
OperatorNameConventions.MINUS,
OperatorNameConventions.TIMES,
OperatorNameConventions.DIV,
OperatorNameConventions.REM
)) {
createMemberFunction(op, targetArithmeticReturnType, "other" to argument, isOperator = true)
}
}
val arithmeticReturnType = getPrimitiveArithmeticOperatorResultType(thisType, thisType)
createMemberFunction(OperatorNameConventions.UNARY_PLUS, arithmeticReturnType, isOperator = true)
createMemberFunction(OperatorNameConventions.UNARY_MINUS, arithmeticReturnType, isOperator = true)
}
private fun IrClass.createStandardNumericAndCharMembers(thisType: IrType) {
createCompanionObject {
val constExprs = getNumericConstantsExpressions(thisType)
createProperty("MIN_VALUE", thisType, isConst = true, withGetter = false, fieldInit = constExprs.min)
createProperty("MAX_VALUE", thisType, isConst = true, withGetter = false, fieldInit = constExprs.max)
createProperty("SIZE_BYTES", intType, isConst = true, withGetter = false, fieldInit = constExprs.sizeBytes)
createProperty("SIZE_BITS", intType, isConst = true, withGetter = false, fieldInit = constExprs.sizeBits)
}
for (targetPrimitive in primitiveIrTypesWithComparisons) {
createMemberFunction("to${targetPrimitive.classFqName!!.shortName().asString()}", targetPrimitive, modality = Modality.OPEN)
}
createMemberFunction(OperatorNameConventions.INC, thisType, isOperator = true, isIntrinsicConst = false)
createMemberFunction(OperatorNameConventions.DEC, thisType, isOperator = true, isIntrinsicConst = false)
}
private fun IrClass.createIntrinsicConstOfToStringAndEquals() {
createMemberFunction(OperatorNameConventions.TO_STRING, stringType)
createMemberFunction(
OperatorNameConventions.EQUALS, booleanType, "other" to anyNType,
modality = Modality.OPEN, isOperator = true
)
}
private fun findFunctions(packageName: FqName, name: Name): List =
components.session.symbolProvider.getTopLevelFunctionSymbols(packageName, name).mapNotNull { firOpSymbol ->
components.declarationStorage.getIrFunctionSymbol(firOpSymbol) as? IrSimpleFunctionSymbol
}
}