IR: mostly remove descriptors from codegen
This commit is contained in:
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
|
||||
internal fun visitAnnotableParameterCount(mv: MethodVisitor, paramCount: Int) {
|
||||
fun visitAnnotableParameterCount(mv: MethodVisitor, paramCount: Int) {
|
||||
mv.visitAnnotableParameterCount(paramCount, true)
|
||||
mv.visitAnnotableParameterCount(paramCount, false)
|
||||
}
|
||||
@@ -7,4 +7,4 @@ package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
|
||||
internal fun visitAnnotableParameterCount(mv: MethodVisitor, paramCount: Int) {}
|
||||
fun visitAnnotableParameterCount(mv: MethodVisitor, paramCount: Int) {}
|
||||
+1
-2
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.backend.common.ir.*
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
@@ -160,7 +159,7 @@ open class DefaultArgumentStubGenerator(
|
||||
newIrFunction: IrFunction,
|
||||
params: MutableList<IrVariable>
|
||||
): IrExpression {
|
||||
val dispatchCall = irCall(irFunction).apply {
|
||||
val dispatchCall = irCall(irFunction.symbol).apply {
|
||||
passTypeArgumentsFrom(newIrFunction)
|
||||
dispatchReceiver = newIrFunction.dispatchReceiverParameter?.let { irGet(it) }
|
||||
extensionReceiver = newIrFunction.extensionReceiverParameter?.let { irGet(it) }
|
||||
|
||||
@@ -11,9 +11,12 @@ import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrPackageFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
@@ -89,3 +92,30 @@ fun IrType.getPrimitiveArrayElementType() = (this as? IrSimpleType)?.let {
|
||||
|
||||
fun IrType.isNonPrimitiveArray() =
|
||||
(this.isArray() || this.isNullableArray()) && !this.isPrimitiveArray()
|
||||
|
||||
|
||||
fun IrType.substitute(params: List<IrTypeParameter>, arguments: List<IrType>): IrType =
|
||||
substitute(params.map { it.symbol }.zip(arguments).toMap())
|
||||
|
||||
|
||||
fun IrType.substitute(substitutionMap: Map<IrTypeParameterSymbol, IrType>): IrType {
|
||||
if (this !is IrSimpleType) return this
|
||||
|
||||
substitutionMap[classifier]?.let { return it }
|
||||
|
||||
val newArguments = arguments.map {
|
||||
if (it is IrTypeProjection) {
|
||||
makeTypeProjection(it.type.substitute(substitutionMap), it.variance)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
|
||||
val newAnnotations = annotations.map { it.deepCopyWithSymbols() }
|
||||
return IrSimpleTypeImpl(
|
||||
classifier,
|
||||
hasQuestionMark,
|
||||
newArguments,
|
||||
newAnnotations
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,27 +6,23 @@
|
||||
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
|
||||
@@ -53,10 +49,7 @@ 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 =
|
||||
@@ -261,47 +254,4 @@ 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
|
||||
)
|
||||
}
|
||||
|
||||
+2
-2
@@ -107,7 +107,7 @@ class AnnotationCodegen(
|
||||
if (declaration is IrValueParameter && isInvisibleFromTheOutside(declaration.parent as? IrDeclaration)) return
|
||||
|
||||
// No need to annotate annotation methods since they're always non-null
|
||||
if (declaration is IrSimpleFunction && declaration.correspondingProperty != null &&
|
||||
if (declaration is IrSimpleFunction && declaration.correspondingPropertySymbol != null &&
|
||||
declaration.parentAsClass.isAnnotationClass
|
||||
) {
|
||||
return
|
||||
@@ -276,7 +276,7 @@ class AnnotationCodegen(
|
||||
}
|
||||
|
||||
interface InnerClassConsumer {
|
||||
fun addInnerClassInfoFromAnnotation(irClass: IrClass)
|
||||
fun addInnerClassInfoFromAnnotation(innerClass: IrClass)
|
||||
}
|
||||
|
||||
private fun isBareTypeParameterWithNullableUpperBound(type: IrType): Boolean {
|
||||
|
||||
+49
-42
@@ -20,28 +20,27 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.constantValue
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding.ASM_TYPE
|
||||
import org.jetbrains.kotlin.codegen.inline.DefaultSourceMapper
|
||||
import org.jetbrains.kotlin.codegen.inline.SourceMapper
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings
|
||||
import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.isTopLevelDeclaration
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
import org.jetbrains.kotlin.serialization.DescriptorSerializer
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import java.io.File
|
||||
@@ -52,20 +51,19 @@ open class ClassCodegen protected constructor(
|
||||
private val parentClassCodegen: ClassCodegen? = null
|
||||
) : InnerClassConsumer {
|
||||
|
||||
private val innerClasses = mutableListOf<ClassDescriptor>()
|
||||
private val innerClasses = mutableListOf<IrClass>()
|
||||
|
||||
val state = context.state
|
||||
|
||||
val typeMapper = context.state.typeMapper
|
||||
val typeMapper = IrTypeMapper(context.state.typeMapper)
|
||||
|
||||
val descriptor = irClass.descriptor
|
||||
|
||||
private val isAnonymous = DescriptorUtils.isAnonymousObject(irClass.descriptor)
|
||||
private val isAnonymous = irClass.isAnonymousObject
|
||||
|
||||
val type: Type = if (isAnonymous) CodegenBinding.asmTypeForAnonymousClass(
|
||||
state.bindingContext,
|
||||
descriptor.source.getPsi() as KtElement
|
||||
) else typeMapper.mapType(descriptor)
|
||||
val type: Type = if (isAnonymous)
|
||||
state.bindingContext.get(ASM_TYPE, descriptor)!!
|
||||
else typeMapper.mapType(irClass)
|
||||
|
||||
private val sourceManager = context.psiSourceManager
|
||||
|
||||
@@ -78,7 +76,7 @@ open class ClassCodegen protected constructor(
|
||||
open fun createClassBuilder() = state.factory.newVisitor(
|
||||
OtherOrigin(psiElement, descriptor),
|
||||
type,
|
||||
psiElement?.containingFile?.let { setOf(it) } ?: emptySet()
|
||||
listOf(File(fileEntry.name))
|
||||
)
|
||||
|
||||
private var sourceMapper: DefaultSourceMapper? = null
|
||||
@@ -92,8 +90,8 @@ open class ClassCodegen protected constructor(
|
||||
}
|
||||
|
||||
fun generate() {
|
||||
val superClassInfo = SuperClassInfo.getSuperClassInfo(descriptor, typeMapper)
|
||||
val signature = ImplementationBodyCodegen.signature(descriptor, type, superClassInfo, typeMapper)
|
||||
val superClassInfo = irClass.getSuperClassInfo(typeMapper)
|
||||
val signature = getSignature(irClass, type, superClassInfo, typeMapper)
|
||||
|
||||
visitor.defineClass(
|
||||
psiElement,
|
||||
@@ -170,22 +168,16 @@ open class ClassCodegen protected constructor(
|
||||
|
||||
companion object {
|
||||
fun generate(irClass: IrClass, context: JvmBackendContext) {
|
||||
val descriptor = irClass.descriptor
|
||||
val state = context.state
|
||||
|
||||
if (ErrorUtils.isError(descriptor)) {
|
||||
badDescriptor(irClass, state.classBuilderMode)
|
||||
return
|
||||
}
|
||||
|
||||
if (irClass.name == SpecialNames.NO_NAME_PROVIDED) {
|
||||
badDescriptor(irClass, state.classBuilderMode)
|
||||
badClass(irClass, state.classBuilderMode)
|
||||
}
|
||||
|
||||
ClassCodegen(irClass, context).generate()
|
||||
}
|
||||
|
||||
private fun badDescriptor(irClass: IrClass, mode: ClassBuilderMode) {
|
||||
private fun badClass(irClass: IrClass, mode: ClassBuilderMode) {
|
||||
if (mode.generateBodies) {
|
||||
throw IllegalStateException("Generating bad class in ClassBuilderMode = $mode: ${irClass.dump()}")
|
||||
}
|
||||
@@ -216,9 +208,9 @@ open class ClassCodegen protected constructor(
|
||||
private fun generateField(field: IrField, companionObjectCodegen: ClassCodegen?) {
|
||||
if (field.origin == IrDeclarationOrigin.FAKE_OVERRIDE) return
|
||||
|
||||
val fieldType = typeMapper.mapType(field.descriptor)
|
||||
val fieldSignature = typeMapper.mapFieldSignature(field.descriptor.type, field.descriptor)
|
||||
val fieldName = field.descriptor.name.asString()
|
||||
val fieldType = typeMapper.mapType(field)
|
||||
val fieldSignature = typeMapper.mapFieldSignature(field.type, field)
|
||||
val fieldName = field.name.asString()
|
||||
// The ConstantValue attribute makes the initializer part of the ABI, which is why since 1.4
|
||||
// it is no longer set unless the property is explicitly `const`.
|
||||
val implicitConst = !state.languageVersionSettings.supportsFeature(LanguageFeature.NoConstantValueAttributeForNonConstVals) &&
|
||||
@@ -274,13 +266,13 @@ open class ClassCodegen protected constructor(
|
||||
private fun writeInnerClasses() {
|
||||
// JVMS7 (4.7.6): a nested class or interface member will have InnerClasses information
|
||||
// for each enclosing class and for each immediate member
|
||||
val classDescriptor = classForInnerClassRecord()
|
||||
if (classDescriptor != null) {
|
||||
parentClassCodegen?.innerClasses?.add(classDescriptor)
|
||||
val classForInnerClassRecord = getClassForInnerClassRecord()
|
||||
if (classForInnerClassRecord != null) {
|
||||
parentClassCodegen?.innerClasses?.add(classForInnerClassRecord)
|
||||
|
||||
var codegen: ClassCodegen? = this
|
||||
while (codegen != null) {
|
||||
val outerClass = codegen.classForInnerClassRecord()
|
||||
val outerClass = codegen.getClassForInnerClassRecord()
|
||||
if (outerClass != null) {
|
||||
innerClasses.add(outerClass)
|
||||
}
|
||||
@@ -289,23 +281,23 @@ open class ClassCodegen protected constructor(
|
||||
}
|
||||
|
||||
for (innerClass in innerClasses) {
|
||||
MemberCodegen.writeInnerClass(innerClass, typeMapper, visitor)
|
||||
writeInnerClass(innerClass, typeMapper, context, visitor)
|
||||
}
|
||||
}
|
||||
|
||||
private fun classForInnerClassRecord(): ClassDescriptor? {
|
||||
return if (parentClassCodegen != null) descriptor else null
|
||||
private fun getClassForInnerClassRecord(): IrClass? {
|
||||
return if (parentClassCodegen != null) irClass else null
|
||||
}
|
||||
|
||||
// It's necessary for proper recovering of classId by plain string JVM descriptor when loading annotations
|
||||
// See FileBasedKotlinClass.convertAnnotationVisitor
|
||||
override fun addInnerClassInfoFromAnnotation(irClass: IrClass) {
|
||||
var current: DeclarationDescriptor? = irClass.descriptor
|
||||
while (current != null && !isTopLevelDeclaration(current)) {
|
||||
if (current is ClassDescriptor) {
|
||||
override fun addInnerClassInfoFromAnnotation(innerClass: IrClass) {
|
||||
var current: IrDeclaration? = innerClass
|
||||
while (current != null) {
|
||||
if (current is IrClass) {
|
||||
innerClasses.add(current)
|
||||
}
|
||||
current = current.containingDeclaration
|
||||
current = current.parent as? IrDeclaration
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,7 +315,7 @@ open class ClassCodegen protected constructor(
|
||||
// in the source.
|
||||
val containingDeclaration = irClass.symbol.owner.parent
|
||||
if (containingDeclaration is IrFunction) {
|
||||
val method = typeMapper.mapAsmMethod(containingDeclaration.descriptor)
|
||||
val method = typeMapper.mapAsmMethod(containingDeclaration)
|
||||
visitor.visitOuterClass(outerClassName, method.name, method.descriptor)
|
||||
} else {
|
||||
visitor.visitOuterClass(outerClassName, null, null)
|
||||
@@ -340,7 +332,7 @@ open class ClassCodegen protected constructor(
|
||||
}
|
||||
|
||||
private val IrClass.flags: Int
|
||||
get() = origin.flags or AsmUtil.getVisibilityAccessFlagForClass(descriptor) or when {
|
||||
get() = origin.flags or getVisibilityAccessFlagForClass() or when {
|
||||
isAnnotationClass -> Opcodes.ACC_ANNOTATION or Opcodes.ACC_INTERFACE or Opcodes.ACC_ABSTRACT
|
||||
isInterface -> Opcodes.ACC_INTERFACE or Opcodes.ACC_ABSTRACT
|
||||
isEnumClass -> Opcodes.ACC_ENUM or Opcodes.ACC_SUPER or modality.flags
|
||||
@@ -372,3 +364,18 @@ private val IrField.OtherOrigin: JvmDeclarationOrigin
|
||||
|
||||
internal val IrFunction.OtherOrigin: JvmDeclarationOrigin
|
||||
get() = OtherOrigin(descriptor.psiElement, this.descriptor)
|
||||
|
||||
private fun IrClass.getSuperClassInfo(typeMapper: IrTypeMapper): IrSuperClassInfo {
|
||||
if (isInterface) {
|
||||
return IrSuperClassInfo(AsmTypes.OBJECT_TYPE, null)
|
||||
}
|
||||
|
||||
for (superType in superTypes) {
|
||||
val superClass = superType.safeAs<IrSimpleType>()?.classifier?.safeAs<IrClassSymbol>()?.owner
|
||||
if (superClass != null && !superClass.isJvmInterface) {
|
||||
return IrSuperClassInfo(typeMapper.mapClass(superClass), superType)
|
||||
}
|
||||
}
|
||||
|
||||
return IrSuperClassInfo(AsmTypes.OBJECT_TYPE, null)
|
||||
}
|
||||
+247
-133
@@ -5,17 +5,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.codegen
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.propertyIfAccessor
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.intrinsics.IntrinsicMethods
|
||||
import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicMethods
|
||||
import org.jetbrains.kotlin.backend.jvm.intrinsics.JavaClassProperty
|
||||
import org.jetbrains.kotlin.backend.jvm.intrinsics.Not
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.CrIrType
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.constantValue
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil.*
|
||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen.putReifiedOperationMarkerIfTypeIsReifiedParameter
|
||||
import org.jetbrains.kotlin.codegen.inline.*
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.OperationKind.AS
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.OperationKind.SAFE_AS
|
||||
@@ -25,27 +22,22 @@ import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.config.isReleaseCoroutines
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumClass
|
||||
import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
|
||||
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.typeUtil.isNothing
|
||||
import org.jetbrains.kotlin.types.typesApproximation.approximateCapturedTypes
|
||||
import org.jetbrains.kotlin.types.upperIfFlexible
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.kotlin.utils.keysToMap
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
@@ -125,18 +117,15 @@ class ExpressionCodegen(
|
||||
|
||||
override var lastLineNumber: Int = -1
|
||||
|
||||
private val KotlinType.asmType: Type
|
||||
get() = typeMapper.mapType(this)
|
||||
|
||||
private val IrType.asmType: Type
|
||||
get() = toKotlinType().asmType
|
||||
|
||||
private val CallableDescriptor.asmType: Type
|
||||
get() = typeMapper.mapType(this)
|
||||
|
||||
val IrExpression.asmType: Type
|
||||
get() = type.asmType
|
||||
|
||||
val IrVariable.asmType: Type
|
||||
get() = type.asmType
|
||||
|
||||
// Assume this expression's result has already been materialized on the stack
|
||||
// with the correct type.
|
||||
val IrExpression.onStack: MaterialValue
|
||||
@@ -178,7 +167,7 @@ class ExpressionCodegen(
|
||||
if (irFunction.origin != JvmLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER) {
|
||||
irFunction.markLineNumber(startOffset = irFunction is IrConstructor && irFunction.isPrimary)
|
||||
}
|
||||
val returnType = typeMapper.mapReturnType(irFunction.descriptor)
|
||||
val returnType = typeMapper.mapReturnType(irFunction)
|
||||
result.coerce(returnType).materialize()
|
||||
mv.areturn(returnType)
|
||||
}
|
||||
@@ -201,18 +190,15 @@ class ExpressionCodegen(
|
||||
}
|
||||
|
||||
private fun writeValueParameterInLocalVariableTable(param: IrValueParameter, startLabel: Label) {
|
||||
val descriptor = param.descriptor
|
||||
val nameForDestructuredParameter = if (descriptor is ValueParameterDescriptor) {
|
||||
getNameForDestructuredParameterOrNull(descriptor)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
// TODO: old code has a special treatment for destructuring lambda parameters.
|
||||
// There is no (easy) way to reproduce it with IR structures.
|
||||
// Does not show up in tests, but might come to bite us at some point.
|
||||
val name = param.name.asString()
|
||||
|
||||
val type = typeMapper.mapType(descriptor)
|
||||
val type = typeMapper.mapType(param)
|
||||
// NOTE: we expect all value parameters to be present in the frame.
|
||||
mv.visitLocalVariable(
|
||||
nameForDestructuredParameter ?: param.name.asString(),
|
||||
type.descriptor, null, startLabel, markNewLabel(), findLocalIndex(param.symbol)
|
||||
name, type.descriptor, null, startLabel, markNewLabel(), findLocalIndex(param.symbol)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -268,10 +254,10 @@ class ExpressionCodegen(
|
||||
|
||||
override fun visitCall(expression: IrCall, data: BlockInfo): PromisedValue {
|
||||
expression.markLineNumber(startOffset = true)
|
||||
if (expression.descriptor is ConstructorDescriptor) {
|
||||
if (expression.symbol.owner is IrConstructor) {
|
||||
throw AssertionError("IrCall with ConstructorDescriptor: ${expression.javaClass.simpleName}")
|
||||
}
|
||||
return generateCall(expression, expression.superQualifier, data)
|
||||
return generateCall(expression, expression.superQualifierSymbol, data)
|
||||
}
|
||||
|
||||
override fun visitConstructorCall(expression: IrConstructorCall, data: BlockInfo): PromisedValue {
|
||||
@@ -287,35 +273,36 @@ class ExpressionCodegen(
|
||||
return expression.onStack
|
||||
}
|
||||
|
||||
fun generateNewArray(expression: IrConstructorCall, data: BlockInfo): PromisedValue {
|
||||
val args = expression.descriptor.valueParameters
|
||||
private fun generateNewArray(expression: IrConstructorCall, data: BlockInfo): PromisedValue {
|
||||
val args = expression.symbol.owner.valueParameters
|
||||
assert(args.size == 1 || args.size == 2) { "Unknown constructor called: " + args.size + " arguments" }
|
||||
|
||||
if (args.size == 1) {
|
||||
// TODO move to the intrinsic
|
||||
expression.getValueArgument(0)!!.accept(this, data).coerce(Type.INT_TYPE).materialize()
|
||||
newArrayInstruction(expression.type.toKotlinType())
|
||||
newArrayInstruction(expression.type)
|
||||
return expression.onStack
|
||||
}
|
||||
|
||||
return generateCall(expression, null, data)
|
||||
}
|
||||
|
||||
private fun generateCall(expression: IrFunctionAccessExpression, superQualifier: ClassDescriptor?, data: BlockInfo): PromisedValue {
|
||||
private fun generateCall(expression: IrFunctionAccessExpression, superQualifierSymbol: IrClassSymbol?, data: BlockInfo): PromisedValue {
|
||||
classCodegen.context.irIntrinsics.getIntrinsic(expression.symbol)
|
||||
?.invoke(expression, this, data)?.let { return it.coerce(expression.asmType) }
|
||||
val isSuperCall = superQualifier != null
|
||||
val isSuperCall = superQualifierSymbol != null
|
||||
val callable = resolveToCallable(expression, isSuperCall)
|
||||
return generateCall(expression, callable, data, isSuperCall)
|
||||
}
|
||||
|
||||
fun generateCall(
|
||||
expression: IrMemberAccessExpression,
|
||||
expression: IrFunctionAccessExpression,
|
||||
callable: Callable,
|
||||
data: BlockInfo,
|
||||
isSuperCall: Boolean = false
|
||||
): PromisedValue {
|
||||
val callGenerator = getOrCreateCallGenerator(expression, expression.descriptor, data)
|
||||
val callee = expression.symbol.owner
|
||||
val callGenerator = getOrCreateCallGenerator(expression, data)
|
||||
|
||||
val receiver = expression.dispatchReceiver
|
||||
receiver?.apply {
|
||||
@@ -335,19 +322,24 @@ class ExpressionCodegen(
|
||||
val defaultMask = DefaultCallArgs(callable.valueParameterTypes.size)
|
||||
val extraArgsShift =
|
||||
when {
|
||||
expression.descriptor is ConstructorDescriptor && isEnumClass(expression.descriptor.containingDeclaration) -> 2
|
||||
expression.descriptor is ConstructorDescriptor &&
|
||||
(expression.descriptor.containingDeclaration as ClassDescriptor).isInner -> 1 // skip the `$outer` parameter
|
||||
callee is IrConstructor && callee.parentAsClass.isEnumClass -> 2
|
||||
callee is IrConstructor && callee.parentAsClass.isInner -> 1 // skip the `$outer` parameter
|
||||
else -> 0
|
||||
}
|
||||
expression.descriptor.valueParameters.forEachIndexed { i, parameterDescriptor ->
|
||||
val typeParameters = if (callee is IrConstructor)
|
||||
callee.parentAsClass.typeParameters + callee.typeParameters
|
||||
else
|
||||
callee.typeParameters
|
||||
val typeArguments = (0 until typeParameters.size).map { expression.getTypeArgument(it)!! }
|
||||
val typeSubstitutionMap = typeParameters.map { it.symbol }.zip(typeArguments).toMap()
|
||||
expression.symbol.owner.valueParameters.forEachIndexed { i, irParameter ->
|
||||
val arg = expression.getValueArgument(i)
|
||||
val parameterType = callable.valueParameterTypes[i]
|
||||
when {
|
||||
arg != null -> {
|
||||
callGenerator.genValueAndPut(parameterDescriptor, arg, parameterType, i, this@ExpressionCodegen, data)
|
||||
callGenerator.genValueAndPut(irParameter, arg, parameterType, i, this@ExpressionCodegen, data)
|
||||
}
|
||||
parameterDescriptor.hasDefaultValue() -> {
|
||||
irParameter.hasDefaultValue() -> {
|
||||
callGenerator.putValueIfNeeded(
|
||||
parameterType,
|
||||
StackValue.createDefaultValue(parameterType),
|
||||
@@ -358,12 +350,10 @@ class ExpressionCodegen(
|
||||
defaultMask.mark(i - extraArgsShift/*TODO switch to separate lower*/)
|
||||
}
|
||||
else -> {
|
||||
assert(parameterDescriptor.varargElementType != null)
|
||||
//empty vararg
|
||||
|
||||
// Upper bound for type of vararg parameter should always have a form of 'Array<out T>',
|
||||
// while its lower bound may be Nothing-typed after approximation
|
||||
val type = typeMapper.mapType(parameterDescriptor.type.upperIfFlexible())
|
||||
assert(irParameter.varargElementType != null)
|
||||
val type = typeMapper.mapType(
|
||||
irParameter.type.substitute(typeSubstitutionMap)
|
||||
)
|
||||
callGenerator.putValueIfNeeded(
|
||||
parameterType,
|
||||
StackValue.operation(type) {
|
||||
@@ -378,17 +368,17 @@ class ExpressionCodegen(
|
||||
|
||||
callGenerator.genCall(
|
||||
callable,
|
||||
defaultMask.generateOnStackIfNeeded(callGenerator, expression.descriptor is ConstructorDescriptor, this),
|
||||
defaultMask.generateOnStackIfNeeded(callGenerator, callee is IrConstructor, this),
|
||||
this,
|
||||
expression
|
||||
)
|
||||
|
||||
val returnType = expression.descriptor.returnType
|
||||
if (returnType != null && returnType.isNothing()) {
|
||||
val returnType = callee.returnType.substitute(typeSubstitutionMap)
|
||||
if (returnType.isNothing()) {
|
||||
mv.aconst(null)
|
||||
mv.athrow()
|
||||
return voidValue
|
||||
} else if (expression.descriptor is ConstructorDescriptor) {
|
||||
} else if (callee is IrConstructor) {
|
||||
return voidValue
|
||||
} else if (expression.type.isUnit()) {
|
||||
// NewInference allows casting `() -> T` to `() -> Unit`. A CHECKCAST here will fail.
|
||||
@@ -398,7 +388,7 @@ class ExpressionCodegen(
|
||||
}
|
||||
|
||||
override fun visitVariable(declaration: IrVariable, data: BlockInfo): PromisedValue {
|
||||
val varType = typeMapper.mapType(declaration.descriptor)
|
||||
val varType = typeMapper.mapType(declaration)
|
||||
val index = frameMap.enter(declaration.symbol, varType)
|
||||
|
||||
declaration.markLineNumber(startOffset = true)
|
||||
@@ -431,10 +421,10 @@ class ExpressionCodegen(
|
||||
return voidValue.coerce(expression.asmType)
|
||||
}
|
||||
|
||||
val realDescriptor = DescriptorUtils.unwrapFakeOverride(expression.descriptor)
|
||||
val fieldType = typeMapper.mapType(realDescriptor.original.type)
|
||||
val ownerType = typeMapper.mapImplementationOwner(expression.descriptor).internalName
|
||||
val fieldName = expression.descriptor.name.asString()
|
||||
val realField = expression.symbol.owner.resolveFakeOverride()!!
|
||||
val fieldType = typeMapper.mapType(realField.type)
|
||||
val ownerType = typeMapper.mapImplementationOwner(expression.symbol.owner).internalName
|
||||
val fieldName = realField.name.asString()
|
||||
val isStatic = expression.receiver == null
|
||||
expression.markLineNumber(startOffset = true)
|
||||
expression.receiver?.accept(this, data)?.materialize()
|
||||
@@ -497,8 +487,8 @@ class ExpressionCodegen(
|
||||
override fun visitSetVariable(expression: IrSetVariable, data: BlockInfo): PromisedValue {
|
||||
expression.markLineNumber(startOffset = true)
|
||||
expression.value.markLineNumber(startOffset = true)
|
||||
expression.value.accept(this, data).coerce(expression.descriptor.asmType).materialize()
|
||||
mv.store(findLocalIndex(expression.symbol), expression.descriptor.asmType)
|
||||
expression.value.accept(this, data).coerce(expression.symbol.owner.asmType).materialize()
|
||||
mv.store(findLocalIndex(expression.symbol), expression.symbol.owner.asmType)
|
||||
return voidValue.coerce(expression.asmType)
|
||||
}
|
||||
|
||||
@@ -547,7 +537,7 @@ class ExpressionCodegen(
|
||||
val hasSpread = arguments.firstIsInstanceOrNull<IrSpreadElement>() != null
|
||||
|
||||
if (hasSpread) {
|
||||
val arrayOfReferences = KotlinBuiltIns.isArray(outType.toKotlinType())
|
||||
val arrayOfReferences = outType.makeNotNull().isArray()
|
||||
if (size == 1) {
|
||||
// Arrays.copyOf(receiverValue, newLength)
|
||||
val argument = (arguments[0] as IrSpreadElement).expression
|
||||
@@ -595,7 +585,7 @@ class ExpressionCodegen(
|
||||
if (arrayOfReferences) {
|
||||
mv.dup()
|
||||
mv.invokevirtual(owner, "size", "()I", false)
|
||||
newArrayInstruction(outType.toKotlinType())
|
||||
newArrayInstruction(outType)
|
||||
mv.invokevirtual(owner, "toArray", toArrayDescriptor, false)
|
||||
mv.checkcast(type)
|
||||
} else {
|
||||
@@ -604,7 +594,7 @@ class ExpressionCodegen(
|
||||
}
|
||||
} else {
|
||||
mv.iconst(size)
|
||||
newArrayInstruction(expression.type.toKotlinType())
|
||||
newArrayInstruction(expression.type)
|
||||
for ((i, element) in expression.elements.withIndex()) {
|
||||
mv.dup()
|
||||
mv.iconst(i)
|
||||
@@ -615,16 +605,16 @@ class ExpressionCodegen(
|
||||
return expression.onStack
|
||||
}
|
||||
|
||||
fun newArrayInstruction(arrayType: KotlinType) {
|
||||
if (KotlinBuiltIns.isArray(arrayType)) {
|
||||
val elementKotlinType = arrayType.arguments[0].type
|
||||
fun newArrayInstruction(arrayType: IrType) {
|
||||
if (arrayType.isArray()) {
|
||||
val elementIrType = arrayType.safeAs<IrSimpleType>()!!.arguments[0].safeAs<IrTypeProjection>()!!.type
|
||||
putReifiedOperationMarkerIfTypeIsReifiedParameter(
|
||||
elementKotlinType,
|
||||
elementIrType,
|
||||
ReifiedTypeInliner.OperationKind.NEW_ARRAY,
|
||||
mv,
|
||||
this
|
||||
)
|
||||
mv.newarray(boxType(elementKotlinType.asmType))
|
||||
mv.newarray(boxType(elementIrType.asmType))
|
||||
} else {
|
||||
val type = typeMapper.mapType(arrayType)
|
||||
mv.newarray(correctElementType(type))
|
||||
@@ -634,10 +624,8 @@ class ExpressionCodegen(
|
||||
override fun visitReturn(expression: IrReturn, data: BlockInfo): PromisedValue {
|
||||
val owner = expression.returnTargetSymbol.owner
|
||||
//TODO: should be owner != irFunction
|
||||
val isNonLocalReturn = state.typeMapper.mapFunctionName(
|
||||
owner.descriptor,
|
||||
OwnerKind.IMPLEMENTATION
|
||||
) != state.typeMapper.mapFunctionName(irFunction.descriptor, OwnerKind.IMPLEMENTATION)
|
||||
val isNonLocalReturn =
|
||||
typeMapper.mapFunctionName(owner, OwnerKind.IMPLEMENTATION) != typeMapper.mapFunctionName(irFunction, OwnerKind.IMPLEMENTATION)
|
||||
if (isNonLocalReturn && state.isInlineDisabled) {
|
||||
//TODO: state.diagnostics.report(Errors.NON_LOCAL_RETURN_IN_DISABLED_INLINE.on(expression))
|
||||
genThrow(
|
||||
@@ -647,7 +635,7 @@ class ExpressionCodegen(
|
||||
return voidValue
|
||||
}
|
||||
|
||||
val returnType = typeMapper.mapReturnType(owner.descriptor)
|
||||
val returnType = typeMapper.mapReturnType(owner)
|
||||
val afterReturnLabel = Label()
|
||||
expression.value.accept(this, data).coerce(returnType).materialize()
|
||||
generateFinallyBlocksIfNeeded(returnType, afterReturnLabel, data)
|
||||
@@ -697,8 +685,9 @@ class ExpressionCodegen(
|
||||
}
|
||||
|
||||
override fun visitTypeOperator(expression: IrTypeOperatorCall, data: BlockInfo): PromisedValue {
|
||||
val kotlinType = expression.typeOperand.toKotlinType()
|
||||
val asmType = kotlinType.asmType
|
||||
val typeOperand = expression.typeOperand
|
||||
val asmType = typeOperand.asmType
|
||||
val kotlinType = typeOperand.toKotlinType()
|
||||
return when (expression.operator) {
|
||||
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT -> {
|
||||
expression.argument.accept(this, data).discard()
|
||||
@@ -714,9 +703,9 @@ class ExpressionCodegen(
|
||||
expression.argument.accept(this, data).coerce(AsmTypes.OBJECT_TYPE).materialize()
|
||||
val boxedType = boxType(asmType)
|
||||
|
||||
if (TypeUtils.isReifiedTypeParameter(kotlinType)) {
|
||||
if (typeOperand.isReifiedTypeParameter) {
|
||||
putReifiedOperationMarkerIfTypeIsReifiedParameter(
|
||||
kotlinType, if (IrTypeOperator.SAFE_CAST == expression.operator) SAFE_AS else AS, mv, this
|
||||
typeOperand, if (IrTypeOperator.SAFE_CAST == expression.operator) SAFE_AS else AS, mv, this
|
||||
)
|
||||
v.checkcast(boxedType)
|
||||
} else {
|
||||
@@ -731,8 +720,8 @@ class ExpressionCodegen(
|
||||
IrTypeOperator.INSTANCEOF, IrTypeOperator.NOT_INSTANCEOF -> {
|
||||
expression.argument.accept(this, data).coerce(AsmTypes.OBJECT_TYPE).materialize()
|
||||
val type = boxType(asmType)
|
||||
if (TypeUtils.isReifiedTypeParameter(kotlinType)) {
|
||||
putReifiedOperationMarkerIfTypeIsReifiedParameter(kotlinType, ReifiedTypeInliner.OperationKind.IS, mv, this)
|
||||
if (typeOperand.isReifiedTypeParameter) {
|
||||
putReifiedOperationMarkerIfTypeIsReifiedParameter(typeOperand, ReifiedTypeInliner.OperationKind.IS, mv, this)
|
||||
v.instanceOf(type)
|
||||
} else {
|
||||
generateIsCheck(mv, kotlinType, type, state.languageVersionSettings.isReleaseCoroutines())
|
||||
@@ -782,17 +771,17 @@ class ExpressionCodegen(
|
||||
// Convert single arg to string.
|
||||
val type = expression.arguments[0].accept(this, data).materialized.type
|
||||
if (!expression.arguments[0].type.isString())
|
||||
AsmUtil.genToString(StackValue.onStack(type), type, null, typeMapper).put(expression.asmType, mv)
|
||||
AsmUtil.genToString(StackValue.onStack(type), type, null, typeMapper.kotlinTypeMapper).put(expression.asmType, mv)
|
||||
}
|
||||
arity == 2 && expression.arguments[0].type.isStringClassType() -> {
|
||||
// Call the stringPlus intrinsic
|
||||
expression.arguments.forEach {
|
||||
val type = it.accept(this, data).materialized.type
|
||||
if (type.sort != Type.OBJECT)
|
||||
AsmUtil.genToString(StackValue.onStack(type), type, null, typeMapper).put(expression.asmType, mv)
|
||||
AsmUtil.genToString(StackValue.onStack(type), type, null, typeMapper.kotlinTypeMapper).put(expression.asmType, mv)
|
||||
}
|
||||
mv.invokestatic(
|
||||
IntrinsicMethods.INTRINSICS_CLASS_NAME,
|
||||
IrIntrinsicMethods.INTRINSICS_CLASS_NAME,
|
||||
"stringPlus",
|
||||
"(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;",
|
||||
false
|
||||
@@ -897,8 +886,8 @@ class ExpressionCodegen(
|
||||
val catches = aTry.catches
|
||||
for (clause in catches) {
|
||||
val clauseStart = markNewLabel()
|
||||
val descriptor = clause.parameter
|
||||
val descriptorType = descriptor.asmType
|
||||
val parameter = clause.catchParameter
|
||||
val descriptorType = parameter.asmType
|
||||
val index = frameMap.enter(clause.catchParameter, descriptorType)
|
||||
mv.store(index, descriptorType)
|
||||
|
||||
@@ -917,7 +906,7 @@ class ExpressionCodegen(
|
||||
val clauseEnd = markNewLabel()
|
||||
|
||||
mv.visitLocalVariable(
|
||||
descriptor.name.asString(), descriptorType.descriptor, null, clauseStart, clauseEnd,
|
||||
parameter.name.asString(), descriptorType.descriptor, null, clauseStart, clauseEnd,
|
||||
index
|
||||
)
|
||||
|
||||
@@ -1025,16 +1014,17 @@ class ExpressionCodegen(
|
||||
} else if (classReference is IrClassReference) {
|
||||
val classType = classReference.classType
|
||||
if (classType is CrIrType) {
|
||||
putJavaLangClassInstance(mv, classType.type, null, typeMapper)
|
||||
putJavaLangClassInstance(mv, classType.type, null, typeMapper.kotlinTypeMapper)
|
||||
return classReference.onStack
|
||||
} else {
|
||||
val kotlinType = classType.toKotlinType()
|
||||
if (TypeUtils.isTypeParameter(kotlinType)) {
|
||||
assert(TypeUtils.isReifiedTypeParameter(kotlinType)) { "Non-reified type parameter under ::class should be rejected by type checker: " + kotlinType }
|
||||
putReifiedOperationMarkerIfTypeIsReifiedParameter(kotlinType, ReifiedTypeInliner.OperationKind.JAVA_CLASS, mv, this)
|
||||
val classifier = classType.classifierOrNull
|
||||
if (classifier is IrTypeParameterSymbol) {
|
||||
assert(classifier.owner.isReified) { "Non-reified type parameter under ::class should be rejected by type checker: ${classifier.owner.dump()}" }
|
||||
putReifiedOperationMarkerIfTypeIsReifiedParameter(classType, ReifiedTypeInliner.OperationKind.JAVA_CLASS, mv, this)
|
||||
}
|
||||
|
||||
putJavaLangClassInstance(mv, typeMapper.mapType(kotlinType), kotlinType, typeMapper)
|
||||
putJavaLangClassInstance(mv, typeMapper.mapType(classType), kotlinType, typeMapper.kotlinTypeMapper)
|
||||
}
|
||||
} else {
|
||||
throw AssertionError("not an IrGetClass or IrClassReference: ${classReference.dump()}")
|
||||
@@ -1046,29 +1036,14 @@ class ExpressionCodegen(
|
||||
return classReference.onStack
|
||||
}
|
||||
|
||||
private fun resolveToCallable(irCall: IrMemberAccessExpression, isSuper: Boolean): Callable {
|
||||
var descriptor = irCall.descriptor
|
||||
if (descriptor is TypeAliasConstructorDescriptor) {
|
||||
throw AssertionError("TypeAliasConstructorDescriptor should be unwrapped in psi2ir: $descriptor")
|
||||
}
|
||||
if (descriptor is PropertyDescriptor) {
|
||||
descriptor = descriptor.getter!!
|
||||
}
|
||||
if (descriptor is CallableMemberDescriptor && JvmCodegenUtil.getDirectMember(descriptor) is SyntheticJavaPropertyDescriptor) {
|
||||
val propertyDescriptor = JvmCodegenUtil.getDirectMember(descriptor) as SyntheticJavaPropertyDescriptor
|
||||
descriptor = if (descriptor is PropertyGetterDescriptor) {
|
||||
propertyDescriptor.getMethod
|
||||
} else {
|
||||
propertyDescriptor.setMethod!!
|
||||
}
|
||||
}
|
||||
return typeMapper.mapToCallableMethod(descriptor as FunctionDescriptor, isSuper)
|
||||
private fun resolveToCallable(irCall: IrFunctionAccessExpression, isSuper: Boolean): Callable {
|
||||
return typeMapper.mapToCallableMethod(irCall.symbol.owner, isSuper)
|
||||
}
|
||||
|
||||
private fun getOrCreateCallGenerator(
|
||||
descriptor: CallableDescriptor,
|
||||
irFunction: IrFunction,
|
||||
element: IrMemberAccessExpression?,
|
||||
typeParameterMappings: TypeParameterMappings?,
|
||||
typeParameterMappings: IrTypeParameterMappings?,
|
||||
isDefaultCompilation: Boolean,
|
||||
data: BlockInfo
|
||||
): IrCallGenerator {
|
||||
@@ -1076,56 +1051,56 @@ class ExpressionCodegen(
|
||||
|
||||
// We should inline callable containing reified type parameters even if inline is disabled
|
||||
// because they may contain something to reify and straight call will probably fail at runtime
|
||||
val isInline = descriptor.isInlineCall(state)
|
||||
val isInline = irFunction.isInlineCall(state)
|
||||
|
||||
if (!isInline) return IrCallGenerator.DefaultCallGenerator
|
||||
|
||||
val original = unwrapInitialSignatureDescriptor(DescriptorUtils.unwrapFakeOverride(descriptor.original as FunctionDescriptor))
|
||||
val original = (irFunction as? IrSimpleFunction)?.resolveFakeOverride() ?: irFunction
|
||||
return if (isDefaultCompilation) {
|
||||
TODO()
|
||||
} else {
|
||||
IrInlineCodegen(this, state, original, typeParameterMappings!!, IrSourceCompilerForInline(state, element, this, data))
|
||||
IrInlineCodegen(this, state, original.descriptor, typeParameterMappings!!, IrSourceCompilerForInline(state, element, this, data))
|
||||
}
|
||||
}
|
||||
|
||||
private fun getOrCreateCallGenerator(
|
||||
memberAccessExpression: IrMemberAccessExpression,
|
||||
descriptor: CallableDescriptor,
|
||||
functionAccessExpression: IrFunctionAccessExpression,
|
||||
data: BlockInfo
|
||||
): IrCallGenerator {
|
||||
val callee = functionAccessExpression.symbol.owner
|
||||
val typeArgumentContainer = if (callee is IrConstructor) callee.parentAsClass else callee
|
||||
val typeArguments =
|
||||
if (memberAccessExpression.typeArgumentsCount == 0) {
|
||||
if (functionAccessExpression.typeArgumentsCount == 0) {
|
||||
//avoid ambiguity with type constructor type parameters
|
||||
emptyMap()
|
||||
} else (descriptor.propertyIfAccessor as? CallableDescriptor)?.original?.typeParameters?.keysToMap {
|
||||
memberAccessExpression.getTypeArgumentOrDefault(it)
|
||||
} ?: emptyMap()
|
||||
} else typeArgumentContainer.typeParameters.keysToMap {
|
||||
functionAccessExpression.getTypeArgumentOrDefault(it)
|
||||
}
|
||||
|
||||
val mappings = TypeParameterMappings()
|
||||
val mappings = IrTypeParameterMappings()
|
||||
for (entry in typeArguments.entries) {
|
||||
val key = entry.key
|
||||
val type = entry.value
|
||||
|
||||
val isReified = key.isReified || InlineUtil.isArrayConstructorWithLambda(descriptor)
|
||||
val isReified = key.isReified || callee.isArrayConstructorWithLambda()
|
||||
|
||||
val typeParameterAndReificationArgument = extractReificationArgument(type)
|
||||
if (typeParameterAndReificationArgument == null) {
|
||||
val approximatedType = approximateCapturedTypes(entry.value).upper
|
||||
val reificationArgument = extractReificationArgument(type)
|
||||
if (reificationArgument == null) {
|
||||
// type is not generic
|
||||
val signatureWriter = BothSignatureWriter(BothSignatureWriter.Mode.TYPE)
|
||||
val asmType = typeMapper.mapTypeParameter(approximatedType, signatureWriter)
|
||||
val asmType = typeMapper.mapTypeParameter(type, signatureWriter)
|
||||
|
||||
mappings.addParameterMappingToType(
|
||||
key.name.identifier, approximatedType, asmType, signatureWriter.toString(), isReified
|
||||
key.name.identifier, type, asmType, signatureWriter.toString(), isReified
|
||||
)
|
||||
} else {
|
||||
mappings.addParameterMappingForFurtherReification(
|
||||
key.name.identifier, type, typeParameterAndReificationArgument.second, isReified
|
||||
key.name.identifier, type, reificationArgument, isReified
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return getOrCreateCallGenerator(descriptor, memberAccessExpression, mappings, false, data)
|
||||
return getOrCreateCallGenerator(callee, functionAccessExpression, mappings, false, data)
|
||||
}
|
||||
|
||||
override fun consumeReifiedOperationMarker(typeParameterDescriptor: TypeParameterDescriptor) {
|
||||
@@ -1152,6 +1127,71 @@ class ExpressionCodegen(
|
||||
fun isFinallyMarkerRequired(): Boolean {
|
||||
return irFunction.isInline || isInlineLambda
|
||||
}
|
||||
|
||||
/* Borrowed and modified from compiler/backend/src/org/jetbrains/kotlin/codegen/codegenUtil.kt */
|
||||
|
||||
private fun extractReificationArgumentWithParameter(initialType: IrType): Pair<IrTypeParameter, IrReificationArgument>? {
|
||||
var type = initialType
|
||||
var arrayDepth = 0
|
||||
val isNullable = type.isMarkedNullable()
|
||||
while (type.isArray() || type.isNullableArray()) {
|
||||
arrayDepth++
|
||||
type = (type as IrSimpleType).arguments[0].safeAs<IrTypeProjection>()?.type ?: classCodegen.context.irBuiltIns.anyNType
|
||||
}
|
||||
|
||||
val parameter = type.getTypeParameterOrNull() ?: return null
|
||||
|
||||
return Pair(parameter, IrReificationArgument(parameter.name.asString(), isNullable, arrayDepth))
|
||||
}
|
||||
|
||||
private fun extractReificationArgument(initialType: IrType): IrReificationArgument? = extractReificationArgumentWithParameter(initialType)?.second
|
||||
|
||||
/* From ReifiedTypeInliner.kt */
|
||||
inner class IrReificationArgument(
|
||||
val parameterName: String, val nullable: Boolean, private val arrayDepth: Int
|
||||
) {
|
||||
fun asString() = "[".repeat(arrayDepth) + parameterName + (if (nullable) "?" else "")
|
||||
fun combine(replacement: IrReificationArgument) =
|
||||
IrReificationArgument(
|
||||
replacement.parameterName,
|
||||
this.nullable || (replacement.nullable && this.arrayDepth == 0),
|
||||
this.arrayDepth + replacement.arrayDepth
|
||||
)
|
||||
|
||||
fun reify(replacementAsmType: Type, irType: IrType) =
|
||||
Pair(
|
||||
Type.getType("[".repeat(arrayDepth) + replacementAsmType),
|
||||
irType.arrayOf(arrayDepth).withHasQuestionMark(nullable)
|
||||
)
|
||||
|
||||
private fun IrType.arrayOf(arrayDepth: Int): IrType {
|
||||
val builtins = classCodegen.context.irBuiltIns
|
||||
var currentType = this
|
||||
|
||||
repeat(arrayDepth) {
|
||||
currentType = builtins.arrayClass.typeWith(currentType)
|
||||
}
|
||||
|
||||
return currentType
|
||||
}
|
||||
|
||||
fun toReificationArgument() = ReificationArgument(parameterName, nullable, arrayDepth)
|
||||
}
|
||||
|
||||
/* From ExpressionCodegen.java */
|
||||
private fun putReifiedOperationMarkerIfTypeIsReifiedParameter(
|
||||
type: IrType, operationKind: ReifiedTypeInliner.OperationKind, v: InstructionAdapter,
|
||||
codegen: BaseExpressionCodegen?
|
||||
) {
|
||||
val typeParameterAndReificationArgument = extractReificationArgumentWithParameter(type)
|
||||
if (typeParameterAndReificationArgument != null && typeParameterAndReificationArgument.first.isReified) {
|
||||
val irTypeParameter = typeParameterAndReificationArgument.first
|
||||
codegen?.consumeReifiedOperationMarker(irTypeParameter.descriptor)
|
||||
ReifiedTypeInliner.putReifiedOperationMarker(
|
||||
operationKind, typeParameterAndReificationArgument.second.toReificationArgument(), v
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun DefaultCallArgs.generateOnStackIfNeeded(callGenerator: IrCallGenerator, isConstructor: Boolean, codegen: ExpressionCodegen): Boolean {
|
||||
@@ -1173,6 +1213,80 @@ fun DefaultCallArgs.generateOnStackIfNeeded(callGenerator: IrCallGenerator, isCo
|
||||
return toInts.isNotEmpty()
|
||||
}
|
||||
|
||||
internal fun CallableDescriptor.isInlineCall(state: GenerationState) =
|
||||
(!state.isInlineDisabled || InlineUtil.containsReifiedTypeParameters(this)) &&
|
||||
(InlineUtil.isInline(this) || InlineUtil.isArrayConstructorWithLambda(this))
|
||||
internal fun IrFunction.isInlineCall(state: GenerationState) =
|
||||
(!state.isInlineDisabled || containsReifiedTypeParameters()) &&
|
||||
(isInline || isArrayConstructorWithLambda())
|
||||
|
||||
val IrType.isReifiedTypeParameter: Boolean
|
||||
get() = this.classifierOrNull?.safeAs<IrTypeParameterSymbol>()?.owner?.isReified == true
|
||||
|
||||
/* Copied and modified from InlineUtil.java */
|
||||
fun isInline(declaration: IrDeclaration?): Boolean = declaration is IrSimpleFunction && declaration.isInline
|
||||
|
||||
fun IrFunction.containsReifiedTypeParameters(): Boolean =
|
||||
typeParameters.any { it.isReified }
|
||||
|
||||
fun IrClass.isArrayOrPrimitiveArray() = this.defaultType.let { it.isArray() || it.isPrimitiveArray() }
|
||||
|
||||
/* From typeUtil.java */
|
||||
fun IrType.getTypeParameterOrNull() = classifierOrNull?.owner?.safeAs<IrTypeParameter>()
|
||||
|
||||
/* From ReifiedTypeInliner.kt */
|
||||
class IrTypeParameterMappings {
|
||||
private val mappingsByName = hashMapOf<String, IrTypeParameterMapping>()
|
||||
|
||||
fun addParameterMappingToType(name: String, type: IrType, asmType: Type, signature: String, isReified: Boolean) {
|
||||
mappingsByName[name] = IrTypeParameterMapping(
|
||||
name, type, asmType, reificationArgument = null, signature = signature, isReified = isReified
|
||||
)
|
||||
}
|
||||
|
||||
fun addParameterMappingForFurtherReification(
|
||||
name: String,
|
||||
type: IrType,
|
||||
reificationArgument: ExpressionCodegen.IrReificationArgument,
|
||||
isReified: Boolean
|
||||
) {
|
||||
mappingsByName[name] = IrTypeParameterMapping(
|
||||
name, type, asmType = null, reificationArgument = reificationArgument, signature = null, isReified = isReified
|
||||
)
|
||||
}
|
||||
|
||||
operator fun get(name: String): IrTypeParameterMapping? = mappingsByName[name]
|
||||
|
||||
fun hasReifiedParameters() = mappingsByName.values.any { it.isReified }
|
||||
|
||||
internal inline fun forEach(l: (IrTypeParameterMapping) -> Unit) {
|
||||
mappingsByName.values.forEach(l)
|
||||
}
|
||||
|
||||
fun toTypeParameterMappings() = TypeParameterMappings().also { result ->
|
||||
mappingsByName.forEach { (_, value) ->
|
||||
if (value.asmType == null) {
|
||||
result.addParameterMappingForFurtherReification(
|
||||
value.name,
|
||||
value.type.toKotlinType(),
|
||||
value.reificationArgument!!.toReificationArgument(),
|
||||
value.isReified
|
||||
)
|
||||
} else {
|
||||
result.addParameterMappingToType(
|
||||
value.name,
|
||||
value.type.toKotlinType(),
|
||||
value.asmType,
|
||||
value.signature!!,
|
||||
value.isReified
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class IrTypeParameterMapping(
|
||||
val name: String,
|
||||
val type: IrType,
|
||||
val asmType: Type?,
|
||||
val reificationArgument: ExpressionCodegen.IrReificationArgument?,
|
||||
val signature: String?,
|
||||
val isReified: Boolean
|
||||
)
|
||||
|
||||
+95
-45
@@ -7,14 +7,14 @@ package org.jetbrains.kotlin.backend.jvm.codegen
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.FunctionCodegen
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.ir.util.getAnnotation
|
||||
import org.jetbrains.kotlin.ir.util.hasAnnotation
|
||||
import org.jetbrains.kotlin.ir.util.isAnnotationClass
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
|
||||
@@ -33,8 +33,6 @@ open class FunctionCodegen(
|
||||
|
||||
val state = classCodegen.state
|
||||
|
||||
val descriptor = irFunction.descriptor
|
||||
|
||||
fun generate(): JvmMethodGenericSignature =
|
||||
try {
|
||||
doGenerate()
|
||||
@@ -43,23 +41,26 @@ open class FunctionCodegen(
|
||||
}
|
||||
|
||||
private fun doGenerate(): JvmMethodGenericSignature {
|
||||
val signature = classCodegen.typeMapper.mapSignatureWithGeneric(descriptor, OwnerKind.IMPLEMENTATION)
|
||||
val signature = classCodegen.typeMapper.mapSignatureWithGeneric(irFunction, OwnerKind.IMPLEMENTATION)
|
||||
|
||||
val flags = calculateMethodFlags(irFunction.isStatic)
|
||||
val methodVisitor = createMethod(flags, signature)
|
||||
|
||||
generateParameterNames(descriptor, methodVisitor, signature, state, flags.and(Opcodes.ACC_SYNTHETIC) != 0)
|
||||
generateParameterNames(irFunction.descriptor, methodVisitor, signature, state, flags.and(Opcodes.ACC_SYNTHETIC) != 0)
|
||||
|
||||
if (irFunction.origin != IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER) {
|
||||
AnnotationCodegen(classCodegen, state, methodVisitor::visitAnnotation).genAnnotations(irFunction, signature.asmMethod.returnType)
|
||||
FunctionCodegen.generateParameterAnnotations(descriptor, methodVisitor, signature, DummyOldInnerClassConsumer(), state)
|
||||
AnnotationCodegen(classCodegen, state, methodVisitor::visitAnnotation).genAnnotations(
|
||||
irFunction,
|
||||
signature.asmMethod.returnType
|
||||
)
|
||||
generateParameterAnnotations(irFunction, methodVisitor, signature, classCodegen, state)
|
||||
}
|
||||
|
||||
if (!state.classBuilderMode.generateBodies || flags.and(Opcodes.ACC_ABSTRACT) != 0 || irFunction.isExternal) {
|
||||
generateAnnotationDefaultValueIfNeeded(methodVisitor)
|
||||
methodVisitor.visitEnd()
|
||||
} else {
|
||||
val frameMap = createFrameMapWithReceivers(classCodegen.state, irFunction, signature)
|
||||
val frameMap = createFrameMapWithReceivers(signature)
|
||||
ExpressionCodegen(irFunction, frameMap, InstructionAdapter(methodVisitor), classCodegen, isInlineLambda).generate()
|
||||
}
|
||||
|
||||
@@ -102,7 +103,7 @@ open class FunctionCodegen(
|
||||
// @Throws(vararg exceptionClasses: KClass<out Throwable>)
|
||||
val exceptions = irFunction.getAnnotation(FqName("kotlin.jvm.Throws"))?.getValueArgument(0)?.let {
|
||||
(it as IrVararg).elements.map { exceptionClass ->
|
||||
classCodegen.typeMapper.mapType((exceptionClass as IrClassReference).classType.toKotlinType()).internalName
|
||||
classCodegen.typeMapper.mapType((exceptionClass as IrClassReference).classType).internalName
|
||||
}.toTypedArray()
|
||||
}
|
||||
|
||||
@@ -127,7 +128,7 @@ open class FunctionCodegen(
|
||||
// TODO: any simpler way to get to the value expression?
|
||||
// Are there other valid IR structures that represent the default value?
|
||||
return irFunction.safeAs<IrSimpleFunction>()
|
||||
?.correspondingProperty
|
||||
?.correspondingPropertySymbol?.owner
|
||||
?.backingField
|
||||
?.initializer.safeAs<IrExpressionBody>()
|
||||
?.expression?.safeAs<IrGetValue>()
|
||||
@@ -135,46 +136,95 @@ open class FunctionCodegen(
|
||||
?.defaultValue?.safeAs<IrExpressionBody>()
|
||||
?.expression
|
||||
}
|
||||
}
|
||||
|
||||
private fun createFrameMapWithReceivers(
|
||||
state: GenerationState,
|
||||
irFunction: IrFunction,
|
||||
signature: JvmMethodSignature
|
||||
): IrFrameMap {
|
||||
val frameMap = IrFrameMap()
|
||||
if (irFunction is IrConstructor) {
|
||||
frameMap.enter((irFunction.parent as IrClass).thisReceiver!!, AsmTypes.OBJECT_TYPE)
|
||||
} else if (irFunction.dispatchReceiverParameter != null) {
|
||||
frameMap.enter(irFunction.dispatchReceiverParameter!!, AsmTypes.OBJECT_TYPE)
|
||||
}
|
||||
private fun createFrameMapWithReceivers(signature: JvmMethodSignature): IrFrameMap {
|
||||
val frameMap = IrFrameMap()
|
||||
if (irFunction is IrConstructor) {
|
||||
frameMap.enter((irFunction.parent as IrClass).thisReceiver!!, AsmTypes.OBJECT_TYPE)
|
||||
} else if (irFunction.dispatchReceiverParameter != null) {
|
||||
frameMap.enter(irFunction.dispatchReceiverParameter!!, AsmTypes.OBJECT_TYPE)
|
||||
}
|
||||
|
||||
for (parameter in signature.valueParameters) {
|
||||
if (parameter.kind == JvmMethodParameterKind.RECEIVER) {
|
||||
val receiverParameter = irFunction.extensionReceiverParameter
|
||||
if (receiverParameter?.descriptor != null) {
|
||||
frameMap.enter(receiverParameter, state.typeMapper.mapType(receiverParameter.descriptor))
|
||||
} else {
|
||||
for (parameter in signature.valueParameters) {
|
||||
if (parameter.kind == JvmMethodParameterKind.RECEIVER) {
|
||||
val receiverParameter = irFunction.extensionReceiverParameter
|
||||
if (receiverParameter != null) {
|
||||
frameMap.enter(receiverParameter, classCodegen.typeMapper.mapType(receiverParameter))
|
||||
} else {
|
||||
frameMap.enterTemp(parameter.asmType)
|
||||
}
|
||||
} else if (parameter.kind != JvmMethodParameterKind.VALUE) {
|
||||
frameMap.enterTemp(parameter.asmType)
|
||||
}
|
||||
} else if (parameter.kind != JvmMethodParameterKind.VALUE) {
|
||||
frameMap.enterTemp(parameter.asmType)
|
||||
}
|
||||
}
|
||||
|
||||
for (parameter in irFunction.valueParameters) {
|
||||
frameMap.enter(parameter, state.typeMapper.mapType(parameter.type.toKotlinType()))
|
||||
}
|
||||
for (parameter in irFunction.valueParameters) {
|
||||
frameMap.enter(parameter, classCodegen.typeMapper.mapType(parameter.type))
|
||||
}
|
||||
|
||||
return frameMap
|
||||
return frameMap
|
||||
}
|
||||
}
|
||||
|
||||
/**/// TODO: temporary, to allow calling the old FunctionCodegen.generateParameterAnnotations
|
||||
private class DummyOldInnerClassConsumer()
|
||||
: org.jetbrains.kotlin.codegen.InnerClassConsumer {
|
||||
|
||||
override fun addInnerClassInfoFromAnnotation(classDescriptor: ClassDescriptor) {
|
||||
|
||||
// Borrowed from org.jetbrains.kotlin.codegen.FunctionCodegen.java
|
||||
fun generateParameterAnnotations(
|
||||
irFunction: IrFunction,
|
||||
mv: MethodVisitor,
|
||||
jvmSignature: JvmMethodSignature,
|
||||
innerClassConsumer: InnerClassConsumer,
|
||||
state: GenerationState
|
||||
) {
|
||||
val iterator = irFunction.valueParameters.iterator()
|
||||
val kotlinParameterTypes = jvmSignature.valueParameters
|
||||
var syntheticParameterCount = 0
|
||||
kotlinParameterTypes.forEachIndexed { i, parameterSignature ->
|
||||
val kind = parameterSignature.kind
|
||||
if (kind.isSkippedInGenericSignature) {
|
||||
if (AsmUtil.IS_BUILT_WITH_ASM6) {
|
||||
markEnumOrInnerConstructorParameterAsSynthetic(mv, i, state.classBuilderMode)
|
||||
} else {
|
||||
syntheticParameterCount++
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!AsmUtil.IS_BUILT_WITH_ASM6) {
|
||||
visitAnnotableParameterCount(mv, kotlinParameterTypes.size - syntheticParameterCount)
|
||||
}
|
||||
|
||||
}
|
||||
kotlinParameterTypes.forEachIndexed { i, parameterSignature ->
|
||||
val kind = parameterSignature.kind
|
||||
if (kind.isSkippedInGenericSignature) return@forEachIndexed
|
||||
|
||||
val annotated = when (kind) {
|
||||
JvmMethodParameterKind.VALUE -> iterator.next()
|
||||
JvmMethodParameterKind.RECEIVER -> irFunction.extensionReceiverParameter
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (annotated != null) {
|
||||
|
||||
AnnotationCodegen(
|
||||
innerClassConsumer,
|
||||
state
|
||||
) { descriptor, visible ->
|
||||
mv.visitParameterAnnotation(
|
||||
if (AsmUtil.IS_BUILT_WITH_ASM6) i else i - syntheticParameterCount,
|
||||
descriptor,
|
||||
visible
|
||||
)
|
||||
}
|
||||
.genAnnotations(annotated, parameterSignature.asmType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun markEnumOrInnerConstructorParameterAsSynthetic(mv: MethodVisitor, i: Int, mode: ClassBuilderMode) {
|
||||
// IDEA's ClsPsi builder fails to annotate synthetic parameters
|
||||
if (mode === ClassBuilderMode.LIGHT_CLASSES) return
|
||||
|
||||
// This is needed to avoid RuntimeInvisibleParameterAnnotations error in javac:
|
||||
// see MethodWriter.visitParameterAnnotation()
|
||||
|
||||
val av = mv.visitParameterAnnotation(i, "Ljava/lang/Synthetic;", true)
|
||||
av?.visitEnd()
|
||||
}
|
||||
|
||||
+4
-4
@@ -20,14 +20,14 @@ import org.jetbrains.kotlin.codegen.Callable
|
||||
import org.jetbrains.kotlin.codegen.CallableMethod
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.codegen.ValueKind
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
interface IrCallGenerator {
|
||||
|
||||
fun genCall(callableMethod: Callable, callDefault: Boolean, codegen: ExpressionCodegen, expression: IrMemberAccessExpression) {
|
||||
fun genCall(callableMethod: Callable, callDefault: Boolean, codegen: ExpressionCodegen, expression: IrFunctionAccessExpression) {
|
||||
if (!callDefault) {
|
||||
callableMethod.genInvokeInstruction(codegen.mv)
|
||||
} else {
|
||||
@@ -40,7 +40,7 @@ interface IrCallGenerator {
|
||||
}
|
||||
|
||||
fun genValueAndPut(
|
||||
valueParameterDescriptor: ValueParameterDescriptor?,
|
||||
irValueParameter: IrValueParameter?,
|
||||
argumentExpression: IrExpression,
|
||||
parameterType: Type,
|
||||
parameterIndex: Int,
|
||||
|
||||
+14
-20
@@ -6,19 +6,15 @@
|
||||
package org.jetbrains.kotlin.backend.jvm.codegen
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.builtins.isExtensionFunctionType
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.inline.*
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil.isInlineParameter
|
||||
import org.jetbrains.kotlin.utils.keysToMap
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||
@@ -27,9 +23,10 @@ class IrInlineCodegen(
|
||||
codegen: ExpressionCodegen,
|
||||
state: GenerationState,
|
||||
function: FunctionDescriptor,
|
||||
typeParameterMappings: TypeParameterMappings,
|
||||
typeParameterMappings: IrTypeParameterMappings,
|
||||
sourceCompiler: SourceCompilerForInline
|
||||
) : InlineCodegen<ExpressionCodegen>(codegen, state, function, typeParameterMappings, sourceCompiler), IrCallGenerator {
|
||||
) : InlineCodegen<ExpressionCodegen>(codegen, state, function, typeParameterMappings.toTypeParameterMappings(), sourceCompiler),
|
||||
IrCallGenerator {
|
||||
override fun generateAssertFieldIfNeeded(info: RootInliningContext) {
|
||||
// TODO: JVM assertions are not implemented yet in IR backend
|
||||
}
|
||||
@@ -45,19 +42,19 @@ class IrInlineCodegen(
|
||||
}
|
||||
|
||||
override fun genValueAndPut(
|
||||
valueParameterDescriptor: ValueParameterDescriptor?,
|
||||
irValueParameter: IrValueParameter?,
|
||||
argumentExpression: IrExpression,
|
||||
parameterType: Type,
|
||||
parameterIndex: Int,
|
||||
codegen: ExpressionCodegen,
|
||||
blockInfo: BlockInfo
|
||||
) {
|
||||
if (valueParameterDescriptor?.let { isInlineParameter(it) } == true && isInlineIrExpression(argumentExpression)) {
|
||||
if (irValueParameter?.isInlineParameter() == true && isInlineIrExpression(argumentExpression)) {
|
||||
val irReference: IrFunctionReference =
|
||||
(argumentExpression as IrBlock).statements.filterIsInstance<IrFunctionReference>().single()
|
||||
rememberClosure(irReference, parameterType, valueParameterDescriptor) as IrExpressionLambdaImpl
|
||||
rememberClosure(irReference, parameterType, irValueParameter) as IrExpressionLambdaImpl
|
||||
} else {
|
||||
putValueOnStack(argumentExpression, parameterType, valueParameterDescriptor?.index ?: -1)
|
||||
putValueOnStack(argumentExpression, parameterType, irValueParameter?.index ?: -1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,12 +86,17 @@ class IrInlineCodegen(
|
||||
invocationParamBuilder.markValueParametersStart()
|
||||
}
|
||||
|
||||
override fun genCall(callableMethod: Callable, callDefault: Boolean, codegen: ExpressionCodegen, expression: IrMemberAccessExpression) {
|
||||
override fun genCall(
|
||||
callableMethod: Callable,
|
||||
callDefault: Boolean,
|
||||
codegen: ExpressionCodegen,
|
||||
expression: IrFunctionAccessExpression
|
||||
) {
|
||||
val typeArguments = expression.descriptor.typeParameters.keysToMap { expression.getTypeArgumentOrDefault(it) }
|
||||
performInline(typeArguments, callDefault, codegen)
|
||||
}
|
||||
|
||||
private fun rememberClosure(irReference: IrFunctionReference, type: Type, parameter: ValueParameterDescriptor): LambdaInfo {
|
||||
private fun rememberClosure(irReference: IrFunctionReference, type: Type, parameter: IrValueParameter): LambdaInfo {
|
||||
//assert(InlineUtil.isInlinableParameterExpression(ktLambda)) { "Couldn't find inline expression in ${expression.text}" }
|
||||
val expression = irReference.symbol.owner
|
||||
return IrExpressionLambdaImpl(
|
||||
@@ -160,13 +162,5 @@ fun IrFunction.isInlineFunctionCall(context: JvmBackendContext) =
|
||||
(!context.state.isInlineDisabled || typeParameters.any { it.isReified }) &&
|
||||
(isInline || isArrayConstructorWithLambda())
|
||||
|
||||
private fun IrFunction.isArrayConstructorWithLambda() =
|
||||
valueParameters.size == 2 &&
|
||||
this is IrConstructor &&
|
||||
parentAsClass.let {
|
||||
it.getPackageFragment()?.fqName?.asString() == "kotlin" &&
|
||||
it.name.asString().endsWith("Array")
|
||||
}
|
||||
|
||||
fun IrValueParameter.isInlineParameter() =
|
||||
!isNoinline && !type.isNullable() && type.isFunctionOrKFunction()
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.codegen
|
||||
|
||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||
import org.jetbrains.kotlin.codegen.signature.JvmSignatureWriter
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
|
||||
class IrTypeMapper(val kotlinTypeMapper: KotlinTypeMapper) {
|
||||
|
||||
val classBuilderMode get() = kotlinTypeMapper.classBuilderMode
|
||||
|
||||
fun classInternalName(irClass: IrClass) = kotlinTypeMapper.classInternalName(irClass.descriptor)
|
||||
|
||||
fun mapAsmMethod(irFunction: IrFunction) = kotlinTypeMapper.mapAsmMethod(irFunction.descriptor)
|
||||
|
||||
fun mapClass(irClass: IrClass) = kotlinTypeMapper.mapClass(irClass.descriptor)
|
||||
|
||||
fun mapFieldSignature(irType: IrType, irFrield: IrField) =
|
||||
kotlinTypeMapper.mapFieldSignature(irType.toKotlinType(), irFrield.descriptor)
|
||||
|
||||
fun mapFunctionName(irReturnTarget: IrReturnTarget, ownerKind: OwnerKind) =
|
||||
kotlinTypeMapper.mapFunctionName(irReturnTarget.descriptor, ownerKind)
|
||||
|
||||
fun mapImplementationOwner(irDeclaration: IrDeclaration) = kotlinTypeMapper.mapImplementationOwner(irDeclaration.descriptor)
|
||||
|
||||
fun mapReturnType(irReturnTarget: IrReturnTarget) = kotlinTypeMapper.mapReturnType(irReturnTarget.descriptor)
|
||||
|
||||
fun mapSignatureSkipGeneric(f: IrFunction, kind: OwnerKind = OwnerKind.IMPLEMENTATION) =
|
||||
kotlinTypeMapper.mapSignatureSkipGeneric(f.descriptor, kind)
|
||||
|
||||
fun mapSignatureWithGeneric(f: IrFunction, kind: OwnerKind) = kotlinTypeMapper.mapSignatureWithGeneric(f.descriptor, kind)
|
||||
|
||||
fun mapSupertype(irType: IrType, sw: JvmSignatureWriter) = kotlinTypeMapper.mapSupertype(irType.toKotlinType(), sw)
|
||||
|
||||
fun mapToCallableMethod(f: IrFunction, superCall: Boolean, kind: OwnerKind? = null, resolvedCall: ResolvedCall<*>? = null) =
|
||||
kotlinTypeMapper.mapToCallableMethod(f.descriptor, superCall, kind, resolvedCall)
|
||||
|
||||
fun mapType(irType: IrType) = kotlinTypeMapper.mapType(irType.toKotlinType())
|
||||
|
||||
fun mapType(irClass: IrClass) = kotlinTypeMapper.mapType(irClass.descriptor)
|
||||
|
||||
fun mapType(irField: IrField) = kotlinTypeMapper.mapType(irField.descriptor)
|
||||
|
||||
fun mapType(irValueParameter: IrValueParameter) = kotlinTypeMapper.mapType(irValueParameter.descriptor)
|
||||
|
||||
fun mapType(irVariable: IrVariable) = kotlinTypeMapper.mapType(irVariable.descriptor)
|
||||
|
||||
fun mapType(irType: IrType, sw: JvmSignatureWriter, mode: TypeMappingMode) =
|
||||
kotlinTypeMapper.mapType(irType.toKotlinType(), sw, mode)
|
||||
|
||||
fun mapTypeParameter(irType: IrType, signatureWriter: JvmSignatureWriter) =
|
||||
kotlinTypeMapper.mapTypeParameter(irType.toKotlinType(), signatureWriter)
|
||||
|
||||
fun writeFormalTypeParameters(irParameters: List<IrTypeParameter>, sw: JvmSignatureWriter) =
|
||||
kotlinTypeMapper.writeFormalTypeParameters(irParameters.map { it.descriptor }, sw)
|
||||
}
|
||||
+398
-6
@@ -6,18 +6,42 @@
|
||||
package org.jetbrains.kotlin.backend.jvm.codegen
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.backend.common.ir.ir2string
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.codegen.FrameMapBase
|
||||
import org.jetbrains.kotlin.codegen.SourceInfo
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.allOverridden
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil.LABELED_THIS_PARAMETER
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil.RECEIVER_PARAMETER_NAME
|
||||
import org.jetbrains.kotlin.codegen.inline.DefaultSourceMapper
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
|
||||
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.util.isAnnotationClass
|
||||
import org.jetbrains.kotlin.ir.util.isInterface
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.load.java.JavaVisibilities
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeMappingMode
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import java.io.File
|
||||
import java.util.ArrayList
|
||||
import java.util.LinkedHashSet
|
||||
|
||||
class IrFrameMap : FrameMapBase<IrSymbol>()
|
||||
|
||||
@@ -61,3 +85,371 @@ fun JvmBackendContext.getSourceMapper(declaration: IrClass): DefaultSourceMapper
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val IrType.isExtensionFunctionType: Boolean
|
||||
get() = isFunctionTypeOrSubtype() && hasAnnotation(KotlinBuiltIns.FQ_NAMES.extensionFunctionType)
|
||||
|
||||
/**
|
||||
* @return true if the function is a constructor of one of 9 array classes (Array<T>, IntArray, FloatArray, ...)
|
||||
* which takes the size and an initializer lambda as parameters. Such constructors are marked as 'inline' but they are not loaded
|
||||
* as such because the 'inline' flag is not stored for constructors in the binary metadata. Therefore we pretend that they are inline
|
||||
*/
|
||||
fun IrFunction.isArrayConstructorWithLambda(): Boolean = this is IrConstructor &&
|
||||
valueParameters.size == 2 &&
|
||||
parentAsClass.isArrayOrPrimitiveArray()
|
||||
|
||||
|
||||
/* Borrowed from MemberCodegen.java */
|
||||
|
||||
fun writeInnerClass(innerClass: IrClass, typeMapper: IrTypeMapper, context: JvmBackendContext, v: ClassBuilder) {
|
||||
val outerClassInternalName = innerClass.parent.safeAs<IrClass>()?.let { typeMapper.classInternalName(it) }
|
||||
/* TODO: So long as the type mapper works by descriptors, the internal name should be consistent with it. */
|
||||
val outerClassInternalNameByDescriptor = innerClass.descriptor.containingDeclaration.safeAs<ClassDescriptor>()?.let {
|
||||
typeMapper.kotlinTypeMapper.classInternalName(it)
|
||||
}
|
||||
val innerName = innerClass.name.takeUnless { it.isSpecial }?.asString()
|
||||
val innerClassInternalName = typeMapper.classInternalName(innerClass)
|
||||
v.visitInnerClass(innerClassInternalName, outerClassInternalNameByDescriptor, innerName, innerClass.calculateInnerClassAccessFlags(context))
|
||||
}
|
||||
|
||||
/* Borrowed with modifications from AsmUtil.java */
|
||||
|
||||
private val NO_FLAG_LOCAL = 0
|
||||
|
||||
private val visibilityToAccessFlag = mapOf(
|
||||
Visibilities.PRIVATE to Opcodes.ACC_PRIVATE,
|
||||
Visibilities.PRIVATE_TO_THIS to Opcodes.ACC_PRIVATE,
|
||||
Visibilities.PROTECTED to Opcodes.ACC_PROTECTED,
|
||||
JavaVisibilities.PROTECTED_STATIC_VISIBILITY to Opcodes.ACC_PROTECTED,
|
||||
JavaVisibilities.PROTECTED_AND_PACKAGE to Opcodes.ACC_PROTECTED,
|
||||
Visibilities.PUBLIC to Opcodes.ACC_PUBLIC,
|
||||
Visibilities.INTERNAL to Opcodes.ACC_PUBLIC,
|
||||
Visibilities.LOCAL to NO_FLAG_LOCAL,
|
||||
JavaVisibilities.PACKAGE_VISIBILITY to AsmUtil.NO_FLAG_PACKAGE_PRIVATE
|
||||
)
|
||||
|
||||
private fun IrDeclaration.getVisibilityAccessFlagForAnonymous(): Int =
|
||||
if (isInlineOrContainedInInline(parent as? IrDeclaration)) Opcodes.ACC_PUBLIC else AsmUtil.NO_FLAG_PACKAGE_PRIVATE
|
||||
|
||||
fun IrClass.calculateInnerClassAccessFlags(context: JvmBackendContext): Int {
|
||||
val isLambda = superTypes.any { it.safeAs<IrSimpleType>()?.classifier === context.ir.symbols.lambdaClass }
|
||||
val visibility = when {
|
||||
isLambda -> getVisibilityAccessFlagForAnonymous()
|
||||
visibility === Visibilities.LOCAL -> Opcodes.ACC_PUBLIC
|
||||
else -> getVisibilityAccessFlag()
|
||||
}
|
||||
return visibility or
|
||||
if (origin.isSynthetic) Opcodes.ACC_SYNTHETIC else 0 or
|
||||
innerAccessFlagsForModalityAndKind() or
|
||||
if (isInner) 0 else Opcodes.ACC_STATIC
|
||||
}
|
||||
|
||||
private fun IrClass.innerAccessFlagsForModalityAndKind(): Int {
|
||||
when (kind) {
|
||||
ClassKind.INTERFACE -> return Opcodes.ACC_ABSTRACT or Opcodes.ACC_INTERFACE
|
||||
ClassKind.ENUM_CLASS -> return Opcodes.ACC_FINAL or Opcodes.ACC_ENUM
|
||||
ClassKind.ANNOTATION_CLASS -> return Opcodes.ACC_ABSTRACT or Opcodes.ACC_ANNOTATION or Opcodes.ACC_INTERFACE
|
||||
else -> {
|
||||
if (modality === Modality.FINAL) {
|
||||
return Opcodes.ACC_FINAL
|
||||
} else if (modality === Modality.ABSTRACT || modality === Modality.SEALED) {
|
||||
return Opcodes.ACC_ABSTRACT
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
private fun IrDeclarationWithVisibility.getVisibilityAccessFlag(kind: OwnerKind? = null): Int =
|
||||
specialCaseVisibility(kind)
|
||||
?: visibilityToAccessFlag[visibility]
|
||||
?: throw IllegalStateException("$visibility is not a valid visibility in backend for ${ir2string(this)}")
|
||||
|
||||
|
||||
private fun IrDeclarationWithVisibility.specialCaseVisibility(kind: OwnerKind?): Int? {
|
||||
// if (JvmCodegenUtil.isNonIntrinsicPrivateCompanionObjectInInterface(memberDescriptor)) {
|
||||
// return ACC_PUBLIC
|
||||
// }
|
||||
if (this is IrClass && Visibilities.isPrivate(visibility) &&
|
||||
parent.safeAs<IrClass>()?.isInterface ?: false) { // TODO: non-intrinsic
|
||||
return Opcodes.ACC_PUBLIC
|
||||
}
|
||||
|
||||
// if (memberDescriptor is FunctionDescriptor && isInlineClassWrapperConstructor(memberDescriptor, kind))
|
||||
if (this is IrConstructor && parentAsClass.isInline && kind === OwnerKind.IMPLEMENTATION) {
|
||||
return Opcodes.ACC_PRIVATE
|
||||
}
|
||||
|
||||
// if (kind !== OwnerKind.ERASED_INLINE_CLASS &&
|
||||
// memberDescriptor is ConstructorDescriptor &&
|
||||
// memberDescriptor !is AccessorForConstructorDescriptor &&
|
||||
// shouldHideConstructorDueToInlineClassTypeValueParameters(memberDescriptor)
|
||||
// ) {
|
||||
if (kind !== OwnerKind.ERASED_INLINE_CLASS &&
|
||||
this is IrConstructor &&
|
||||
shouldHideDueToInlineClassTypeValueParameters()
|
||||
) {
|
||||
return Opcodes.ACC_PRIVATE
|
||||
}
|
||||
|
||||
// if (memberDescriptor.isEffectivelyInlineOnly()) {
|
||||
if (isEffectivelyInlineOnly()) {
|
||||
return Opcodes.ACC_PRIVATE
|
||||
}
|
||||
|
||||
// if (memberVisibility === Visibilities.LOCAL && memberDescriptor is CallableMemberDescriptor) {
|
||||
if (visibility === Visibilities.LOCAL && this is IrFunction) {
|
||||
return Opcodes.ACC_PUBLIC
|
||||
}
|
||||
|
||||
// if (isEnumEntry(memberDescriptor)) {
|
||||
if (this is IrClass && this.kind === ClassKind.ENUM_ENTRY) {
|
||||
return AsmUtil.NO_FLAG_PACKAGE_PRIVATE
|
||||
}
|
||||
|
||||
// These ones should be public anyway after ToArrayLowering.
|
||||
// if (memberDescriptor.isToArrayFromCollection()) {
|
||||
// return ACC_PUBLIC
|
||||
// }
|
||||
|
||||
// if (memberDescriptor is ConstructorDescriptor && isAnonymousObject(memberDescriptor.containingDeclaration)) {
|
||||
// return getVisibilityAccessFlagForAnonymous(memberDescriptor.containingDeclaration as ClassDescriptor)
|
||||
// }
|
||||
if (this is IrConstructor && parentAsClass.isAnonymousObject) {
|
||||
return parentAsClass.getVisibilityAccessFlagForAnonymous()
|
||||
}
|
||||
|
||||
// TODO: when is this applicable?
|
||||
// if (memberDescriptor is SyntheticJavaPropertyDescriptor) {
|
||||
// return getVisibilityAccessFlag((memberDescriptor as SyntheticJavaPropertyDescriptor).getMethod)
|
||||
// }
|
||||
|
||||
|
||||
// if (memberDescriptor is PropertyAccessorDescriptor) {
|
||||
// val property = memberDescriptor.correspondingProperty
|
||||
// if (property is SyntheticJavaPropertyDescriptor) {
|
||||
// val method = (if (memberDescriptor === property.getGetter())
|
||||
// (property as SyntheticJavaPropertyDescriptor).getMethod
|
||||
// else
|
||||
// (property as SyntheticJavaPropertyDescriptor).setMethod)
|
||||
// ?: error("No get/set method in SyntheticJavaPropertyDescriptor: $property")
|
||||
// return getVisibilityAccessFlag(method)
|
||||
// }
|
||||
// }
|
||||
if (this is IrField && correspondingPropertySymbol?.owner?.isExternal == true) {
|
||||
val method = correspondingPropertySymbol?.owner?.getter ?: correspondingPropertySymbol?.owner?.setter
|
||||
?: error("No get/set method in SyntheticJavaPropertyDescriptor: ${ir2string(correspondingPropertySymbol?.owner)}")
|
||||
return method.getVisibilityAccessFlag()
|
||||
}
|
||||
|
||||
// if (memberDescriptor is CallableDescriptor && memberVisibility === Visibilities.PROTECTED) {
|
||||
// for (overridden in DescriptorUtils.getAllOverriddenDescriptors(memberDescriptor as CallableDescriptor)) {
|
||||
// if (isJvmInterface(overridden.containingDeclaration)) {
|
||||
// return ACC_PUBLIC
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
if (this is IrSimpleFunction && visibility === Visibilities.PROTECTED &&
|
||||
allOverridden().any { it.parentAsClass.isJvmInterface }
|
||||
) {
|
||||
return Opcodes.ACC_PUBLIC
|
||||
}
|
||||
|
||||
if (!Visibilities.isPrivate(visibility)) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (this is IrSimpleFunction && isSuspend) {
|
||||
return AsmUtil.NO_FLAG_PACKAGE_PRIVATE
|
||||
}
|
||||
|
||||
// Should be taken care of in IR
|
||||
// if (memberDescriptor is AccessorForCompanionObjectInstanceFieldDescriptor) {
|
||||
// return NO_FLAG_PACKAGE_PRIVATE
|
||||
// }
|
||||
|
||||
// return if (memberDescriptor is ConstructorDescriptor && isEnumEntry(containingDeclaration)) {
|
||||
// NO_FLAG_PACKAGE_PRIVATE
|
||||
// } else null
|
||||
if (this is IrConstructor && parentAsClass.kind === ClassKind.ENUM_ENTRY) {
|
||||
return AsmUtil.NO_FLAG_PACKAGE_PRIVATE
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
/* From inlineClassManglingRules.kt */
|
||||
fun IrConstructor.shouldHideDueToInlineClassTypeValueParameters() =
|
||||
!Visibilities.isPrivate(visibility) &&
|
||||
!parentAsClass.isInline &&
|
||||
parentAsClass.modality !== Modality.SEALED &&
|
||||
valueParameters.any { it.type.requiresFunctionNameMangling() }
|
||||
|
||||
fun IrType.requiresFunctionNameMangling(): Boolean =
|
||||
isInlineClassThatRequiresMangling() || isTypeParameterWithUpperBoundThatRequiresMangling()
|
||||
|
||||
fun IrType.isInlineClassThatRequiresMangling() =
|
||||
safeAs<IrSimpleType>()?.classifier?.owner?.safeAs<IrClass>()?.let {
|
||||
it.isInline && !it.isDontMangleClass()
|
||||
} ?: false
|
||||
|
||||
fun IrClass.isDontMangleClass() =
|
||||
fqNameWhenAvailable != DescriptorUtils.RESULT_FQ_NAME
|
||||
|
||||
fun IrType.isTypeParameterWithUpperBoundThatRequiresMangling() =
|
||||
safeAs<IrSimpleType>()?.classifier?.owner.safeAs<IrTypeParameter>()?.let { param ->
|
||||
param.superTypes.any { it.requiresFunctionNameMangling() }
|
||||
} ?: false
|
||||
|
||||
|
||||
/* Borrowed from InlineUtil. */
|
||||
private tailrec fun isInlineOrContainedInInline(declaration: IrDeclaration?): Boolean = when {
|
||||
declaration === null -> false
|
||||
declaration is IrFunction && declaration.isInline -> true
|
||||
else -> isInlineOrContainedInInline(declaration.parent as? IrDeclaration)
|
||||
}
|
||||
|
||||
/* Borrowed from inlineOnly.kt */
|
||||
|
||||
private val INLINE_ONLY_ANNOTATION_FQ_NAME = FqName("kotlin.internal.InlineOnly")
|
||||
|
||||
fun IrDeclarationWithVisibility.isInlineOnlyOrReifiable(): Boolean =
|
||||
this is IrFunction && (isReifiable() || isInlineOnly())
|
||||
|
||||
fun IrDeclarationWithVisibility.isEffectivelyInlineOnly(): Boolean =
|
||||
isInlineOnlyOrReifiable() ||
|
||||
(this is IrSimpleFunction && isSuspend && isInline &&
|
||||
(valueParameters.any { it.isCrossinline } || visibility === Visibilities.PRIVATE))
|
||||
|
||||
private fun IrFunction.isInlineOnly() =
|
||||
isInline && hasAnnotation(INLINE_ONLY_ANNOTATION_FQ_NAME)
|
||||
|
||||
private fun IrFunction.isReifiable() = typeParameters.any { it.isReified }
|
||||
|
||||
|
||||
// Borrowed with modifications from ImplementationBodyCodegen.java
|
||||
|
||||
private val KOTLIN_MARKER_INTERFACES: Map<FqName, String> = run {
|
||||
val kotlinMarkerInterfaces = mutableMapOf<FqName, String>()
|
||||
for (platformMutabilityMapping in JavaToKotlinClassMap.mutabilityMappings) {
|
||||
kotlinMarkerInterfaces[platformMutabilityMapping.kotlinReadOnly.asSingleFqName()] = "kotlin/jvm/internal/markers/KMappedMarker"
|
||||
|
||||
val mutableClassId = platformMutabilityMapping.kotlinMutable
|
||||
kotlinMarkerInterfaces[mutableClassId.asSingleFqName()] =
|
||||
"kotlin/jvm/internal/markers/K" + mutableClassId.relativeClassName.asString()
|
||||
.replace("MutableEntry", "Entry") // kotlin.jvm.internal.markers.KMutableMap.Entry for some reason
|
||||
.replace(".", "$")
|
||||
}
|
||||
kotlinMarkerInterfaces
|
||||
}
|
||||
|
||||
internal class IrSuperClassInfo(val type: Type, val irType: IrType?)
|
||||
|
||||
internal fun getSignature(
|
||||
irClass: IrClass,
|
||||
classAsmType: Type,
|
||||
superClassInfo: IrSuperClassInfo,
|
||||
typeMapper: IrTypeMapper
|
||||
): JvmClassSignature {
|
||||
val sw = BothSignatureWriter(BothSignatureWriter.Mode.CLASS)
|
||||
|
||||
typeMapper.writeFormalTypeParameters(irClass.typeParameters, sw)
|
||||
|
||||
sw.writeSuperclass()
|
||||
val irType = superClassInfo.irType
|
||||
if (irType == null) {
|
||||
sw.writeClassBegin(superClassInfo.type)
|
||||
sw.writeClassEnd()
|
||||
} else {
|
||||
typeMapper.mapSupertype(irType, sw)
|
||||
}
|
||||
sw.writeSuperclassEnd()
|
||||
|
||||
val superInterfaces = LinkedHashSet<String>()
|
||||
val kotlinMarkerInterfaces = LinkedHashSet<String>()
|
||||
|
||||
for (superType in irClass.superTypes) {
|
||||
val superClass = superType.safeAs<IrSimpleType>()?.classifier?.safeAs<IrClassSymbol>()?.owner ?: continue
|
||||
if (superClass.isJvmInterface) {
|
||||
val kotlinInterfaceName = superClass.fqNameWhenAvailable!!
|
||||
|
||||
sw.writeInterface()
|
||||
val jvmInterfaceType = typeMapper.mapSupertype(superType, sw)
|
||||
sw.writeInterfaceEnd()
|
||||
val jvmInterfaceInternalName = jvmInterfaceType.internalName
|
||||
|
||||
superInterfaces.add(jvmInterfaceInternalName)
|
||||
|
||||
val kotlinMarkerInterfaceInternalName = KOTLIN_MARKER_INTERFACES.get(kotlinInterfaceName)
|
||||
if (kotlinMarkerInterfaceInternalName != null) {
|
||||
if (typeMapper.classBuilderMode === ClassBuilderMode.LIGHT_CLASSES) {
|
||||
sw.writeInterface()
|
||||
val kotlinCollectionType =
|
||||
typeMapper.mapType(superClass.defaultType, sw, TypeMappingMode.SUPER_TYPE_KOTLIN_COLLECTIONS_AS_IS)
|
||||
sw.writeInterfaceEnd()
|
||||
superInterfaces.add(kotlinCollectionType.internalName)
|
||||
}
|
||||
|
||||
kotlinMarkerInterfaces.add(kotlinMarkerInterfaceInternalName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (kotlinMarkerInterface in kotlinMarkerInterfaces) {
|
||||
sw.writeInterface()
|
||||
sw.writeAsmType(Type.getObjectType(kotlinMarkerInterface))
|
||||
sw.writeInterfaceEnd()
|
||||
}
|
||||
|
||||
superInterfaces.addAll(kotlinMarkerInterfaces)
|
||||
|
||||
return JvmClassSignature(
|
||||
classAsmType.internalName, superClassInfo.type.internalName,
|
||||
ArrayList(superInterfaces), sw.makeJavaGenericSignature()
|
||||
)
|
||||
}
|
||||
|
||||
/* Copied with modifications from AsmUtil.getVisibilityAccessFlagForClass */
|
||||
/*
|
||||
Use this method to get visibility flag for class to define it in byte code (v.defineClass method).
|
||||
For other cases use getVisibilityAccessFlag(MemberDescriptor descriptor)
|
||||
Classes in byte code should be public or package private
|
||||
*/
|
||||
fun IrClass.getVisibilityAccessFlagForClass(): Int {
|
||||
/* Original had a check for SyntheticClassDescriptorForJava, never invoked in th IR backend. */
|
||||
if (isOptionalAnnotationClass()) {
|
||||
return AsmUtil.NO_FLAG_PACKAGE_PRIVATE
|
||||
}
|
||||
if (kind == ClassKind.ENUM_ENTRY) {
|
||||
return AsmUtil.NO_FLAG_PACKAGE_PRIVATE
|
||||
}
|
||||
return if (visibility === Visibilities.PUBLIC ||
|
||||
visibility === Visibilities.PROTECTED ||
|
||||
// TODO: should be package private, but for now Kotlin's reflection can't access members of such classes
|
||||
visibility === Visibilities.LOCAL ||
|
||||
visibility === Visibilities.INTERNAL
|
||||
) {
|
||||
Opcodes.ACC_PUBLIC
|
||||
} else AsmUtil.NO_FLAG_PACKAGE_PRIVATE
|
||||
}
|
||||
|
||||
/* Borrowed and translated from ExpectedActualDeclarationChecker */
|
||||
// TODO: Descriptor-based code also checks for `descriptor.isExpect`; we don't represent expect/actual distinction in IR thus far.
|
||||
fun IrClass.isOptionalAnnotationClass(): Boolean =
|
||||
isAnnotationClass &&
|
||||
hasAnnotation(ExpectedActualDeclarationChecker.OPTIONAL_EXPECTATION_FQ_NAME)
|
||||
|
||||
//@JvmOverloads
|
||||
//fun OtherOriginForIr(element: PsiElement?, descriptor: DeclarationDescriptor? = null) =
|
||||
// if (element == null && descriptor == null)
|
||||
// JvmDeclarationOrigin.NO_ORIGIN
|
||||
// else
|
||||
// object : JvmDeclarationOrigin(JvmDeclarationOriginKind.OTHER, element, descriptor) {
|
||||
// override val element get() =
|
||||
// error("Access to PsiElement")
|
||||
// override val descriptor get() =
|
||||
// error("Access to descriptor")
|
||||
// }
|
||||
|
||||
// JvmDeclarationOrigin(OTHER, element, descriptor)
|
||||
|
||||
|
||||
+10
-8
@@ -18,21 +18,23 @@ 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
|
||||
|
||||
object ArrayIterator : IntrinsicMethod() {
|
||||
override fun toCallable(expression: IrFunctionAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
|
||||
val method = context.state.typeMapper.mapToCallableMethod(expression.descriptor as FunctionDescriptor, false)
|
||||
override fun toCallable(
|
||||
expression: IrFunctionAccessExpression,
|
||||
signature: JvmMethodSignature,
|
||||
context: JvmBackendContext
|
||||
): IrIntrinsicFunction {
|
||||
val method = context.state.typeMapper.mapToCallableMethod(expression.descriptor, false)
|
||||
return IrIntrinsicFunction.create(expression, signature, context, method.owner) {
|
||||
val methodSignature = "(${method.owner.descriptor})${method.returnType.descriptor}"
|
||||
val intrinsicOwner =
|
||||
if (AsmUtil.isPrimitive(method.owner.elementType))
|
||||
"kotlin/jvm/internal/ArrayIteratorsKt"
|
||||
else
|
||||
"kotlin/jvm/internal/ArrayIteratorKt"
|
||||
if (AsmUtil.isPrimitive(method.owner.elementType))
|
||||
"kotlin/jvm/internal/ArrayIteratorsKt"
|
||||
else
|
||||
"kotlin/jvm/internal/ArrayIteratorKt"
|
||||
it.invokestatic(intrinsicOwner, "iterator", methodSignature, false)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -88,7 +88,7 @@ class PrimitiveComparison(
|
||||
private val operatorToken: KtSingleValueToken
|
||||
) : IntrinsicMethod() {
|
||||
override fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo): PromisedValue? {
|
||||
val parameterType = codegen.typeMapper.mapType(primitiveNumberType)
|
||||
val parameterType = codegen.typeMapper.kotlinTypeMapper.mapType(primitiveNumberType)
|
||||
val (left, right) = expression.receiverAndArgs()
|
||||
val a = left.accept(codegen, data).coerce(parameterType).materialized
|
||||
val b = right.accept(codegen, data).coerce(parameterType).materialized
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ abstract class IntrinsicMethod {
|
||||
|
||||
open fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo): PromisedValue? =
|
||||
with(codegen) {
|
||||
val descriptor = typeMapper.mapSignatureSkipGeneric(expression.descriptor)
|
||||
val descriptor = typeMapper.mapSignatureSkipGeneric(expression.symbol.owner)
|
||||
val stackValue = toCallable(expression, descriptor, context).invoke(mv, codegen, data)
|
||||
return object : PromisedValue(mv, stackValue.type) {
|
||||
override fun materialize() = stackValue.put(mv)
|
||||
|
||||
+8
-6
@@ -21,24 +21,26 @@ import org.jetbrains.kotlin.backend.jvm.codegen.BlockInfo
|
||||
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
|
||||
|
||||
object IrEnumValueOf : IntrinsicMethod() {
|
||||
override fun toCallable(expression: IrFunctionAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
|
||||
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;
|
||||
val newSignature = context.state.typeMapper.mapSignatureSkipGeneric(expression.descriptor, OwnerKind.IMPLEMENTATION)
|
||||
val stringType = AsmTypes.JAVA_STRING_TYPE
|
||||
|
||||
return object : IrIntrinsicFunction(expression, newSignature, context, listOf(stringType)) {
|
||||
override fun invoke(v: InstructionAdapter, codegen: ExpressionCodegen, data: BlockInfo): StackValue {
|
||||
v.tconst(enumType)
|
||||
codegen.gen(expression.getValueArgument(0)!!, stringType, data)
|
||||
v.invokestatic("java/lang/Enum", "valueOf", "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;", false);
|
||||
v.invokestatic("java/lang/Enum", "valueOf", "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;", false)
|
||||
v.checkcast(enumType)
|
||||
return StackValue.onStack(enumType)
|
||||
}
|
||||
|
||||
+10
-11
@@ -11,9 +11,8 @@ import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.Callable
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
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.calls.components.isVararg
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
@@ -23,7 +22,7 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import java.util.*
|
||||
|
||||
open class IrIntrinsicFunction(
|
||||
val expression: IrMemberAccessExpression,
|
||||
val expression: IrFunctionAccessExpression,
|
||||
val signature: JvmMethodSignature,
|
||||
val context: JvmBackendContext,
|
||||
val argsTypes: List<Type> = expression.argTypes(context)
|
||||
@@ -80,7 +79,7 @@ open class IrIntrinsicFunction(
|
||||
argument != null ->
|
||||
genArg(argument, codegen, i + offset, data)
|
||||
descriptor.isVararg -> {
|
||||
val parameterType = codegen.typeMapper.mapType(descriptor.type)
|
||||
val parameterType = codegen.typeMapper.kotlinTypeMapper.mapType(descriptor.type)
|
||||
StackValue.operation(parameterType) {
|
||||
it.aconst(0)
|
||||
it.newarray(AsmUtil.correctElementType(parameterType))
|
||||
@@ -98,7 +97,7 @@ open class IrIntrinsicFunction(
|
||||
|
||||
companion object {
|
||||
fun create(
|
||||
expression: IrMemberAccessExpression,
|
||||
expression: IrFunctionAccessExpression,
|
||||
signature: JvmMethodSignature,
|
||||
context: JvmBackendContext,
|
||||
argsTypes: List<Type> = expression.argTypes(context),
|
||||
@@ -111,7 +110,7 @@ open class IrIntrinsicFunction(
|
||||
}
|
||||
|
||||
fun createWithResult(
|
||||
expression: IrMemberAccessExpression, signature: JvmMethodSignature,
|
||||
expression: IrFunctionAccessExpression, signature: JvmMethodSignature,
|
||||
context: JvmBackendContext,
|
||||
argsTypes: List<Type> = expression.argTypes(context),
|
||||
invokeInstruction: IrIntrinsicFunction.(InstructionAdapter) -> Type
|
||||
@@ -123,7 +122,7 @@ open class IrIntrinsicFunction(
|
||||
}
|
||||
|
||||
fun create(
|
||||
expression: IrMemberAccessExpression,
|
||||
expression: IrFunctionAccessExpression,
|
||||
signature: JvmMethodSignature,
|
||||
context: JvmBackendContext,
|
||||
type: Type,
|
||||
@@ -134,17 +133,17 @@ open class IrIntrinsicFunction(
|
||||
}
|
||||
}
|
||||
|
||||
fun IrMemberAccessExpression.argTypes(context: JvmBackendContext): ArrayList<Type> {
|
||||
val callableMethod = context.state.typeMapper.mapToCallableMethod(descriptor as FunctionDescriptor, false)
|
||||
fun IrFunctionAccessExpression.argTypes(context: JvmBackendContext): ArrayList<Type> {
|
||||
val callableMethod = context.state.typeMapper.mapToCallableMethod(descriptor, false)
|
||||
return arrayListOf<Type>().apply {
|
||||
callableMethod.dispatchReceiverType?.let { add(it) }
|
||||
addAll(callableMethod.getAsmMethod().argumentTypes)
|
||||
}
|
||||
}
|
||||
|
||||
fun IrMemberAccessExpression.receiverAndArgs(): List<IrExpression> {
|
||||
fun IrFunctionAccessExpression.receiverAndArgs(): List<IrExpression> {
|
||||
return (arrayListOf(this.dispatchReceiver, this.extensionReceiver) +
|
||||
descriptor.valueParameters.mapIndexed { i, _ -> getValueArgument(i) }).filterNotNull()
|
||||
symbol.owner.valueParameters.mapIndexed { i, _ -> getValueArgument(i) }).filterNotNull()
|
||||
}
|
||||
|
||||
fun List<IrExpression>.asmTypes(context: JvmBackendContext): List<Type> {
|
||||
|
||||
+57
-12
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.backend.jvm.intrinsics
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmSymbols
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrPackageFragment
|
||||
@@ -26,8 +27,8 @@ 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.types.classifierOrNull
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||
import org.jetbrains.kotlin.ir.util.functions
|
||||
@@ -43,18 +44,64 @@ import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
|
||||
|
||||
private val KOTLIN_INTERNAL_IR = FqName("kotlin.internal.ir")
|
||||
private val KOTLIN_JVM = FqName("kotlin.jvm")
|
||||
private val KOTLIN_JVM_INTERNAL_UNSAFE = FqName("kotlin.jvm.internal.unsafe")
|
||||
|
||||
val andandSymbol = irBuiltIns.run { defineOperator(OperatorNames.ANDAND, bool, listOf(bool, bool)) }
|
||||
|
||||
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,
|
||||
Key(KOTLIN_JVM, FqName("T"),"<get-javaClass>", emptyList()) to JavaClassProperty,
|
||||
Key(
|
||||
KOTLIN_JVM,
|
||||
KotlinBuiltIns.FQ_NAMES.kClass.toSafe(),
|
||||
"<get-java>",
|
||||
emptyList()
|
||||
) to KClassJavaProperty,
|
||||
Key(
|
||||
KOTLIN_JVM_INTERNAL_UNSAFE,
|
||||
null,
|
||||
"monitorEnter",
|
||||
listOf(KotlinBuiltIns.FQ_NAMES.any.toSafe())
|
||||
) to MonitorInstruction.MONITOR_ENTER,
|
||||
Key(
|
||||
KOTLIN_JVM_INTERNAL_UNSAFE,
|
||||
null,
|
||||
"monitorExit",
|
||||
listOf(KotlinBuiltIns.FQ_NAMES.any.toSafe())
|
||||
) to MonitorInstruction.MONITOR_EXIT,
|
||||
Key(
|
||||
KOTLIN_JVM,
|
||||
KotlinBuiltIns.FQ_NAMES.array.toSafe(),
|
||||
"isArrayOf",
|
||||
emptyList()
|
||||
) to IsArrayOf,
|
||||
symbols.arrayOf.toKey() to ArrayOf,
|
||||
symbols.extensionToString.toKey() to ToString,
|
||||
symbols.arrayOfNulls.toKey() to NewArray,
|
||||
Key(
|
||||
KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME,
|
||||
KotlinBuiltIns.FQ_NAMES.any.toSafe(),
|
||||
"toString",
|
||||
emptyList()
|
||||
) to ToString,
|
||||
Key(
|
||||
KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME,
|
||||
null,
|
||||
"arrayOfNulls",
|
||||
listOf(KotlinBuiltIns.FQ_NAMES._int.toSafe())
|
||||
) to NewArray,
|
||||
Key(
|
||||
KotlinBuiltIns.FQ_NAMES.cloneable.toSafe(),
|
||||
null,
|
||||
"clone",
|
||||
emptyList()
|
||||
) to Clone,
|
||||
Key(
|
||||
KOTLIN_INTERNAL_IR,
|
||||
null,
|
||||
OperatorNames.ANDAND,
|
||||
listOf(KotlinBuiltIns.FQ_NAMES._boolean.toSafe(), KotlinBuiltIns.FQ_NAMES._boolean.toSafe())
|
||||
) to AndAnd,
|
||||
irBuiltIns.eqeqSymbol.toKey()!! to Equals(KtTokens.EQEQ),
|
||||
irBuiltIns.eqeqeqSymbol.toKey()!! to Equals(KtTokens.EQEQEQ),
|
||||
irBuiltIns.ieee754equalsFunByOperandType[irBuiltIns.float]!!.toKey()!! to Ieee754Equals(Type.FLOAT_TYPE),
|
||||
@@ -63,8 +110,7 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
|
||||
irBuiltIns.enumValueOfSymbol.toKey()!! to IrEnumValueOf,
|
||||
irBuiltIns.noWhenBranchMatchedExceptionSymbol.toKey()!! to IrNoWhenBranchMatchedException,
|
||||
irBuiltIns.illegalArgumentExceptionSymbol.toKey()!! to IrIllegalArgumentException,
|
||||
irBuiltIns.throwNpeSymbol.toKey()!! to ThrowNPE,
|
||||
andandSymbol.toKey() to AndAnd
|
||||
irBuiltIns.throwNpeSymbol.toKey()!! to ThrowNPE
|
||||
) +
|
||||
numberConversionMethods() +
|
||||
unaryFunForPrimitives("plus", UnaryPlus) +
|
||||
@@ -94,7 +140,6 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
|
||||
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)
|
||||
} +
|
||||
@@ -147,7 +192,7 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
|
||||
}
|
||||
|
||||
private fun getParameterFqName(parameter: IrValueParameter?): FqName? =
|
||||
parameter?.type?.safeAs<IrSimpleType>()?.classifier?.owner?.let {
|
||||
parameter?.type?.classifierOrNull?.owner?.let {
|
||||
when (it) {
|
||||
is IrClass -> it.fqNameWhenAvailable
|
||||
is IrTypeParameter -> FqName(it.name.asString())
|
||||
|
||||
@@ -10,7 +10,6 @@ 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.IrFunctionAccessExpression
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
@@ -21,11 +20,11 @@ object NewArray : IntrinsicMethod() {
|
||||
signature: JvmMethodSignature,
|
||||
context: JvmBackendContext
|
||||
): IrIntrinsicFunction {
|
||||
val ktType = expression.type
|
||||
val irType = expression.type
|
||||
return object : IrIntrinsicFunction(expression, signature, context) {
|
||||
override fun invoke(v: InstructionAdapter, codegen: ExpressionCodegen, data: BlockInfo): StackValue {
|
||||
super.invoke(v, codegen, data)
|
||||
codegen.newArrayInstruction(ktType.toKotlinType())
|
||||
codegen.newArrayInstruction(irType)
|
||||
return StackValue.onStack(returnType)
|
||||
}
|
||||
|
||||
|
||||
+1
-25
@@ -44,7 +44,6 @@ import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
@@ -109,7 +108,7 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
|
||||
val vararg = IrVarargImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
context.ir.symbols.array.typeWith(context.irBuiltIns.anyNType),
|
||||
context.irBuiltIns.anyClass.typeWith(),
|
||||
context.irBuiltIns.anyNType,
|
||||
(0 until argumentsCount).map { i -> expression.getValueArgument(i)!! }
|
||||
)
|
||||
val invokeFun = context.ir.symbols.functionN.owner.declarations.single {
|
||||
@@ -596,26 +595,3 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
|
||||
const val MAX_ARGCOUNT_WITHOUT_VARARG = 22
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Move to IrUtils
|
||||
private fun IrType.substitute(substitutionMap: Map<IrTypeParameterSymbol, IrType>): IrType {
|
||||
if (this !is IrSimpleType) return this
|
||||
|
||||
substitutionMap[classifier]?.let { return it }
|
||||
|
||||
val newArguments = arguments.map {
|
||||
if (it is IrTypeProjection) {
|
||||
makeTypeProjection(it.type.substitute(substitutionMap), it.variance)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
|
||||
val newAnnotations = annotations.map { it.deepCopyWithSymbols() }
|
||||
return IrSimpleTypeImpl(
|
||||
classifier,
|
||||
hasQuestionMark,
|
||||
newArguments,
|
||||
newAnnotations
|
||||
)
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
|
||||
/**
|
||||
* Binds the arguments explicitly represented in the IR to the parameters of the accessed function.
|
||||
@@ -281,6 +282,7 @@ val IrClass.isEnumEntry get() = kind == ClassKind.ENUM_ENTRY
|
||||
val IrClass.isInterface get() = kind == ClassKind.INTERFACE
|
||||
val IrClass.isClass get() = kind == ClassKind.CLASS
|
||||
val IrClass.isObject get() = kind == ClassKind.OBJECT
|
||||
val IrClass.isAnonymousObject get() = isClass && name == SpecialNames.NO_NAME_PROVIDED
|
||||
val IrDeclarationWithName.fqNameWhenAvailable: FqName?
|
||||
get() = when (val parent = parent) {
|
||||
is IrDeclarationWithName -> parent.fqNameWhenAvailable?.child(name)
|
||||
@@ -352,6 +354,12 @@ inline fun <reified T : IrDeclaration> IrDeclarationContainer.findDeclaration(pr
|
||||
inline fun <reified T : IrDeclaration> IrDeclarationContainer.filterDeclarations(predicate: (T) -> Boolean): List<T> =
|
||||
declarations.filter { it is T && predicate(it) } as List<T>
|
||||
|
||||
fun IrValueParameter.hasDefaultValue(): Boolean = DFS.ifAny(
|
||||
listOf(this),
|
||||
{ current -> (current.parent as? IrSimpleFunction)?.overriddenSymbols?.map { it.owner.valueParameters[current.index] } ?: listOf() },
|
||||
{ current -> current.defaultValue != null }
|
||||
)
|
||||
|
||||
fun IrValueParameter.copy(newDescriptor: ParameterDescriptor): IrValueParameter {
|
||||
assert(this.descriptor.type == newDescriptor.type)
|
||||
|
||||
|
||||
Vendored
+2
@@ -1,3 +1,5 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// For JVM_IR, NewInference is needed because of KT-26531. See functionExpressionWithThisReferenceNI.kt
|
||||
|
||||
fun Int.thisRef1() = fun () = this
|
||||
fun Int.thisRef2() = fun (): Int {return this}
|
||||
|
||||
Vendored
+36
@@ -0,0 +1,36 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// NewInference needed because of KT-26531
|
||||
|
||||
fun Int.thisRef1() = fun () = this
|
||||
fun Int.thisRef2() = fun (): Int {return this}
|
||||
|
||||
fun <T> T.genericThisRef1() = fun () = this
|
||||
fun <T> T.genericThisRef2() = fun (): T {return this}
|
||||
|
||||
val Int.valThisRef1: () -> Int get() = fun () = this
|
||||
val Int.valThisRef2: () -> Int get() = fun (): Int {return this}
|
||||
|
||||
val <T> T.valGenericThisRef1: ()->T get() = fun () = this
|
||||
val <T> T.valGenericThisRef2: ()->T get() = fun (): T {return this}
|
||||
|
||||
val <T> T.withLabel1: ()->T get() = fun () = this@withLabel1
|
||||
val <T> T.withLabel2: ()->T get() = fun (): T {return this@withLabel2}
|
||||
|
||||
fun box(): String {
|
||||
if (1.thisRef1()() != 1) return "Test 1 failed"
|
||||
if (2.thisRef2()() != 2) return "Test 2 failed"
|
||||
|
||||
if (3.genericThisRef1()() != 3) return "Test 3 failed"
|
||||
if (4.genericThisRef2()() != 4) return "Test 4 failed"
|
||||
|
||||
if (5.valThisRef1() != 5) return "Test 5 failed"
|
||||
if (6.valThisRef2() != 6) return "Test 6 failed"
|
||||
|
||||
if (7.valGenericThisRef1() != 7) return "Test 7 failed"
|
||||
if (8.valGenericThisRef2() != 8) return "Test 8 failed"
|
||||
|
||||
if ("bar".withLabel1() != "bar") return "Test 9 failed"
|
||||
if ("bar".withLabel2() != "bar") return "Test 10 failed"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi
|
||||
// IGNORE_BACKEND: JS, JS_IR, NATIVE
|
||||
// IGNORE_BACKEND: JS, JS_IR, NATIVE, JVM_IR
|
||||
// WITH_REFLECT
|
||||
|
||||
package test
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// WITH_REFLECT
|
||||
|
||||
package test
|
||||
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class C
|
||||
|
||||
fun check(expected: String, actual: KType) {
|
||||
assertEquals(expected, actual.toString())
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
check("kotlin.Any", typeOf<Any>())
|
||||
check("kotlin.String", typeOf<String>())
|
||||
check("kotlin.String?", typeOf<String?>())
|
||||
check("kotlin.Unit", typeOf<Unit>())
|
||||
|
||||
check("test.C", typeOf<C>())
|
||||
check("test.C?", typeOf<C?>())
|
||||
|
||||
check("kotlin.collections.List<kotlin.String>", typeOf<List<String>>())
|
||||
check("kotlin.collections.Map<in kotlin.Number, *>?", typeOf<Map<in Number, *>?>())
|
||||
check("kotlin.Enum<*>", typeOf<Enum<*>>())
|
||||
check("kotlin.Enum<kotlin.annotation.AnnotationRetention>", typeOf<Enum<AnnotationRetention>>())
|
||||
|
||||
check("kotlin.Array<kotlin.Any>", typeOf<Array<Any>>())
|
||||
check("kotlin.Array<*>", typeOf<Array<*>>())
|
||||
check("kotlin.Array<kotlin.IntArray>", typeOf<Array<IntArray>>())
|
||||
check("kotlin.Array<in kotlin.Array<test.C>?>", typeOf<Array<in Array<C>?>>())
|
||||
|
||||
check("kotlin.Int", typeOf<Int>())
|
||||
check("kotlin.Int?", typeOf<Int?>())
|
||||
check("kotlin.Boolean", typeOf<Boolean>())
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
package test
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// Separate test is needed for IR because type arguments of typeOf are computed differently.
|
||||
|
||||
package test
|
||||
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class C
|
||||
|
||||
fun check(expected: String, actual: KType) {
|
||||
assertEquals(expected + " (Kotlin reflection is not available)", actual.toString())
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
check("java.lang.Object", typeOf<Any>())
|
||||
check("java.lang.String", typeOf<String>())
|
||||
check("java.lang.String?", typeOf<String?>())
|
||||
check("kotlin.Unit", typeOf<Unit>())
|
||||
|
||||
check("test.C", typeOf<C>())
|
||||
check("test.C?", typeOf<C?>())
|
||||
|
||||
check("java.util.List<java.lang.String>", typeOf<List<String>>())
|
||||
check("java.util.Map<in java.lang.Number, *>?", typeOf<Map<in Number, *>?>())
|
||||
check("java.lang.Enum<*>", typeOf<Enum<*>>())
|
||||
check("java.lang.Enum<kotlin.annotation.AnnotationRetention>", typeOf<Enum<AnnotationRetention>>())
|
||||
|
||||
check("kotlin.Array<java.lang.Object>", typeOf<Array<Any>>())
|
||||
check("kotlin.Array<*>", typeOf<Array<*>>())
|
||||
check("kotlin.Array<kotlin.IntArray>", typeOf<Array<IntArray>>())
|
||||
check("kotlin.Array<in kotlin.Array<test.C>?>", typeOf<Array<in Array<C>?>>())
|
||||
|
||||
check("int", typeOf<Int>())
|
||||
check("java.lang.Integer?", typeOf<Int?>())
|
||||
check("boolean", typeOf<Boolean>())
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+1
@@ -1,5 +1,6 @@
|
||||
// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
|
||||
package test
|
||||
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// WITH_RUNTIME
|
||||
// Separate test is needed for IR because of different ways type arguments of typeOf are calculated.
|
||||
|
||||
package test
|
||||
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
class C
|
||||
|
||||
fun assertEqual(a: KType, b: KType) {
|
||||
if (a != b || b != a) throw AssertionError("Fail equals: $a != $b")
|
||||
if (a.hashCode() != b.hashCode()) throw AssertionError("Fail hashCode: $a != $b")
|
||||
}
|
||||
|
||||
fun assertNotEqual(a: KType, b: KType) {
|
||||
if (a == b || b == a) throw AssertionError("Fail equals: $a == $b")
|
||||
}
|
||||
|
||||
inline fun <reified A, reified B> equal() {
|
||||
assertEqual(typeOf<A>(), typeOf<B>())
|
||||
}
|
||||
|
||||
inline fun <reified A, reified B> notEqual() {
|
||||
assertNotEqual(typeOf<A>(), typeOf<B>())
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
equal<Any, Any>()
|
||||
equal<Any?, Any?>()
|
||||
equal<String, String>()
|
||||
|
||||
equal<C, C>()
|
||||
equal<C?, C?>()
|
||||
|
||||
equal<List<String>, List<String>>()
|
||||
equal<Enum<AnnotationRetention>, Enum<AnnotationRetention>>()
|
||||
|
||||
equal<Array<Any>, Array<Any>>()
|
||||
equal<Array<IntArray>, Array<IntArray>>()
|
||||
equal<Array<*>, Array<*>>()
|
||||
|
||||
equal<Int, Int>()
|
||||
equal<Int?, Int?>()
|
||||
|
||||
notEqual<Any, Any?>()
|
||||
notEqual<Any, String>()
|
||||
notEqual<List<Any>, List<Any?>>()
|
||||
notEqual<Map<in Number, BooleanArray>, Map<out Number, BooleanArray>>()
|
||||
notEqual<Array<IntArray>, Array<Array<Int>>>()
|
||||
|
||||
return "OK"
|
||||
}
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
class Recursive<T : Recursive<T>> : Generic<PlaceHolder<T>>, MainSupertype
|
||||
open class Simple<T> : Generic<T>, MainSupertype
|
||||
|
||||
+5
@@ -11261,6 +11261,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/functions/functionExpression/functionExpressionWithThisReference.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionExpressionWithThisReferenceNI.kt")
|
||||
public void testFunctionExpressionWithThisReferenceNI() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/functionExpression/functionExpressionWithThisReferenceNI.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionLiteralExpression.kt")
|
||||
public void testFunctionLiteralExpression() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/functionExpression/functionLiteralExpression.kt");
|
||||
|
||||
+5
@@ -11261,6 +11261,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/functions/functionExpression/functionExpressionWithThisReference.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionExpressionWithThisReferenceNI.kt")
|
||||
public void testFunctionExpressionWithThisReferenceNI() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/functionExpression/functionExpressionWithThisReferenceNI.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionLiteralExpression.kt")
|
||||
public void testFunctionLiteralExpression() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/functionExpression/functionLiteralExpression.kt");
|
||||
|
||||
+20
@@ -11266,6 +11266,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/functions/functionExpression/functionExpressionWithThisReference.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionExpressionWithThisReferenceNI.kt")
|
||||
public void testFunctionExpressionWithThisReferenceNI() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/functionExpression/functionExpressionWithThisReferenceNI.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionLiteralExpression.kt")
|
||||
public void testFunctionLiteralExpression() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/functionExpression/functionLiteralExpression.kt");
|
||||
@@ -21724,6 +21729,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/classes.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("classesIR.kt")
|
||||
public void testClassesIR() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/classesIR.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineClasses.kt")
|
||||
public void testInlineClasses() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/inlineClasses.kt");
|
||||
@@ -21756,6 +21766,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/classes.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("classesIR.kt")
|
||||
public void testClassesIR() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/classesIR.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inlineClasses.kt")
|
||||
public void testInlineClasses() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/inlineClasses.kt");
|
||||
@@ -21765,6 +21780,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
public void testTypeReferenceEqualsHashCode() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/typeReferenceEqualsHashCode.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typeReferenceEqualsHashCodeIR.kt")
|
||||
public void testTypeReferenceEqualsHashCodeIR() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/typeReferenceEqualsHashCodeIR.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Generated
+5
@@ -8816,6 +8816,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/functions/functionExpression/functionExpressionWithThisReference.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionExpressionWithThisReferenceNI.kt")
|
||||
public void testFunctionExpressionWithThisReferenceNI() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/functionExpression/functionExpressionWithThisReferenceNI.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionLiteralExpression.kt")
|
||||
public void testFunctionLiteralExpression() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/functionExpression/functionLiteralExpression.kt");
|
||||
|
||||
+5
@@ -9891,6 +9891,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/functions/functionExpression/functionExpressionWithThisReference.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionExpressionWithThisReferenceNI.kt")
|
||||
public void testFunctionExpressionWithThisReferenceNI() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/functionExpression/functionExpressionWithThisReferenceNI.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("functionLiteralExpression.kt")
|
||||
public void testFunctionLiteralExpression() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/functions/functionExpression/functionLiteralExpression.kt");
|
||||
|
||||
Reference in New Issue
Block a user