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.backend.jvm.intrinsics.IrIntrinsicMethods.kt Maven / Gradle / Ivy
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.JvmSymbols
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrPackageFragment
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.isFileClass
import org.jetbrains.kotlin.lexer.KtSingleValueToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.types.expressions.OperatorConventions
import org.jetbrains.org.objectweb.asm.Opcodes.*
import org.jetbrains.org.objectweb.asm.Type
class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
private val kotlinJvm = FqName("kotlin.jvm")
private val kotlinJvmInternalUnsafe = FqName("kotlin.jvm.internal.unsafe")
private val intrinsicsMap = (
listOf(
Key(kotlinJvm, FqName("T"), "", emptyList()) to JavaClassProperty,
Key(kotlinJvm, StandardNames.FqNames.kClass.toSafe(), "", emptyList()) to GetJavaObjectType,
Key(kotlinJvm, StandardNames.FqNames.kClass.toSafe(), "", emptyList()) to GetJavaPrimitiveType,
Key(
kotlinJvm,
StandardNames.FqNames.kClass.toSafe(),
"",
emptyList()
) to KClassJavaProperty,
Key(
kotlinJvmInternalUnsafe,
null,
"access\$monitorEnter",
listOf(StandardNames.FqNames.any.toSafe())
) to MonitorInstruction.MONITOR_ENTER,
Key(
kotlinJvmInternalUnsafe,
null,
"access\$monitorExit",
listOf(StandardNames.FqNames.any.toSafe())
) to MonitorInstruction.MONITOR_EXIT,
Key(
kotlinJvm,
StandardNames.FqNames.array.toSafe(),
"isArrayOf",
emptyList()
) to IsArrayOf,
Key(
StandardNames.BUILT_INS_PACKAGE_FQ_NAME,
null,
"arrayOfNulls",
listOf(StandardNames.FqNames._int.toSafe())
) to NewArray,
Key(
StandardNames.FqNames.cloneable.toSafe(),
null,
"clone",
emptyList()
) to Clone,
Key(
StandardNames.BUILT_INS_PACKAGE_FQ_NAME,
null,
"enumValues",
listOf()
) to EnumValues,
Key(
StandardNames.BUILT_INS_PACKAGE_FQ_NAME,
null,
"enumValueOf",
listOf(StandardNames.FqNames.string.toSafe())
) to EnumValueOf,
Key(
StandardNames.BUILT_INS_PACKAGE_FQ_NAME,
StandardNames.FqNames.string.toSafe(),
"plus",
listOf(StandardNames.FqNames.any.toSafe())
) to StringPlus,
irBuiltIns.eqeqSymbol.toKey()!! to Equals(KtTokens.EQEQ),
irBuiltIns.eqeqeqSymbol.toKey()!! to Equals(KtTokens.EQEQEQ),
irBuiltIns.ieee754equalsFunByOperandType[irBuiltIns.floatClass]!!.toKey()!! to Ieee754Equals(Type.FLOAT_TYPE),
irBuiltIns.ieee754equalsFunByOperandType[irBuiltIns.doubleClass]!!.toKey()!! to Ieee754Equals(Type.DOUBLE_TYPE),
irBuiltIns.booleanNotSymbol.toKey()!! to Not,
irBuiltIns.noWhenBranchMatchedExceptionSymbol.toKey()!! to IrNoWhenBranchMatchedException,
irBuiltIns.illegalArgumentExceptionSymbol.toKey()!! to IrIllegalArgumentException,
irBuiltIns.andandSymbol.toKey()!! to AndAnd,
irBuiltIns.ororSymbol.toKey()!! to OrOr,
irBuiltIns.dataClassArrayMemberHashCodeSymbol.toKey()!! to IrDataClassArrayMemberHashCode,
irBuiltIns.dataClassArrayMemberToStringSymbol.toKey()!! to IrDataClassArrayMemberToString,
symbols.unsafeCoerceIntrinsic.toKey()!! to UnsafeCoerce,
symbols.signatureStringIntrinsic.toKey()!! to SignatureString,
symbols.reassignParameterIntrinsic.toKey()!! to ReassignParameter,
symbols.throwNullPointerException.toKey()!! to ThrowException(Type.getObjectType("java/lang/NullPointerException")),
symbols.throwTypeCastException.toKey()!! to ThrowException(Type.getObjectType("kotlin/TypeCastException")),
symbols.throwUnsupportedOperationException.toKey()!! to ThrowException(Type.getObjectType("java/lang/UnsupportedOperationException")),
symbols.throwKotlinNothingValueException.toKey()!! to ThrowKotlinNothingValueException,
) +
numberConversionMethods() +
unaryFunForPrimitives("plus", UnaryPlus) +
unaryFunForPrimitives("unaryPlus", UnaryPlus) +
unaryFunForPrimitives("minus", UnaryMinus) +
unaryFunForPrimitives("unaryMinus", UnaryMinus) +
unaryFunForPrimitives("inv", Inv) +
unaryFunForPrimitives("inc", INC) +
unaryFunForPrimitives("dec", DEC) +
unaryFunForPrimitives("hashCode", HashCode) +
binaryFunForPrimitives("equals", EXPLICIT_EQUALS, irBuiltIns.anyClass) +
binaryFunForPrimitivesAcrossPrimitives("rangeTo", RangeTo) +
binaryOp("plus", IADD) +
binaryOp("minus", ISUB) +
binaryOp("times", IMUL) +
binaryOp("div", IDIV) +
binaryOp("mod", IREM) +
binaryOp("rem", IREM) +
binaryOp("shl", ISHL) +
binaryOp("shr", ISHR) +
binaryOp("ushr", IUSHR) +
binaryOp("and", IAND) +
binaryOp("or", IOR) +
binaryOp("xor", IXOR) +
binaryFunForPrimitivesAcrossPrimitives("compareTo", CompareTo) +
createKeyMapping(Not, irBuiltIns.booleanClass, "not") +
createKeyMapping(StringGetChar, irBuiltIns.stringClass, "get", irBuiltIns.intClass) +
symbols.primitiveIteratorsByType.values.map { iteratorClass ->
createKeyMapping(IteratorNext, iteratorClass, "next")
} +
arrayMethods() +
primitiveComparisonIntrinsics(irBuiltIns.lessFunByOperandType, KtTokens.LT) +
primitiveComparisonIntrinsics(irBuiltIns.lessOrEqualFunByOperandType, KtTokens.LTEQ) +
primitiveComparisonIntrinsics(irBuiltIns.greaterFunByOperandType, KtTokens.GT) +
primitiveComparisonIntrinsics(irBuiltIns.greaterOrEqualFunByOperandType, KtTokens.GTEQ)
).toMap()
private val PrimitiveType.symbol
get() = irBuiltIns.primitiveTypeToIrType[this]!!.classOrNull!!
fun getIntrinsic(symbol: IrFunctionSymbol): IntrinsicMethod? = intrinsicsMap[symbol.toKey()]
private fun unaryFunForPrimitives(name: String, intrinsic: IntrinsicMethod): List> =
PrimitiveType.values().map { type ->
createKeyMapping(intrinsic, type.symbol, name)
}
private fun binaryFunForPrimitivesAcrossPrimitives(name: String, intrinsic: IntrinsicMethod): List> =
PrimitiveType.values().flatMap { parameter ->
binaryFunForPrimitives(name, intrinsic, parameter.symbol)
}
private fun binaryFunForPrimitives(
name: String,
intrinsic: IntrinsicMethod,
parameter: IrClassifierSymbol
): List> =
PrimitiveType.values().map { type ->
createKeyMapping(
intrinsic,
type.symbol,
name,
parameter
)
}
private fun binaryOp(methodName: String, opcode: Int) = binaryFunForPrimitivesAcrossPrimitives(methodName, BinaryOp(opcode))
private fun numberConversionMethods(): List> =
PrimitiveType.NUMBER_TYPES.flatMap { type ->
numberConversionMethods(type.symbol)
} + numberConversionMethods(irBuiltIns.numberClass)
private fun arrayMethods(): List> =
symbols.primitiveArrays.flatMap { (key, value) ->
arrayMethods(
key.symbol,
value
)
} + arrayMethods(symbols.array.owner.typeParameters.single().symbol, symbols.array)
private fun arrayMethods(elementClass: IrClassifierSymbol, arrayClass: IrClassSymbol) =
listOf(
createKeyMapping(ArraySize, arrayClass, ""),
createKeyMapping(NewArray, arrayClass, "", irBuiltIns.intClass),
createKeyMapping(ArraySet, arrayClass, "set", irBuiltIns.intClass, elementClass),
createKeyMapping(ArrayGet, arrayClass, "get", irBuiltIns.intClass),
createKeyMapping(Clone, arrayClass, "clone"),
createKeyMapping(ArrayIterator, arrayClass, "iterator")
)
data class Key(val owner: FqName, val receiverParameterTypeName: FqName?, val name: String, val valueParameterTypeNames: List)
companion object {
internal val INTRINSICS_CLASS_NAME = "kotlin/jvm/internal/Intrinsics"
private val INC = Increment(1)
private val DEC = Increment(-1)
private val EXPLICIT_EQUALS = ExplicitEquals()
private fun IrFunctionSymbol.toKey(): Key? {
val parent = owner.parent
val ownerFqName = when {
parent is IrClass && parent.isFileClass ->
(parent.parent as IrPackageFragment).fqName
parent is IrClass -> parent.fqNameWhenAvailable ?: return null
parent is IrPackageFragment -> parent.fqName
else -> return null
}
return Key(
ownerFqName,
getParameterFqName(owner.extensionReceiverParameter),
owner.name.asString(),
owner.valueParameters.map(::getParameterFqName)
)
}
private fun getParameterFqName(parameter: IrValueParameter?): FqName? =
getParameterFqName(parameter?.type?.classifierOrNull)
private fun getParameterFqName(parameter: IrClassifierSymbol?): FqName? =
parameter?.owner?.let {
when (it) {
is IrClass -> it.fqNameWhenAvailable
is IrTypeParameter -> FqName(it.name.asString())
else -> null
}
}
private fun createKeyMapping(
intrinsic: IntrinsicMethod,
klass: IrClassSymbol,
name: String,
vararg args: IrClassifierSymbol
): Pair =
Key(klass.owner.fqNameWhenAvailable!!, null, name, args.map {
getParameterFqName(it)
}) to intrinsic
private fun numberConversionMethods(numberClass: IrClassSymbol) =
OperatorConventions.NUMBER_CONVERSIONS.map { method ->
createKeyMapping(NumberCast, numberClass, method.asString())
}
private fun primitiveComparisonIntrinsics(
typeToIrFun: Map,
operator: KtSingleValueToken
): List> =
typeToIrFun.map { (type, irFunSymbol) ->
irFunSymbol.toKey()!! to PrimitiveComparison(type.descriptor.defaultType, operator)
}
}
}