diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt index 94ab6ad4626..98012886a5d 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt @@ -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(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(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(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(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 abstract val coroutineImpl: IrClassSymbol @@ -152,32 +163,28 @@ abstract class Symbols(val context: T, private val abstract val getContinuation: IrSimpleFunctionSymbol - private val binaryOperatorCache = mutableMapOf, IrFunctionSymbol>() + private val binaryOperatorCache = mutableMapOf, 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, IrFunctionSymbol>() + private val unaryOperatorCache = mutableMapOf, 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(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 -> diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt index 08b5431f8af..e3e6a4568ba 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt @@ -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 diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSymbols.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSymbols.kt index 03a244de5a0..99e79390145 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSymbols.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmSymbols.kt @@ -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 + ) } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index de0a736e617..6877b595ce5 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -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) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayConstructor.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayConstructor.kt index accf489d2fb..dd443543838 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayConstructor.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayConstructor.kt @@ -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 { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayGet.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayGet.kt index 2f785fca3b3..379b5d1335c 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayGet.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayGet.kt @@ -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)) { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayIterator.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayIterator.kt index eaef0c94122..b144fa40329 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayIterator.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayIterator.kt @@ -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}" diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayOf.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayOf.kt index 95afab25724..4f5578e607a 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayOf.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayOf.kt @@ -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 } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArraySet.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArraySet.kt index b166ac240b7..18e94f4f9e3 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArraySet.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArraySet.kt @@ -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)) { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArraySize.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArraySize.kt index e6ecd556562..f9a10633185 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArraySize.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArraySize.kt @@ -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() } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/BinaryOp.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/BinaryOp.kt index dfa54665ce3..7c891aad245 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/BinaryOp.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/BinaryOp.kt @@ -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) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Clone.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Clone.kt index 908de2bd490..20f7b40c8ad 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Clone.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Clone.kt @@ -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) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/CompareTo.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/CompareTo.kt index 15ffb6d5f41..48670ac2a32 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/CompareTo.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/CompareTo.kt @@ -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 { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Equals.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Equals.kt index a1dfcb7cee9..dcaff7a22ae 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Equals.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Equals.kt @@ -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 { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/HashCode.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/HashCode.kt index 3c39aeec29d..03798b2464a 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/HashCode.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/HashCode.kt @@ -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) } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Increment.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Increment.kt index 8abfe9900ea..8ae71840dc8 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Increment.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Increment.kt @@ -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) } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethod.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethod.kt index 9e9dacd4dc4..3ad7c30a5b9 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethod.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethod.kt @@ -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") diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethods.java b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethods.java deleted file mode 100644 index 8ed1a684066..00000000000 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethods.java +++ /dev/null @@ -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 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, "", 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); - } -} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicsMap.java b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicsMap.java deleted file mode 100644 index e12f51cd182..00000000000 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicsMap.java +++ /dev/null @@ -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 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); - } -} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Inv.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Inv.kt index 31ede304c11..c9a499a2f77 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Inv.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Inv.kt @@ -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) { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrEnumValueOf.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrEnumValueOf.kt index 5f9e926fcdd..97e9438b66f 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrEnumValueOf.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrEnumValueOf.kt @@ -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; diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIllegalArgumentException.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIllegalArgumentException.kt index 3e8203ffa25..d6411de5b6e 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIllegalArgumentException.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIllegalArgumentException.kt @@ -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 { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt index 4898218f102..a51db9b41b6 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt @@ -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() + fun getIntrinsic(symbol: IrFunctionSymbol): IntrinsicMethod? = intrinsicsMap[symbol.toKey()] - private fun createPrimitiveComparisonIntrinsics(typeToIrFun: Map, operator: KtSingleValueToken) { - for ((type, irFunSymbol) in typeToIrFun) { - irMapping[irFunSymbol.descriptor] = PrimitiveComparison(type, operator) + private fun unaryFunForPrimitives(name: String, intrinsic: IntrinsicMethod): List> = + 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> = + 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> = + PrimitiveType.NUMBER_TYPES.flatMap { type -> + numberConversionMethods(irBuiltIns.primitiveTypeToIrType[type]!!.classOrNull!!) + } + numberConversionMethods(irBuiltIns.numberClass) + + private fun arrayMethods(): List> = + symbols.primitiveArrays.values.flatMap { arrayMethods(it) } + arrayMethods(symbols.array) + + 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 EQUALS = Equals(KtTokens.EQEQ) + + private fun IrFunctionSymbol.toKey(): Key? { + return Key( + owner.parent.safeAs()?.fqNameWhenAvailable ?: owner.parent.safeAs()?.fqName ?: return null, + getParameterFqName(owner.extensionReceiverParameter), + owner.name.asString(), + owner.valueParameters.map(::getParameterFqName) + ) + } + + private fun getParameterFqName(parameter: IrValueParameter?): FqName? = + parameter?.type?.safeAs()?.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> = + 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, operator: KtSingleValueToken) = + typeToIrFun.map { (type, irFunSymbol) -> + irFunSymbol.toKey()!! to PrimitiveComparison(type, operator) + } } private object OperatorNames { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrNoWhenBranchMatchedException.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrNoWhenBranchMatchedException.kt index 767649141e2..f2b3e357de1 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrNoWhenBranchMatchedException.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrNoWhenBranchMatchedException.kt @@ -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) } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IsArrayOf.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IsArrayOf.kt index a09537d55ee..ece6fb90f19 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IsArrayOf.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IsArrayOf.kt @@ -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 diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IteratorNext.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IteratorNext.kt index 4b5eb8f8b4a..914c40aee2d 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IteratorNext.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IteratorNext.kt @@ -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) } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/KClassJavaProperty.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/KClassJavaProperty.kt index 7eb80c7f43c..edd2d1c5693 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/KClassJavaProperty.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/KClassJavaProperty.kt @@ -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) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/MonitorInstruction.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/MonitorInstruction.kt index 0089cb56045..ffcdaaadf77 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/MonitorInstruction.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/MonitorInstruction.kt @@ -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) } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/NewArray.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/NewArray.kt index 54e3e7bf3f6..21c46bab763 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/NewArray.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/NewArray.kt @@ -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 { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Not.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Not.kt index a1e567c4746..ed8ea0148ec 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Not.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Not.kt @@ -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) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/NumberCast.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/NumberCast.kt index d9edb664d17..9bf50c624b1 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/NumberCast.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/NumberCast.kt @@ -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) } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/RangeTo.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/RangeTo.kt index c5e05fe99b9..abf50a13f36 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/RangeTo.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/RangeTo.kt @@ -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) { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/StringGetChar.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/StringGetChar.kt index 4438e29ba14..73f772e2a08 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/StringGetChar.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/StringGetChar.kt @@ -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) } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ThrowNPE.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ThrowNPE.kt index 4d96ec95412..a3f39b99e06 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ThrowNPE.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ThrowNPE.kt @@ -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 { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ToString.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ToString.kt index dd82c12d63d..216202ecf14 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ToString.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ToString.kt @@ -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) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/UnaryMinus.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/UnaryMinus.kt index 03855e2c4d4..fecf1ffd591 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/UnaryMinus.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/UnaryMinus.kt @@ -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)) } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/UnaryPlus.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/UnaryPlus.kt index 49ac6d4802a..499b25c58fb 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/UnaryPlus.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/UnaryPlus.kt @@ -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) { } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/AnnotationLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/AnnotationLowering.kt index 70921d06ba7..4fe97abf8e9 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/AnnotationLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/AnnotationLowering.kt @@ -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 = diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt index 0ccd7e29329..0f40507822e 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt @@ -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)