IR: mostly remove descriptors from codegen

This commit is contained in:
Georgy Bronnikov
2019-04-15 01:29:55 +03:00
parent 9923d956aa
commit bfe148efd5
36 changed files with 1224 additions and 375 deletions
@@ -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) {}
@@ -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
)
}
@@ -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 {
@@ -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)
}
@@ -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
)
@@ -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()
}
@@ -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,
@@ -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)
}
@@ -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&lt;T&gt;, 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)
@@ -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)
}
}
@@ -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
@@ -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)
@@ -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)
}
@@ -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> {
@@ -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)
}
@@ -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)
@@ -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}
@@ -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 -1
View File
@@ -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,5 +1,6 @@
// !USE_EXPERIMENTAL: kotlin.ExperimentalStdlibApi
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM_IR
// WITH_RUNTIME
package test
@@ -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,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
@@ -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");
@@ -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");
@@ -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");
}
}
}
@@ -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");
@@ -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");