JVM_IR: rework IrIntrinsicMethods

This commit is contained in:
Georgy Bronnikov
2019-04-15 01:02:42 +03:00
parent 98d309d03b
commit 9923d956aa
39 changed files with 368 additions and 454 deletions
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.builtins.UnsignedType
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.declarations.IrFunction
@@ -46,6 +47,20 @@ abstract class Symbols<out T : CommonBackendContext>(val context: T, private val
protected fun builtInsPackage(vararg packageNameSegments: String) =
context.builtIns.builtInsModule.getPackage(FqName.fromSegments(listOf(*packageNameSegments))).memberScope
private fun getSimpleFunction(
name: Name,
vararg packageNameSegments: String = arrayOf("kotlin"),
condition: (SimpleFunctionDescriptor) -> Boolean
): IrSimpleFunctionSymbol =
symbolTable.referenceSimpleFunction(
builtInsPackage(*packageNameSegments).getContributedFunctions(name, NoLookupLocation.FROM_BACKEND)
.first(condition)
)
private fun getClass(name: Name, vararg packageNameSegments: String = arrayOf("kotlin")): IrClassSymbol =
symbolTable.referenceClass(
builtInsPackage(*packageNameSegments).getContributedClassifier(name, NoLookupLocation.FROM_BACKEND) as ClassDescriptor
)
/**
* Use this table to reference external dependencies.
@@ -63,21 +78,18 @@ abstract class Symbols<out T : CommonBackendContext>(val context: T, private val
abstract val defaultConstructorMarker: IrClassSymbol
val iterator = symbolTable.referenceClass(
builtInsPackage("kotlin", "collections").getContributedClassifier(
Name.identifier("Iterator"), NoLookupLocation.FROM_BACKEND
) as ClassDescriptor
)
val iterator = getClass(Name.identifier("Iterator"), "kotlin", "collections")
val primitiveIteratorsByType = PrimitiveType.values().associate { type ->
val iteratorClass = getClass(Name.identifier(type.typeName.asString() + "Iterator"), "kotlin", "collections")
type to iteratorClass
}
val asserts = builtInsPackage("kotlin")
.getContributedFunctions(Name.identifier("assert"), NoLookupLocation.FROM_BACKEND)
.map { symbolTable.referenceFunction(it) }
private fun progression(name: String) = symbolTable.referenceClass(
builtInsPackage("kotlin", "ranges").getContributedClassifier(
Name.identifier(name), NoLookupLocation.FROM_BACKEND
) as ClassDescriptor
)
private fun progression(name: String) = getClass(Name.identifier(name), "kotlin", "ranges")
val charProgression = progression("CharProgression")
val intProgression = progression("IntProgression")
@@ -98,14 +110,23 @@ abstract class Symbols<out T : CommonBackendContext>(val context: T, private val
val integerClasses = listOf(byte, short, int, long)
val integerClassesTypes = integerClasses.map { it.descriptor.defaultType }
val arrayOf = symbolTable.referenceSimpleFunction(
builtInsPackage("kotlin").getContributedFunctions(
Name.identifier("arrayOf"), NoLookupLocation.FROM_BACKEND
).first {
val arrayOf = getSimpleFunction(Name.identifier("arrayOf")) {
it.extensionReceiverParameter == null && it.dispatchReceiverParameter == null && it.valueParameters.size == 1 &&
it.valueParameters[0].isVararg
}
val primitiveArrayOfByType = PrimitiveType.values().associate { type ->
val function = getSimpleFunction(Name.identifier(type.name.toLowerCase() + "ArrayOf")) {
it.extensionReceiverParameter == null && it.dispatchReceiverParameter == null && it.valueParameters.size == 1 &&
it.valueParameters[0].isVararg
}
)
type to function
}
val arrayOfNulls = getSimpleFunction(Name.identifier("arrayOfNulls")) {
it.extensionReceiverParameter == null && it.dispatchReceiverParameter == null && it.valueParameters.size == 1 &&
KotlinBuiltIns.isInt(it.valueParameters[0].type)
}
val array = symbolTable.referenceClass(builtIns.array)
@@ -134,16 +155,6 @@ abstract class Symbols<out T : CommonBackendContext>(val context: T, private val
val arrays = primitiveArrays.values + unsignedArrays.values + array
protected fun arrayExtensionFun(type: KotlinType, name: String): IrSimpleFunctionSymbol {
val descriptor = builtInsPackage("kotlin")
.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND)
.firstOrNull {
it.valueParameters.isEmpty()
&& (it.extensionReceiverParameter?.type?.constructor?.declarationDescriptor as? ClassDescriptor)?.defaultType == type
} ?: throw Error(type.toString())
return symbolTable.referenceSimpleFunction(descriptor)
}
abstract val copyRangeTo: Map<ClassDescriptor, IrSimpleFunctionSymbol>
abstract val coroutineImpl: IrClassSymbol
@@ -152,32 +163,28 @@ abstract class Symbols<out T : CommonBackendContext>(val context: T, private val
abstract val getContinuation: IrSimpleFunctionSymbol
private val binaryOperatorCache = mutableMapOf<Triple<Name, KotlinType, KotlinType>, IrFunctionSymbol>()
private val binaryOperatorCache = mutableMapOf<Triple<Name, KotlinType, KotlinType>, IrSimpleFunctionSymbol>()
fun getBinaryOperator(name: Name, lhsType: KotlinType, rhsType: KotlinType): IrFunctionSymbol {
fun getBinaryOperator(name: Name, lhsType: KotlinType, rhsType: KotlinType): IrSimpleFunctionSymbol {
val key = Triple(name, lhsType, rhsType)
var result = binaryOperatorCache[key]
if (result == null) {
result = symbolTable.referenceFunction(lhsType.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND)
.first { it.valueParameters.size == 1 && it.valueParameters[0].type == rhsType }
return binaryOperatorCache.getOrPut(key) {
symbolTable.referenceSimpleFunction(
lhsType.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND)
.first { it.valueParameters.size == 1 && it.valueParameters[0].type == rhsType }
)
binaryOperatorCache[key] = result
}
return result
}
private val unaryOperatorCache = mutableMapOf<Pair<Name, KotlinType>, IrFunctionSymbol>()
private val unaryOperatorCache = mutableMapOf<Pair<Name, KotlinType>, IrSimpleFunctionSymbol>()
fun getUnaryOperator(name: Name, receiverType: KotlinType): IrFunctionSymbol {
fun getUnaryOperator(name: Name, receiverType: KotlinType): IrSimpleFunctionSymbol {
val key = name to receiverType
var result = unaryOperatorCache[key]
if (result == null) {
result = symbolTable.referenceFunction(receiverType.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND)
.first { it.valueParameters.isEmpty() }
return unaryOperatorCache.getOrPut(key) {
symbolTable.referenceSimpleFunction(
receiverType.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND)
.first { it.valueParameters.isEmpty() }
)
unaryOperatorCache[key] = result
}
return result
}
val intAnd = getBinaryOperator(OperatorNameConventions.AND, builtIns.intType, builtIns.intType)
@@ -186,6 +193,17 @@ abstract class Symbols<out T : CommonBackendContext>(val context: T, private val
fun functionN(n: Int): IrClassSymbol = symbolTable.referenceClass(builtIns.getFunction(n))
fun suspendFunctionN(n: Int): IrClassSymbol = symbolTable.referenceClass(builtIns.getSuspendFunction(n))
val extensionToString = getSimpleFunction(Name.identifier("toString")) {
it.dispatchReceiverParameter == null && it.extensionReceiverParameter != null &&
KotlinBuiltIns.isNullableAny(it.extensionReceiverParameter!!.type) && it.valueParameters.size == 0
}
val stringPlus = getSimpleFunction(Name.identifier("plus")) {
it.dispatchReceiverParameter == null && it.extensionReceiverParameter != null &&
KotlinBuiltIns.isStringOrNullableString(it.extensionReceiverParameter!!.type) && it.valueParameters.size == 1 &&
KotlinBuiltIns.isNullableAny(it.valueParameters.first().type)
}
companion object {
fun isLateinitIsInitializedPropertyGetter(symbol: IrFunctionSymbol): Boolean =
symbol is IrSimpleFunctionSymbol && symbol.owner.let { function ->
@@ -39,7 +39,7 @@ class JvmBackendContext(
private val symbolTable = symbolTable.lazyWrapper
override val ir = JvmIr(irModuleFragment, this.symbolTable)
val irIntrinsics = IrIntrinsicMethods(irBuiltIns)
val irIntrinsics = IrIntrinsicMethods(irBuiltIns, ir.symbols)
override var inVerbosePhase: Boolean = false
@@ -6,23 +6,27 @@
package org.jetbrains.kotlin.backend.jvm
import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.backend.common.ir.addChild
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.builders.declarations.*
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrPackageFragment
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl
import org.jetbrains.kotlin.ir.types.defaultType
import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
@@ -49,7 +53,10 @@ class JvmSymbols(
private fun createPackage(fqName: FqName): IrPackageFragment =
IrExternalPackageFragmentImpl(IrExternalPackageFragmentSymbolImpl(EmptyPackageFragmentDescriptor(context.state.module, fqName)))
private val kotlinPackage: IrPackageFragment = createPackage(FqName("kotlin"))
private val kotlinJvmPackage: IrPackageFragment = createPackage(FqName("kotlin.jvm"))
private val kotlinJvmInternalPackage: IrPackageFragment = createPackage(FqName("kotlin.jvm.internal"))
private val kotlinJvmInternalUnsafePackage: IrPackageFragment = createPackage(FqName("kotlin.jvm.internal.unsafe"))
private val kotlinJvmFunctionsPackage: IrPackageFragment = createPackage(FqName("kotlin.jvm.functions"))
private fun createClass(fqName: FqName, classKind: ClassKind = ClassKind.CLASS, block: (IrClass) -> Unit): IrClass =
@@ -254,4 +261,47 @@ class JvmSymbols(
val getOrCreateKotlinClasses: IrSimpleFunctionSymbol =
reflection.functions.single { it.owner.name.asString() == "getOrCreateKotlinClasses" }
val javaClassProperty: IrPropertySymbol = kotlinJvmPackage.addProperty {
name = Name.identifier("javaClass")
}.apply {
addGetter().apply {
val typeParameter = addTypeParameter {
name = Name.identifier("T")
}.apply {
superTypes.add(irBuiltIns.anyType)
}
addExtensionReceiver(typeParameter.defaultType)
returnType = javaLangClass.typeWith(typeParameter.defaultType)
}
}.symbol
val kClassJavaProperty: IrPropertySymbol = kotlinJvmPackage.addProperty {
name = Name.identifier("java")
}.apply {
addGetter().apply {
val extensionReceiverType = irBuiltIns.kClassClass.typeWith()
addExtensionReceiver(extensionReceiverType)
returnType = javaLangClass.typeWith(extensionReceiverType)
}
}.symbol
val monitorEnter = kotlinJvmInternalUnsafePackage.addFunction("monitorEnter", irBuiltIns.unitType, isStatic = true).apply {
addValueParameter("monitor", irBuiltIns.anyType)
}.symbol
val monitorExit = kotlinJvmInternalUnsafePackage.addFunction("monitorExit", irBuiltIns.unitType, isStatic = true).apply {
addValueParameter("monitor", irBuiltIns.anyType)
}.symbol
val isArrayOf = kotlinJvmPackage.addFunction("isArrayOf", irBuiltIns.booleanType, isStatic = true).apply {
addExtensionReceiver(irBuiltIns.arrayClass.owner.defaultType)
addTypeParameter("T", irBuiltIns.anyNType)
}.symbol
// We cannot create Cloneable reference out of thin air, since we have to preserve the information that it is a Java interface and
// it has no DefaultImpls counterpart.
val cloneable = symbolTable.referenceClass(
builtInsPackage("kotlin").getContributedClassifier(Name.identifier("Cloneable"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor
)
}
@@ -302,7 +302,7 @@ class ExpressionCodegen(
}
private fun generateCall(expression: IrFunctionAccessExpression, superQualifier: ClassDescriptor?, data: BlockInfo): PromisedValue {
classCodegen.context.irIntrinsics.getIntrinsic(expression.descriptor.original as CallableMemberDescriptor)
classCodegen.context.irIntrinsics.getIntrinsic(expression.symbol)
?.invoke(expression, this, data)?.let { return it.coerce(expression.asmType) }
val isSuperCall = superQualifier != null
val callable = resolveToCallable(expression, isSuperCall)
@@ -20,7 +20,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.codegen.BlockInfo
import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.Type
@@ -28,7 +28,7 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
object ArrayConstructor : IntrinsicMethod() {
override fun toCallable(
expression: IrMemberAccessExpression,
expression: IrFunctionAccessExpression,
signature: JvmMethodSignature,
context: JvmBackendContext
): IrIntrinsicFunction {
@@ -18,12 +18,13 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.Type
class ArrayGet : IntrinsicMethod() {
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
object ArrayGet : IntrinsicMethod() {
override fun toCallable(expression: IrFunctionAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
val arrayType = calcReceiverType(expression, context)
val elementType = AsmUtil.correctElementType(arrayType)
return IrIntrinsicFunction.create(expression, signature.newReturnType(elementType), context, listOf(arrayType, Type.INT_TYPE)) {
@@ -19,11 +19,12 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
class ArrayIterator : IntrinsicMethod() {
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
object ArrayIterator : IntrinsicMethod() {
override fun toCallable(expression: IrFunctionAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
val method = context.state.typeMapper.mapToCallableMethod(expression.descriptor as FunctionDescriptor, false)
return IrIntrinsicFunction.create(expression, signature, context, method.owner) {
val methodSignature = "(${method.owner.descriptor})${method.returnType.descriptor}"
@@ -17,11 +17,11 @@
package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
class ArrayOf : IntrinsicMethod() {
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
object ArrayOf : IntrinsicMethod() {
override fun toCallable(expression: IrFunctionAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
return IrIntrinsicFunction.create(expression, signature, context, signature.returnType) {
//do nothing all generated as vararg
}
@@ -18,13 +18,14 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.Type
class ArraySet : IntrinsicMethod() {
object ArraySet : IntrinsicMethod() {
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
override fun toCallable(expression: IrFunctionAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
val arrayType = expressionType(expression.dispatchReceiver!!, context)
val elementType = AsmUtil.correctElementType(arrayType)
return IrIntrinsicFunction.create(expression, signature, context, listOf(arrayType, Type.INT_TYPE, elementType)) {
@@ -17,12 +17,13 @@
package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
class ArraySize : IntrinsicMethod() {
object ArraySize : IntrinsicMethod() {
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
override fun toCallable(expression: IrFunctionAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
return IrIntrinsicFunction.create(expression, signature, context) {
it.arraylength()
}
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.codegen.AsmUtil.numberFunctionOperandType
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.Opcodes.*
@@ -28,7 +29,7 @@ class BinaryOp(private val opcode: Int) : IntrinsicMethod() {
private fun shift(): Boolean =
opcode == ISHL || opcode == ISHR || opcode == IUSHR
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
override fun toCallable(expression: IrFunctionAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
val owner = context.state.typeMapper.mapOwner(expression.descriptor)
val returnType = signature.returnType
val intermediateResultType: Type = numberFunctionOperandType(returnType)
@@ -18,14 +18,15 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.Opcodes
class Clone : IntrinsicMethod() {
object Clone : IntrinsicMethod() {
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
override fun toCallable(expression: IrFunctionAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
return IrIntrinsicFunction.create(expression, signature.newReturnType(AsmTypes.OBJECT_TYPE), context) {
val opcode = if (expression is IrCall && expression.superQualifier != null) Opcodes.INVOKESPECIAL else Opcodes.INVOKEVIRTUAL
it.visitMethodInsn(opcode, "java/lang/Object", "clone", "()Ljava/lang/Object;", false)
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.codegen.BranchedValue
import org.jetbrains.kotlin.codegen.NumberCompare
import org.jetbrains.kotlin.codegen.ObjectCompare
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.lexer.KtSingleValueToken
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.types.KotlinType
@@ -33,17 +32,17 @@ import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import java.lang.UnsupportedOperationException
class CompareTo : IntrinsicMethod() {
object CompareTo : IntrinsicMethod() {
private fun genInvoke(type: Type?, v: InstructionAdapter) {
when (type) {
Type.CHAR_TYPE, Type.BYTE_TYPE, Type.SHORT_TYPE, Type.INT_TYPE ->
v.invokestatic(
IntrinsicMethods.INTRINSICS_CLASS_NAME,
IrIntrinsicMethods.INTRINSICS_CLASS_NAME,
"compare",
"(II)I",
false
)
Type.LONG_TYPE -> v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "compare", "(JJ)I", false)
Type.LONG_TYPE -> v.invokestatic(IrIntrinsicMethods.INTRINSICS_CLASS_NAME, "compare", "(JJ)I", false)
Type.FLOAT_TYPE -> v.invokestatic("java/lang/Float", "compare", "(FF)I", false)
Type.DOUBLE_TYPE -> v.invokestatic("java/lang/Double", "compare", "(DD)I", false)
else -> throw UnsupportedOperationException()
@@ -51,7 +50,7 @@ class CompareTo : IntrinsicMethod() {
}
override fun toCallable(
expression: IrMemberAccessExpression,
expression: IrFunctionAccessExpression,
signature: JvmMethodSignature,
context: JvmBackendContext
): IrIntrinsicFunction {
@@ -61,7 +61,7 @@ class Ieee754Equals(val operandType: Type) : IntrinsicMethod() {
private val boxedOperandType = AsmUtil.boxType(operandType)
override fun toCallable(
expression: IrMemberAccessExpression,
expression: IrFunctionAccessExpression,
signature: JvmMethodSignature,
context: JvmBackendContext
): IrIntrinsicFunction {
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.Callable
import org.jetbrains.kotlin.codegen.CallableMethod
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
@@ -28,9 +29,9 @@ import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class HashCode : IntrinsicMethod() {
object HashCode : IntrinsicMethod() {
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
override fun toCallable(expression: IrFunctionAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
return IrIntrinsicFunction.create(expression, signature, context, AsmTypes.OBJECT_TYPE) {
it.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "hashCode", "()I", false)
}
@@ -18,11 +18,12 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.codegen.AsmUtil.genIncrement
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
class Increment(private val myDelta: Int) : IntrinsicMethod() {
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
override fun toCallable(expression: IrFunctionAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
return IrIntrinsicFunction.create(expression, signature, context) {
genIncrement(signature.returnType, myDelta, it)
}
@@ -19,7 +19,7 @@ import org.jetbrains.org.objectweb.asm.commons.Method
abstract class IntrinsicMethod {
open fun toCallable(
expression: IrMemberAccessExpression,
expression: IrFunctionAccessExpression,
signature: JvmMethodSignature,
context: JvmBackendContext
): IrIntrinsicFunction = TODO("implement toCallable() or invoke() of $this")
@@ -1,181 +0,0 @@
/*
* 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 com.google.common.collect.ImmutableList;
import kotlin.text.StringsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.builtins.PrimitiveType;
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.FqNameUnsafe;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType;
import org.jetbrains.kotlin.types.expressions.OperatorConventions;
import org.jetbrains.org.objectweb.asm.Type;
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.*;
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
public class IntrinsicMethods {
public static final String INTRINSICS_CLASS_NAME = "kotlin/jvm/internal/Intrinsics";
private static final FqName KOTLIN_JVM = new FqName("kotlin.jvm");
/* package */ static final FqNameUnsafe RECEIVER_PARAMETER_FQ_NAME = new FqNameUnsafe("T");
private static final IntrinsicMethod UNARY_MINUS = new UnaryMinus();
private static final IntrinsicMethod UNARY_PLUS = new UnaryPlus();
private static final IntrinsicMethod NUMBER_CAST = new NumberCast();
private static final IntrinsicMethod INV = new Inv();
private static final IntrinsicMethod RANGE_TO = new RangeTo();
private static final IntrinsicMethod INC = new Increment(1);
private static final IntrinsicMethod DEC = new Increment(-1);
private static final IntrinsicMethod HASH_CODE = new HashCode();
private static final IntrinsicMethod ARRAY_SIZE = new ArraySize();
private static final Equals EQUALS = new Equals(KtTokens.EQEQ);
private static final IteratorNext ITERATOR_NEXT = new IteratorNext();
private static final ArraySet ARRAY_SET = new ArraySet();
private static final ArrayGet ARRAY_GET = new ArrayGet();
private static final ToString TO_STRING = new ToString();
private static final Clone CLONE = new Clone();
private static final IntrinsicMethod ARRAY_ITERATOR = new ArrayIterator();
private final IntrinsicsMap intrinsicsMap = new IntrinsicsMap();
public IntrinsicMethods() {
intrinsicsMap.registerIntrinsic(KOTLIN_JVM, RECEIVER_PARAMETER_FQ_NAME, "javaClass", -1, JavaClassProperty.INSTANCE);
intrinsicsMap.registerIntrinsic(KOTLIN_JVM, KotlinBuiltIns.FQ_NAMES.kClass, "java", -1, new KClassJavaProperty());
intrinsicsMap.registerIntrinsic(new FqName("kotlin.jvm.internal.unsafe"), null, "monitorEnter", 1, MonitorInstruction.MONITOR_ENTER);
intrinsicsMap.registerIntrinsic(new FqName("kotlin.jvm.internal.unsafe"), null, "monitorExit", 1, MonitorInstruction.MONITOR_EXIT);
intrinsicsMap.registerIntrinsic(KOTLIN_JVM, KotlinBuiltIns.FQ_NAMES.array, "isArrayOf", 0, new IsArrayOf());
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, null, "arrayOf", 1, new ArrayOf());
ImmutableList<Name> primitiveCastMethods = OperatorConventions.NUMBER_CONVERSIONS.asList();
for (Name method : primitiveCastMethods) {
String methodName = method.asString();
declareIntrinsicFunction(FQ_NAMES.number, methodName, 0, NUMBER_CAST);
for (PrimitiveType type : PrimitiveType.NUMBER_TYPES) {
declareIntrinsicFunction(type.getTypeFqName(), methodName, 0, NUMBER_CAST);
}
}
for (PrimitiveType type : PrimitiveType.NUMBER_TYPES) {
FqName typeFqName = type.getTypeFqName();
declareIntrinsicFunction(typeFqName, "plus", 0, UNARY_PLUS);
declareIntrinsicFunction(typeFqName, "unaryPlus", 0, UNARY_PLUS);
declareIntrinsicFunction(typeFqName, "minus", 0, UNARY_MINUS);
declareIntrinsicFunction(typeFqName, "unaryMinus", 0, UNARY_MINUS);
declareIntrinsicFunction(typeFqName, "inv", 0, INV);
declareIntrinsicFunction(typeFqName, "rangeTo", 1, RANGE_TO);
declareIntrinsicFunction(typeFqName, "inc", 0, INC);
declareIntrinsicFunction(typeFqName, "dec", 0, DEC);
}
for (PrimitiveType type : PrimitiveType.values()) {
FqName typeFqName = type.getTypeFqName();
Type asmPrimitiveType = AsmTypes.valueTypeForPrimitive(type);
declareIntrinsicFunction(typeFqName, "equals", 1, EQUALS);
declareIntrinsicFunction(typeFqName, "hashCode", 0, HASH_CODE);
declareIntrinsicFunction(typeFqName, "toString", 0, TO_STRING);
intrinsicsMap.registerIntrinsic(
BUILT_INS_PACKAGE_FQ_NAME, null, StringsKt.decapitalize(type.getArrayTypeName().asString()) + "Of", 1, new ArrayOf()
);
}
declareBinaryOp("plus", IADD);
declareBinaryOp("minus", ISUB);
declareBinaryOp("times", IMUL);
declareBinaryOp("div", IDIV);
declareBinaryOp("mod", IREM);
declareBinaryOp("rem", IREM);
declareBinaryOp("shl", ISHL);
declareBinaryOp("shr", ISHR);
declareBinaryOp("ushr", IUSHR);
declareBinaryOp("and", IAND);
declareBinaryOp("or", IOR);
declareBinaryOp("xor", IXOR);
declareIntrinsicFunction(FQ_NAMES._boolean, "not", 0, new Not());
declareIntrinsicFunction(FQ_NAMES.string, "get", 1, new StringGetChar());
declareIntrinsicFunction(FQ_NAMES.cloneable, "clone", 0, CLONE);
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, KotlinBuiltIns.FQ_NAMES.any, "toString", 0, TO_STRING);
intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, null, "arrayOfNulls", 1, new NewArray());
for (PrimitiveType type : PrimitiveType.values()) {
declareIntrinsicFunction(type.getTypeFqName(), "compareTo", 1, new CompareTo());
declareIntrinsicFunction(COLLECTIONS_PACKAGE_FQ_NAME.child(Name.identifier(type.getTypeName().asString() + "Iterator")), "next", 0, ITERATOR_NEXT);
}
declareArrayMethods();
}
private void declareArrayMethods() {
for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) {
declareArrayMethods(jvmPrimitiveType.getPrimitiveType().getArrayTypeFqName());
}
declareArrayMethods(FQ_NAMES.array.toSafe());
}
private void declareArrayMethods(@NotNull FqName arrayTypeFqName) {
declareIntrinsicFunction(arrayTypeFqName, "size", -1, ARRAY_SIZE);
declareIntrinsicFunction(arrayTypeFqName, "set", 2, ARRAY_SET);
declareIntrinsicFunction(arrayTypeFqName, "get", 1, ARRAY_GET);
declareIntrinsicFunction(arrayTypeFqName, "clone", 0, CLONE);
declareIntrinsicFunction(arrayTypeFqName, "iterator", 0, ARRAY_ITERATOR);
declareIntrinsicFunction(arrayTypeFqName, "<init>", 2, ArrayConstructor.INSTANCE);
}
private void declareBinaryOp(@NotNull String methodName, int opcode) {
BinaryOp op = new BinaryOp(opcode);
for (PrimitiveType type : PrimitiveType.values()) {
declareIntrinsicFunction(type.getTypeFqName(), methodName, 1, op);
}
}
private void declareIntrinsicFunction(
@NotNull FqName classFqName,
@NotNull String methodName,
int arity,
@NotNull IntrinsicMethod implementation
) {
intrinsicsMap.registerIntrinsic(classFqName, null, methodName, arity, implementation);
}
private void declareIntrinsicFunction(
@NotNull FqNameUnsafe classFqName,
@NotNull String methodName,
int arity,
@NotNull IntrinsicMethod implementation
) {
intrinsicsMap.registerIntrinsic(classFqName.toSafe(), null, methodName, arity, implementation);
}
@Nullable
public IntrinsicMethod getIntrinsic(@NotNull CallableMemberDescriptor descriptor) {
return intrinsicsMap.getIntrinsic(descriptor);
}
}
@@ -1,118 +0,0 @@
/*
* 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.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.FqNameUnsafe;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import java.util.HashMap;
import java.util.Map;
class IntrinsicsMap {
private static final class Key {
private final FqNameUnsafe owner;
private final FqNameUnsafe receiverParameter;
private final String name;
private final int valueParameterCount;
private Key(@NotNull FqNameUnsafe owner, @Nullable FqNameUnsafe receiverParameter, @NotNull String name, int valueParameterCount) {
this.owner = owner;
this.receiverParameter = receiverParameter;
this.name = name;
this.valueParameterCount = valueParameterCount;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Key key = (Key) o;
if (valueParameterCount != key.valueParameterCount) return false;
if (!name.equals(key.name)) return false;
if (!owner.equals(key.owner)) return false;
if (receiverParameter == null ? key.receiverParameter != null : !receiverParameter.equals(key.receiverParameter)) return false;
return true;
}
@Override
public int hashCode() {
int result = owner.hashCode();
result = 31 * result + name.hashCode();
result = 31 * result + valueParameterCount;
result = 31 * result + (receiverParameter != null ? receiverParameter.hashCode() : 0);
return result;
}
}
private static int valueParameterCountForKey(@NotNull CallableMemberDescriptor member) {
if (member instanceof PropertyDescriptor) {
return -1;
}
else {
return member.getValueParameters().size();
}
}
private final Map<Key, IntrinsicMethod> intrinsicsMap = new HashMap<>();
/**
* @param valueParameterCount -1 for property
*/
public void registerIntrinsic(
@NotNull FqName owner,
@Nullable FqNameUnsafe receiverParameter,
@NotNull String name,
int valueParameterCount,
@NotNull IntrinsicMethod impl
) {
intrinsicsMap.put(new Key(owner.toUnsafe(), receiverParameter, name, valueParameterCount), impl);
}
@Nullable
public IntrinsicMethod getIntrinsic(@NotNull CallableMemberDescriptor descriptor) {
Key key = new Key(
DescriptorUtils.getFqName(descriptor.getContainingDeclaration()),
getReceiverParameterFqName(descriptor),
descriptor.getName().asString(),
valueParameterCountForKey(descriptor)
);
return intrinsicsMap.get(key);
}
@Nullable
private static FqNameUnsafe getReceiverParameterFqName(@NotNull CallableMemberDescriptor descriptor) {
ReceiverParameterDescriptor receiverParameter = descriptor.getExtensionReceiverParameter();
if (receiverParameter == null) return null;
ClassifierDescriptor classifier = receiverParameter.getType().getConstructor().getDeclarationDescriptor();
if (classifier == null) return null;
if (classifier instanceof TypeParameterDescriptor) {
return IntrinsicMethods.RECEIVER_PARAMETER_FQ_NAME;
}
return DescriptorUtils.getFqName(classifier);
}
}
@@ -18,13 +18,14 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.codegen.AsmUtil.numberFunctionOperandType
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.Type
class Inv : IntrinsicMethod() {
object Inv : IntrinsicMethod() {
/*TODO new this type*/
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
override fun toCallable(expression: IrFunctionAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
val returnType = signature.returnType
val type = numberFunctionOperandType(returnType)
return IrIntrinsicFunction.create(expression, signature, context, type) {
@@ -22,13 +22,14 @@ import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.OwnerKind
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class IrEnumValueOf : IntrinsicMethod() {
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
object IrEnumValueOf : IntrinsicMethod() {
override fun toCallable(expression: IrFunctionAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
val enumType = context.state.typeMapper.mapType(expression.descriptor.returnType!!)
val newSignature = context.state.typeMapper.mapSignatureSkipGeneric(expression.descriptor as FunctionDescriptor, OwnerKind.IMPLEMENTATION)
val stringType = AsmTypes.JAVA_STRING_TYPE;
@@ -20,17 +20,18 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.codegen.BlockInfo
import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_STRING_TYPE
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class IrIllegalArgumentException : IntrinsicMethod() {
object IrIllegalArgumentException : IntrinsicMethod() {
val exceptionTypeDescriptor = Type.getType(IllegalArgumentException::class.java)!!
override fun toCallable(
expression: IrMemberAccessExpression,
expression: IrFunctionAccessExpression,
signature: JvmMethodSignature,
context: JvmBackendContext
): IrIntrinsicFunction {
@@ -16,59 +16,170 @@
package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.backend.jvm.JvmSymbols
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.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.properties
import org.jetbrains.kotlin.lexer.KtSingleValueToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.types.SimpleType
import org.jetbrains.kotlin.types.expressions.OperatorConventions
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import org.jetbrains.org.objectweb.asm.Opcodes.*
import org.jetbrains.org.objectweb.asm.Type
class IrIntrinsicMethods(irBuiltIns: IrBuiltIns) {
val intrinsics = IntrinsicMethods()
class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
val andandSymbol = irBuiltIns.run { defineOperator(OperatorNames.ANDAND, bool, listOf(bool, bool)) }
private val andand = andandSymbol.descriptor
private val intrinsicsMap = (
listOf(
symbols.javaClassProperty.owner.getter!!.symbol.toKey() to JavaClassProperty,
symbols.kClassJavaProperty.owner.getter!!.symbol.toKey() to KClassJavaProperty,
symbols.monitorEnter.toKey() to MonitorInstruction.MONITOR_ENTER,
symbols.monitorExit.toKey() to MonitorInstruction.MONITOR_EXIT,
symbols.isArrayOf.toKey() to IsArrayOf,
symbols.arrayOf.toKey() to ArrayOf,
symbols.extensionToString.toKey() to ToString,
symbols.arrayOfNulls.toKey() to NewArray,
irBuiltIns.eqeqSymbol.toKey()!! to Equals(KtTokens.EQEQ),
irBuiltIns.eqeqeqSymbol.toKey()!! to Equals(KtTokens.EQEQEQ),
irBuiltIns.ieee754equalsFunByOperandType[irBuiltIns.float]!!.toKey()!! to Ieee754Equals(Type.FLOAT_TYPE),
irBuiltIns.ieee754equalsFunByOperandType[irBuiltIns.double]!!.toKey()!! to Ieee754Equals(Type.DOUBLE_TYPE),
irBuiltIns.booleanNotSymbol.toKey()!! to Not,
irBuiltIns.enumValueOfSymbol.toKey()!! to IrEnumValueOf,
irBuiltIns.noWhenBranchMatchedExceptionSymbol.toKey()!! to IrNoWhenBranchMatchedException,
irBuiltIns.illegalArgumentExceptionSymbol.toKey()!! to IrIllegalArgumentException,
irBuiltIns.throwNpeSymbol.toKey()!! to ThrowNPE,
andandSymbol.toKey() to AndAnd
) +
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) +
unaryFunForPrimitives("toString", ToString) +
binaryFunForPrimitives("equals", EQUALS) +
symbols.primitiveArrayOfByType.values.map { it.toKey() to ArrayOf } +
binaryFunForPrimitives("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) +
binaryFunForPrimitives("compareTo", CompareTo) +
methodWithArity(irBuiltIns.booleanClass, "not", 0, Not) +
methodWithArity(irBuiltIns.stringClass, "get", 1, StringGetChar) +
methodWithArity(symbols.cloneable, "clone", 0, Clone) +
symbols.primitiveIteratorsByType.values.flatMap { iteratorClass ->
methodWithArity(iteratorClass, "next", 0, IteratorNext)
} +
arrayMethods() +
primitiveComparisonIntrinsics(irBuiltIns.lessFunByOperandType, KtTokens.LT) +
primitiveComparisonIntrinsics(irBuiltIns.lessOrEqualFunByOperandType, KtTokens.LTEQ) +
primitiveComparisonIntrinsics(irBuiltIns.greaterFunByOperandType, KtTokens.GT) +
primitiveComparisonIntrinsics(irBuiltIns.greaterOrEqualFunByOperandType, KtTokens.GTEQ)
).toMap()
private val irMapping = hashMapOf<CallableMemberDescriptor, IntrinsicMethod>()
fun getIntrinsic(symbol: IrFunctionSymbol): IntrinsicMethod? = intrinsicsMap[symbol.toKey()]
private fun createPrimitiveComparisonIntrinsics(typeToIrFun: Map<SimpleType, IrSimpleFunctionSymbol>, operator: KtSingleValueToken) {
for ((type, irFunSymbol) in typeToIrFun) {
irMapping[irFunSymbol.descriptor] = PrimitiveComparison(type, operator)
private fun unaryFunForPrimitives(name: String, intrinsic: IntrinsicMethod): List<Pair<Key, IntrinsicMethod>> =
PrimitiveType.values().flatMap { type ->
methodWithArity(irBuiltIns.primitiveTypeToIrType[type]!!.classOrNull!!, name, 0, intrinsic)
}
}
init {
irMapping[irBuiltIns.eqeq] = Equals(KtTokens.EQEQ)
irMapping[irBuiltIns.eqeqeq] = Equals(KtTokens.EQEQEQ)
irMapping[irBuiltIns.ieee754equalsFunByOperandType[irBuiltIns.float]!!.descriptor] = Ieee754Equals(Type.FLOAT_TYPE)
irMapping[irBuiltIns.ieee754equalsFunByOperandType[irBuiltIns.double]!!.descriptor] = Ieee754Equals(Type.DOUBLE_TYPE)
irMapping[irBuiltIns.booleanNot] = Not()
createPrimitiveComparisonIntrinsics(irBuiltIns.lessFunByOperandType, KtTokens.LT)
createPrimitiveComparisonIntrinsics(irBuiltIns.lessOrEqualFunByOperandType, KtTokens.LTEQ)
createPrimitiveComparisonIntrinsics(irBuiltIns.greaterFunByOperandType, KtTokens.GT)
createPrimitiveComparisonIntrinsics(irBuiltIns.greaterOrEqualFunByOperandType, KtTokens.GTEQ)
irMapping[irBuiltIns.enumValueOf] = IrEnumValueOf()
irMapping[irBuiltIns.noWhenBranchMatchedException] = IrNoWhenBranchMatchedException()
irMapping[irBuiltIns.illegalArgumentException] = IrIllegalArgumentException()
irMapping[irBuiltIns.throwNpe] = ThrowNPE()
irMapping[andand] = AndAnd
}
fun getIntrinsic(descriptor: CallableMemberDescriptor): IntrinsicMethod? {
intrinsics.getIntrinsic(descriptor)?.let { return it }
if (descriptor is PropertyAccessorDescriptor) {
return intrinsics.getIntrinsic(DescriptorUtils.unwrapFakeOverride(descriptor.correspondingProperty))
private fun binaryFunForPrimitives(name: String, intrinsic: IntrinsicMethod): List<Pair<Key, IntrinsicMethod>> =
PrimitiveType.values().flatMap { type ->
methodWithArity(irBuiltIns.primitiveTypeToIrType[type]!!.classOrNull!!, name, 1, intrinsic)
}
return irMapping[descriptor.original]
private fun binaryOp(methodName: String, opcode: Int) = binaryFunForPrimitives(methodName, BinaryOp(opcode))
private fun numberConversionMethods(): List<Pair<Key, IntrinsicMethod>> =
PrimitiveType.NUMBER_TYPES.flatMap { type ->
numberConversionMethods(irBuiltIns.primitiveTypeToIrType[type]!!.classOrNull!!)
} + numberConversionMethods(irBuiltIns.numberClass)
private fun arrayMethods(): List<Pair<Key, IntrinsicMethod>> =
symbols.primitiveArrays.values.flatMap { arrayMethods(it) } + arrayMethods(symbols.array)
data class Key(val owner: FqName, val receiverParameterTypeName: FqName?, val name: String, val valueParameterTypeNames: List<FqName?>)
companion object {
internal val INTRINSICS_CLASS_NAME = "kotlin/jvm/internal/Intrinsics"
private val INC = Increment(1)
private val DEC = Increment(-1)
private val EQUALS = Equals(KtTokens.EQEQ)
private fun IrFunctionSymbol.toKey(): Key? {
return Key(
owner.parent.safeAs<IrClass>()?.fqNameWhenAvailable ?: owner.parent.safeAs<IrPackageFragment>()?.fqName ?: return null,
getParameterFqName(owner.extensionReceiverParameter),
owner.name.asString(),
owner.valueParameters.map(::getParameterFqName)
)
}
private fun getParameterFqName(parameter: IrValueParameter?): FqName? =
parameter?.type?.safeAs<IrSimpleType>()?.classifier?.owner?.let {
when (it) {
is IrClass -> it.fqNameWhenAvailable
is IrTypeParameter -> FqName(it.name.asString())
else -> null
}
}
private fun methodWithArity(klass: IrClassSymbol, name: String, arity: Int, intrinsic: IntrinsicMethod): List<Pair<Key, IntrinsicMethod>> =
klass.owner.functions.filter {
it.name.asString() == name && it.valueParameters.size == arity
}.map {
it.symbol.toKey()!! to intrinsic
}.toList()
private fun numberConversionMethods(numberClass: IrClassSymbol) =
OperatorConventions.NUMBER_CONVERSIONS.flatMap { method ->
methodWithArity(numberClass, method.asString(), 0, NumberCast)
}
private fun arrayMethods(arrayClass: IrClassSymbol) = listOf(
arrayClass.constructors.single { it.owner.valueParameters.size == 2 }.toKey()!! to ArrayConstructor,
arrayClass.owner.properties.single { it.name.asString() == "size" }.getter!!.symbol.toKey()!! to ArraySize
) +
methodWithArity(arrayClass, "set", 2, ArraySet) +
methodWithArity(arrayClass, "get", 1, ArrayGet) +
methodWithArity(arrayClass, "clone", 0, Clone) +
methodWithArity(arrayClass, "iterator", 0, ArrayIterator)
private fun primitiveComparisonIntrinsics(typeToIrFun: Map<SimpleType, IrSimpleFunctionSymbol>, operator: KtSingleValueToken) =
typeToIrFun.map { (type, irFunSymbol) ->
irFunSymbol.toKey()!! to PrimitiveComparison(type, operator)
}
}
private object OperatorNames {
@@ -18,11 +18,12 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.codegen.AsmUtil.genThrow
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
class IrNoWhenBranchMatchedException : IntrinsicMethod() {
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
object IrNoWhenBranchMatchedException : IntrinsicMethod() {
override fun toCallable(expression: IrFunctionAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
return IrIntrinsicFunction.create(expression, signature, context) {
genThrow(it, "kotlin/NoWhenBranchMatchedException", null)
}
@@ -6,14 +6,15 @@
package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.types.Variance
class IsArrayOf : IntrinsicMethod() {
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
object IsArrayOf : IntrinsicMethod() {
override fun toCallable(expression: IrFunctionAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
val typeMapper = context.state.typeMapper
val descriptor = expression.descriptor
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.COLLECTIONS_PACKAGE_FQ_NAME
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.fileClasses.internalNameWithoutInnerClasses
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
@@ -27,32 +28,30 @@ import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.Type
class IteratorNext : IntrinsicMethod() {
object IteratorNext : IntrinsicMethod() {
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
override fun toCallable(expression: IrFunctionAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
val type = AsmUtil.unboxType(signature.returnType)
val newSignature = signature.newReturnType(type)
return IrIntrinsicFunction.create(expression, newSignature, context, AsmTypes.OBJECT_TYPE) {
val primitiveClassName = getKotlinPrimitiveClassName(type)
it.invokevirtual(
getPrimitiveIteratorType(primitiveClassName).internalName,
"next${primitiveClassName.asString()}",
"()" + type.descriptor,
false
getPrimitiveIteratorType(primitiveClassName).internalName,
"next${primitiveClassName.asString()}",
"()" + type.descriptor,
false
)
}
}
companion object {
// Type.CHAR_TYPE -> "Char"
private fun getKotlinPrimitiveClassName(type: Type): Name {
return JvmPrimitiveType.get(type.className).primitiveType.typeName
}
// Type.CHAR_TYPE -> "Char"
private fun getKotlinPrimitiveClassName(type: Type): Name {
return JvmPrimitiveType.get(type.className).primitiveType.typeName
}
// "Char" -> type for kotlin.collections.CharIterator
fun getPrimitiveIteratorType(primitiveClassName: Name): Type {
val iteratorName = Name.identifier(primitiveClassName.asString() + "Iterator")
return Type.getObjectType(COLLECTIONS_PACKAGE_FQ_NAME.child(iteratorName).internalNameWithoutInnerClasses)
}
// "Char" -> type for kotlin.collections.CharIterator
fun getPrimitiveIteratorType(primitiveClassName: Name): Type {
val iteratorName = Name.identifier(primitiveClassName.asString() + "Iterator")
return Type.getObjectType(COLLECTIONS_PACKAGE_FQ_NAME.child(iteratorName).internalNameWithoutInnerClasses)
}
}
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.ir.expressions.IrClassReference
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrGetClass
class KClassJavaProperty : IntrinsicMethod() {
object KClassJavaProperty : IntrinsicMethod() {
override fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo): PromisedValue? {
val extensionReceiver = expression.extensionReceiver
if (extensionReceiver !is IrClassReference && extensionReceiver !is IrGetClass)
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
@@ -32,7 +33,7 @@ class MonitorInstruction private constructor(private val opcode: Int) : Intrinsi
}
/*TODO void return type*/
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
override fun toCallable(expression: IrFunctionAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
return IrIntrinsicFunction.create(expression, signature, context, OBJECT_TYPE) {
it.visitInsn(opcode)
}
@@ -9,14 +9,18 @@ import org.jetbrains.kotlin.backend.jvm.codegen.BlockInfo
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class NewArray : IntrinsicMethod() {
object NewArray : IntrinsicMethod() {
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
override fun toCallable(
expression: IrFunctionAccessExpression,
signature: JvmMethodSignature,
context: JvmBackendContext
): IrIntrinsicFunction {
val ktType = expression.type
return object : IrIntrinsicFunction(expression, signature, context) {
override fun invoke(v: InstructionAdapter, codegen: ExpressionCodegen, data: BlockInfo): StackValue {
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.backend.jvm.codegen.coerceToBoolean
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.org.objectweb.asm.Label
class Not : IntrinsicMethod() {
object Not : IntrinsicMethod() {
class BooleanNegation(val value: BooleanValue) : BooleanValue(value.mv) {
override fun jumpIfFalse(target: Label) = value.jumpIfTrue(target)
override fun jumpIfTrue(target: Label) = value.jumpIfFalse(target)
@@ -18,12 +18,13 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
class NumberCast : IntrinsicMethod() {
object NumberCast : IntrinsicMethod() {
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
override fun toCallable(expression: IrFunctionAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
return IrIntrinsicFunction.create(expression, signature, context) {
StackValue.coerce(argsTypes[0], signature.returnType, it)
}
@@ -20,14 +20,14 @@ import org.jetbrains.kotlin.backend.jvm.codegen.BlockInfo
import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.Type.*
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import java.lang.IllegalStateException
class RangeTo : IntrinsicMethod() {
object RangeTo : IntrinsicMethod() {
private fun rangeTypeToPrimitiveType(rangeType: Type): Type {
val fqName = rangeType.internalName
val name = fqName.substringAfter("kotlin/ranges/").substringBefore("Range")
@@ -43,7 +43,7 @@ class RangeTo : IntrinsicMethod() {
}
}
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
override fun toCallable(expression: IrFunctionAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
val argType = rangeTypeToPrimitiveType(signature.returnType)
return object: IrIntrinsicFunction(expression, signature, context, listOf(argType) + signature.valueParameters.map { argType }) {
override fun genInvokeInstruction(v: InstructionAdapter) {
@@ -17,11 +17,12 @@
package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
class StringGetChar : IntrinsicMethod() {
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
object StringGetChar : IntrinsicMethod() {
override fun toCallable(expression: IrFunctionAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
return IrIntrinsicFunction.create(expression, signature, context) {
it.invokevirtual("java/lang/String", "charAt", "(I)C", false)
}
@@ -7,13 +7,14 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.Type
class ThrowNPE : IntrinsicMethod() {
object ThrowNPE : IntrinsicMethod() {
override fun toCallable(
expression: IrMemberAccessExpression,
expression: IrFunctionAccessExpression,
signature: JvmMethodSignature,
context: JvmBackendContext
): IrIntrinsicFunction {
@@ -18,11 +18,12 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
class ToString : IntrinsicMethod() {
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
object ToString : IntrinsicMethod() {
override fun toCallable(expression: IrFunctionAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
val type = AsmUtil.stringValueOfType(calcReceiverType(expression, context))
return IrIntrinsicFunction.create(expression, signature, context, type) {
it.invokestatic("java/lang/String", "valueOf", "(${type.descriptor})Ljava/lang/String;", false)
@@ -19,12 +19,13 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.codegen.AsmUtil.numberFunctionOperandType
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
class UnaryMinus : IntrinsicMethod() {
object UnaryMinus : IntrinsicMethod() {
/*TODO return type*/
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
override fun toCallable(expression: IrFunctionAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
return IrIntrinsicFunction.create(expression, signature, context) {
it.neg(numberFunctionOperandType(signature.returnType))
}
@@ -17,11 +17,12 @@
package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
class UnaryPlus : IntrinsicMethod() {
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
object UnaryPlus : IntrinsicMethod() {
override fun toCallable(expression: IrFunctionAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
return IrIntrinsicFunction.create(expression, signature, context) {
}
@@ -154,7 +154,7 @@ private class AnnotationLowering(private val context: JvmBackendContext) : FileL
}
private fun IrCall.isGetJava(): Boolean =
context.irIntrinsics.getIntrinsic(descriptor) is KClassJavaProperty
context.irIntrinsics.getIntrinsic(symbol) is KClassJavaProperty
}
private fun IrClassSymbol.getFunctionByName(name: String, numParams: Int): IrSimpleFunctionSymbol =
@@ -6,6 +6,7 @@
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
@@ -183,6 +184,17 @@ class IrBuiltIns(
val primitiveTypesWithComparisons = listOf(char, byte, short, int, long, float, double)
val primitiveFloatingPointTypes = listOf(float, double)
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 = primitiveTypesWithComparisons.defineComparisonOperatorForEachType(OperatorNames.LESS)
val lessOrEqualFunByOperandType = primitiveTypesWithComparisons.defineComparisonOperatorForEachType(OperatorNames.LESS_OR_EQUAL)
val greaterOrEqualFunByOperandType = primitiveTypesWithComparisons.defineComparisonOperatorForEachType(OperatorNames.GREATER_OR_EQUAL)