Rewrite AnnotationCodegen for IR, removing descriptors

This commit is contained in:
Georgy Bronnikov
2019-03-07 15:50:24 +03:00
parent 8bd6e1b8e4
commit 451cda79de
31 changed files with 841 additions and 64 deletions
@@ -100,6 +100,20 @@ public class ClassFileFactory implements OutputFileCollection {
return answer;
}
@NotNull
public ClassBuilder newVisitor(
@NotNull JvmDeclarationOrigin origin,
@NotNull Type asmType,
@NotNull List<File> sourceFiles
) {
ClassBuilder answer = builderFactory.newClassBuilder(origin);
generators.put(
asmType.getInternalName() + ".class",
new ClassBuilderAndSourceFileList(answer, sourceFiles)
);
return answer;
}
public void done() {
if (!isDone) {
isDone = true;
@@ -38,10 +38,7 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
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.ir.util.DumpIrTreeVisitor
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
@@ -114,6 +111,15 @@ val IrSimpleFunction.isOverridableOrOverrides: Boolean get() = isOverridable ||
val IrClass.isFinalClass: Boolean
get() = modality == Modality.FINAL && kind != ClassKind.ENUM_CLASS
// For an annotation, get the annotation class.
fun IrCall.getAnnotationClass(): IrClass {
val callable = symbol.owner
assert(callable is IrConstructor) { "Constructor call expected, got ${ir2string(this)}" }
val annotationClass = callable.parentAsClass
assert(annotationClass.isAnnotationClass) { "Annotation class expected, got ${ir2string(annotationClass)}" }
return annotationClass
}
val IrTypeParametersContainer.classIfConstructor get() = if (this is IrConstructor) parentAsClass else this
fun IrValueParameter.copyTo(
@@ -549,6 +549,8 @@ class LocalDeclarationsLowering(
newDeclaration.valueParameters += createTransformedValueParameters(capturedValues, oldDeclaration, newDeclaration)
newDeclaration.recordTransformedValueParameters(localFunctionContext)
newDeclaration.annotations.addAll(oldDeclaration.annotations)
transformedDeclarations[oldDeclaration] = newDeclaration
}
@@ -84,9 +84,7 @@ class PropertiesLowering(
body = IrBlockBodyImpl(-1, -1)
// TODO: uncomment this and derive annotations from owner in wrapped descriptors
// annotations.addAll(declaration.annotations)
annotations.addAll(declaration.annotations)
metadata = declaration.metadata
}
}
@@ -105,6 +105,7 @@ val jvmPhases = namedIrFilePhase(
foldConstantLoweringPhase then
flattenStringConcatenationPhase then
jvmBuiltinOptimizationLoweringPhase then
additionalClassAnnotationPhase then
makePatchParentsPhase(3)
)
@@ -0,0 +1,317 @@
/*
* Copyright 2010-2019 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.backend.jvm.codegen
import org.jetbrains.annotations.NotNull
import org.jetbrains.annotations.Nullable
import org.jetbrains.kotlin.backend.common.ir.ir2string
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.synthetic.isVisibleOutside
import org.jetbrains.org.objectweb.asm.*
import java.lang.annotation.RetentionPolicy
class AnnotationCodegen(
private val innerClassConsumer: InnerClassConsumer,
state: GenerationState,
private val visitAnnotation: (descriptor: String, visible: Boolean) -> AnnotationVisitor
) {
private val typeMapper = state.typeMapper
/**
* @param returnType can be null if not applicable (e.g. [annotated] is a class)
*/
fun genAnnotations(annotated: IrAnnotationContainer?, returnType: Type?) {
if (annotated == null) return
val annotationDescriptorsAlreadyPresent = mutableSetOf<String>()
val annotations = annotated.annotations
for (annotation in annotations) {
val applicableTargets = annotation.applicableTargetSet()
if (annotated is IrSimpleFunction &&
annotated.origin === IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA &&
KotlinTarget.FUNCTION !in applicableTargets &&
KotlinTarget.PROPERTY_GETTER !in applicableTargets &&
KotlinTarget.PROPERTY_SETTER !in applicableTargets
) {
assert(KotlinTarget.EXPRESSION in applicableTargets) {
"Inconsistent target list for lambda annotation: $applicableTargets on $annotated"
}
continue
}
if (annotated is IrClass &&
KotlinTarget.CLASS !in applicableTargets &&
KotlinTarget.ANNOTATION_CLASS !in applicableTargets
) {
if (annotated.visibility == Visibilities.LOCAL) {
assert(KotlinTarget.EXPRESSION in applicableTargets) {
"Inconsistent target list for object literal annotation: $applicableTargets on $annotated"
}
continue
}
}
genAnnotation(annotation)?.let { descriptor ->
annotationDescriptorsAlreadyPresent.add(descriptor)
}
}
generateAdditionalAnnotations(annotated, returnType, annotationDescriptorsAlreadyPresent)
}
private fun generateAdditionalAnnotations(
annotated: IrAnnotationContainer,
returnType: Type?,
annotationDescriptorsAlreadyPresent: MutableSet<String>
) {
if (annotated is IrDeclaration) {
if (returnType != null && !AsmUtil.isPrimitive(returnType)) {
generateNullabilityAnnotationForCallable(annotated, annotationDescriptorsAlreadyPresent)
}
}
}
private fun generateNullabilityAnnotationForCallable(
declaration: IrDeclaration, // There is no superclass that encompasses IrFunction, IrField and nothing else.
annotationDescriptorsAlreadyPresent: MutableSet<String>
) {
// No need to annotate privates, synthetic accessors and their parameters
if (isInvisibleFromTheOutside(declaration)) return
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 &&
declaration.parentAsClass.isAnnotationClass
) {
return
}
val type = when (declaration) {
is IrFunction -> declaration.returnType
is IrField -> declaration.type
is IrValueDeclaration -> declaration.type
else -> return
}
if (isBareTypeParameterWithNullableUpperBound(type)) {
// This is to account for the case of, say
// class Function<R> { fun invoke(): R }
// it would be a shame to put @Nullable on the return type of the function, and force all callers to check for null,
// so we put no annotations
return
}
val annotationClass = if (type.isNullable()) Nullable::class.java else NotNull::class.java
generateAnnotationIfNotPresent(annotationDescriptorsAlreadyPresent, annotationClass)
}
private fun generateAnnotationIfNotPresent(annotationDescriptorsAlreadyPresent: MutableSet<String>, annotationClass: Class<*>) {
val descriptor = Type.getType(annotationClass).descriptor
if (!annotationDescriptorsAlreadyPresent.contains(descriptor)) {
visitAnnotation(descriptor, false).visitEnd()
}
}
fun generateAnnotationDefaultValue(value: IrExpression) {
val visitor = visitAnnotation("", false) // Parameters are unimportant
genCompileTimeValue(null, value, visitor)
visitor.visitEnd()
}
private fun genAnnotation(annotation: IrCall): String? {
val annotationClass = annotation.annotationClass
val rp = getRetentionPolicy(annotationClass)
if (rp == RetentionPolicy.SOURCE && !typeMapper.classBuilderMode.generateSourceRetentionAnnotations) {
return null
}
innerClassConsumer.addInnerClassInfoFromAnnotation(annotationClass)
val asmTypeDescriptor = typeMapper.mapType(annotation.type.toKotlinType()).descriptor
val annotationVisitor = visitAnnotation(asmTypeDescriptor, rp == RetentionPolicy.RUNTIME)
genAnnotationArguments(annotation, annotationVisitor)
annotationVisitor.visitEnd()
return asmTypeDescriptor
}
private fun genAnnotationArguments(annotation: IrCall, annotationVisitor: AnnotationVisitor) {
val annotationClass = annotation.annotationClass
for (param in annotation.symbol.owner.valueParameters) {
val value = annotation.getValueArgument(param.index)
if (value == null) {
if (param.defaultValue != null) continue // Default value will be supplied by JVM at runtime.
else error("No value for annotation parameter $param")
}
genCompileTimeValue(getAnnotationArgumentJvmName(annotationClass, param.name), value, annotationVisitor)
}
}
private fun getAnnotationArgumentJvmName(annotationClass: IrClass?, parameterName: Name): String {
if (annotationClass == null) return parameterName.asString()
val field =
annotationClass.declarations.filterIsInstance<IrField>().singleOrNull { it.name == parameterName }
?: return parameterName.asString()
return typeMapper.mapAnnotationParameterName(field.descriptor)
}
private fun genCompileTimeValue(
name: String?,
value: IrExpression,
annotationVisitor: AnnotationVisitor
) {
fun visitUnsupportedValue(value: IrExpression) {
val mode = typeMapper.classBuilderMode
if (mode.generateBodies) {
throw IllegalStateException("Don't know how to compile annotation value ${ir2string(value)}")
}
}
when (value) {
is IrConst<*> -> annotationVisitor.visit(name, value.value)
is IrCall -> {
val callee = value.symbol.owner
when {
callee is IrConstructor && callee.parentAsClass.isAnnotationClass -> {
val internalAnnName = typeMapper.mapType(callee.returnType.toKotlinType()).descriptor
val visitor = annotationVisitor.visitAnnotation(name, internalAnnName)
genAnnotationArguments(value, visitor)
visitor.visitEnd()
}
else -> error("Not supported as annotation! ${ir2string(value)}")
}
}
is IrGetEnumValue -> {
val enumClassInternalName = typeMapper.mapClass(value.symbol.owner.parentAsClass.descriptor).descriptor
val enumEntryName = value.symbol.owner.name
annotationVisitor.visitEnum(name, enumClassInternalName, enumEntryName.asString())
}
is IrVararg -> { // array constructor
val visitor = annotationVisitor.visitArray(name)
for (element in value.elements) {
genCompileTimeValue(null, element as IrExpression, visitor)
}
visitor.visitEnd()
}
is IrClassReference -> {
annotationVisitor.visit(name, typeMapper.mapType(value.classType.toKotlinType()))
}
is IrErrorExpression -> visitUnsupportedValue(value)
else -> error("Unsupported compiletime value ${ir2string(value)}")
}
}
companion object {
private fun isInvisibleFromTheOutside(declaration: IrDeclaration?): Boolean {
if (declaration is IrSimpleFunction && declaration.origin === JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR) {
return true
}
if (declaration is IrDeclarationWithVisibility) {
return !declaration.visibility.isVisibleOutside()
}
return false
}
private val annotationRetentionMap = mapOf(
KotlinRetention.SOURCE to RetentionPolicy.SOURCE,
KotlinRetention.BINARY to RetentionPolicy.CLASS,
KotlinRetention.RUNTIME to RetentionPolicy.RUNTIME
)
private fun getRetentionPolicy(irClass: IrClass): RetentionPolicy {
val retention = irClass.getAnnotationRetention()
if (retention != null) {
return annotationRetentionMap[retention]!!
}
irClass.getAnnotation(FqName(java.lang.annotation.Retention::class.java.name))?.let { retentionAnnotation ->
val value = retentionAnnotation.getValueArgument(0)
if (value is IrEnumEntry) {
val enumClassFqName = value.parentAsClass.fqNameWhenAvailable
if (RetentionPolicy::class.java.name == enumClassFqName?.asString()) {
return RetentionPolicy.valueOf(value.name.asString())
}
}
}
return RetentionPolicy.RUNTIME
}
/* Temporary? */
fun IrCall.applicableTargetSet() =
annotationClass.applicableTargetSet() ?: KotlinTarget.DEFAULT_TARGET_SET
val IrCall.annotationClass get() = symbol.owner.parentAsClass
}
}
interface InnerClassConsumer {
fun addInnerClassInfoFromAnnotation(irClass: IrClass)
}
private fun isBareTypeParameterWithNullableUpperBound(type: IrType): Boolean {
return type.classifierOrNull?.owner is IrTypeParameter && !type.isMarkedNullable() && type.isNullable()
}
private val RETENTION_PARAMETER_NAME = Name.identifier("value")
private fun IrClass.getAnnotationRetention(): KotlinRetention? {
val retentionArgument =
getAnnotation(KotlinBuiltIns.FQ_NAMES.retention)?.getValueArgument(RETENTION_PARAMETER_NAME)
as? IrGetEnumValue?: return null
val retentionArgumentValue = retentionArgument.symbol.owner
return KotlinRetention.valueOf(retentionArgumentValue.name.asString())
}
// To be generalized to IrMemberAccessExpression as soon as properties get symbols.
private fun IrCall.getValueArgument(name: Name): IrExpression? {
val index = symbol.owner.valueParameters.find { it.name == name }?.index ?: return null
return getValueArgument(index)
}
// Copied and modified from AnnotationChecker.kt
private val TARGET_ALLOWED_TARGETS = Name.identifier("allowedTargets")
private fun IrClass.applicableTargetSet(): Set<KotlinTarget>? {
val targetEntry = getAnnotation(KotlinBuiltIns.FQ_NAMES.target) ?: return null
return loadAnnotationTargets(targetEntry)
}
private fun loadAnnotationTargets(targetEntry: IrCall): Set<KotlinTarget>? {
val valueArgument = targetEntry.getValueArgument(TARGET_ALLOWED_TARGETS)
as? IrVararg ?: return null
return valueArgument.elements.filterIsInstance<IrGetEnumValue>().mapNotNull {
KotlinTarget.valueOrNull(it.symbol.owner.name.asString())
}.toSet()
}
@@ -103,7 +103,7 @@ open class ClassCodegen protected constructor(
signature.superclassName,
signature.interfaces.toTypedArray()
)
AnnotationCodegen.forClass(visitor.visitor, this, context.state).genAnnotations(descriptor, null)
AnnotationCodegen(this, context.state, visitor.visitor::visitAnnotation).genAnnotations(irClass, null)
/* TODO: Temporary workaround: ClassBuilder needs a pathless name. */
val shortName = File(fileEntry.name).name
visitor.visitSource(shortName, null)
@@ -222,9 +222,7 @@ open class ClassCodegen protected constructor(
fieldSignature, null/*TODO support default values*/
)
if (field.origin == IrDeclarationOrigin.FIELD_FOR_ENUM_ENTRY) {
AnnotationCodegen.forField(fv, this, state).genAnnotations(field.descriptor, null)
}
AnnotationCodegen(this, state, fv::visitAnnotation).genAnnotations(field, fieldType)
val descriptor = field.metadata?.descriptor
if (descriptor != null) {
@@ -295,8 +293,8 @@ open class ClassCodegen protected constructor(
// It's necessary for proper recovering of classId by plain string JVM descriptor when loading annotations
// See FileBasedKotlinClass.convertAnnotationVisitor
override fun addInnerClassInfoFromAnnotation(classDescriptor: ClassDescriptor) {
var current: DeclarationDescriptor? = classDescriptor
override fun addInnerClassInfoFromAnnotation(irClass: IrClass) {
var current: DeclarationDescriptor? = irClass.descriptor
while (current != null && !isTopLevelDeclaration(current)) {
if (current is ClassDescriptor) {
innerClasses.add(current)
@@ -575,7 +575,7 @@ class ExpressionCodegen(
val hasSpread = arguments.firstIsInstanceOrNull<IrSpreadElement>() != null
if (hasSpread) {
val arrayOfReferences = KotlinBuiltIns.isArray(outType.toKotlinType()!!)
val arrayOfReferences = KotlinBuiltIns.isArray(outType.toKotlinType())
if (size == 1) {
// Arrays.copyOf(receiverValue, newLength)
val argument = (arguments[0] as IrSpreadElement).expression
@@ -633,7 +633,7 @@ class ExpressionCodegen(
} else {
mv.iconst(size)
newArrayInstruction(expression.type.toKotlinType())
val elementKotlinType = classCodegen.context.builtIns.getArrayElementType(outType.toKotlinType()!!)
val elementKotlinType = classCodegen.context.builtIns.getArrayElementType(outType.toKotlinType())
for ((i, element) in expression.elements.withIndex()) {
mv.dup()
StackValue.constant(i).put(mv)
@@ -10,18 +10,19 @@ 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.dump
import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.ir.util.isAnnotationClass
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.resolve.source.getPsi
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.commons.InstructionAdapter
@@ -46,8 +47,8 @@ open class FunctionCodegen(private val irFunction: IrFunction, private val class
val methodVisitor = createMethod(flags, signature)
if (irFunction.origin != IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER) {
AnnotationCodegen.forMethod(methodVisitor, classCodegen, state).genAnnotations(descriptor, signature.asmMethod.returnType)
FunctionCodegen.generateParameterAnnotations(descriptor, methodVisitor, signature, classCodegen, state)
AnnotationCodegen(classCodegen, state, methodVisitor::visitAnnotation).genAnnotations(irFunction, signature.asmMethod.returnType)
FunctionCodegen.generateParameterAnnotations(descriptor, methodVisitor, signature, DummyOldInnerClassConsumer(), state)
}
if (!state.classBuilderMode.generateBodies || flags.and(Opcodes.ACC_ABSTRACT) != 0 || irFunction.isExternal) {
@@ -105,21 +106,25 @@ open class FunctionCodegen(private val irFunction: IrFunction, private val class
}
private fun generateAnnotationDefaultValueIfNeeded(methodVisitor: MethodVisitor) {
if (classCodegen.irClass.isAnnotationClass) {
val source = JvmCodegenUtil.getDirectMember(descriptor).source
(source.getPsi() as? KtParameter)?.defaultValue?.apply {
val defaultValue = this
val constant = org.jetbrains.kotlin.codegen.ExpressionCodegen.getCompileTimeConstant(
defaultValue, state.bindingContext, true, state.shouldInlineConstVals
)
assert(!state.classBuilderMode.generateBodies || constant != null) { "Default value for annotation parameter should be compile time value: " + defaultValue.text }
if (constant != null) {
val annotationCodegen = AnnotationCodegen.forAnnotationDefaultValue(methodVisitor, classCodegen, state)
annotationCodegen.generateAnnotationDefaultValue(constant, descriptor.returnType!!)
}
}
getAnnotationDefaultValueExpression()?.let { defaultValueExpression ->
val annotationCodegen = AnnotationCodegen(classCodegen, state) { _, _ -> methodVisitor.visitAnnotationDefault() }
annotationCodegen.generateAnnotationDefaultValue(defaultValueExpression)
}
}
private fun getAnnotationDefaultValueExpression(): IrExpression? {
if (!classCodegen.irClass.isAnnotationClass) return null
// 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
?.backingField
?.initializer.safeAs<IrExpressionBody>()
?.expression?.safeAs<IrGetValue>()
?.symbol?.owner?.safeAs<IrValueParameter>()
?.defaultValue?.safeAs<IrExpressionBody>()
?.expression
}
}
private fun createFrameMapWithReceivers(
@@ -153,3 +158,13 @@ private fun createFrameMapWithReceivers(
return frameMap
}
/**/// TODO: temporary, to allow calling the old FunctionCodegen.generateParameterAnnotations
private class DummyOldInnerClassConsumer()
: org.jetbrains.kotlin.codegen.InnerClassConsumer {
override fun addInnerClassInfoFromAnnotation(classDescriptor: ClassDescriptor) {
}
}
@@ -0,0 +1,247 @@
/*
* 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.lower
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.descriptors.WrappedEnumEntryDescriptor
import org.jetbrains.kotlin.backend.common.ir.addChild
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
import org.jetbrains.kotlin.ir.builders.declarations.buildClass
import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor
import org.jetbrains.kotlin.ir.builders.declarations.buildValueParameter
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrEnumEntryImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetEnumValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrEnumEntrySymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
internal val additionalClassAnnotationPhase = makeIrFilePhase(
::AdditionalClassAnnotationLowering,
name = "AdditionalClassAnnotation",
description = "Add Documented, Retention and Target annotations to annotation classes"
)
private class AdditionalClassAnnotationLowering(private val context: JvmBackendContext) : ClassLoweringPass {
val typeMapper = context.state.typeMapper
// TODO: import IR structures from the library?
private val annotationPackage: IrPackageFragment = IrExternalPackageFragmentImpl(
IrExternalPackageFragmentSymbolImpl(
EmptyPackageFragmentDescriptor(
context.ir.irModule.descriptor,
FqName("java.lang.annotation")
)
)
)
private fun buildAnnotationClass(
className: String,
classKind: ClassKind = ClassKind.ANNOTATION_CLASS
): IrClass = buildClass {
name = Name.identifier(className)
kind = classKind
}.apply {
val irClass = this
parent = annotationPackage
annotationPackage.addChild(this)
thisReceiver = buildValueParameter {
name = Name.identifier("\$this")
type = IrSimpleTypeImpl(irClass.symbol, false, emptyList(), emptyList())
}
}
private fun buildAnnotationConstructor(annotationClass: IrClass): IrConstructor = buildConstructor {
isPrimary = true
}.apply {
parent = annotationClass
annotationClass.addChild(this)
returnType = annotationClass.defaultType
}
private fun buildEnumEntry(enumClass: IrClass, entryName: String): IrEnumEntry = IrEnumEntryImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB,
IrEnumEntrySymbolImpl(WrappedEnumEntryDescriptor()),
Name.identifier(entryName)
).apply {
(descriptor as WrappedEnumEntryDescriptor).bind(this)
parent = enumClass
enumClass.addChild(this)
}
private val documentedConstructor = buildAnnotationConstructor(buildAnnotationClass("Documented"))
private val retentionPolicyEnum = buildAnnotationClass("RetentionPolicy", classKind = ClassKind.ENUM_CLASS)
private val rpSource = buildEnumEntry(retentionPolicyEnum, "SOURCE")
private val rpClass = buildEnumEntry(retentionPolicyEnum, "CLASS")
private val rpRuntime = buildEnumEntry(retentionPolicyEnum, "RUNTIME")
private val retentionConstructor = buildAnnotationConstructor(buildAnnotationClass("Retention")).apply {
addValueParameter(Name.identifier("value"), retentionPolicyEnum.defaultType, IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB)
}
private val elementTypeEnum = buildAnnotationClass("ElementType", classKind = ClassKind.ENUM_CLASS)
private val etAnnotationType = buildEnumEntry(elementTypeEnum, "ANNOTATION_TYPE")
private val etConstructor = buildEnumEntry(elementTypeEnum, "CONSTRUCTOR")
private val etField = buildEnumEntry(elementTypeEnum, "FIELD")
private val etLocalVariable = buildEnumEntry(elementTypeEnum, "LOCAL_VARIABLE")
private val etMethod = buildEnumEntry(elementTypeEnum, "METHOD")
private val etPackage = buildEnumEntry(elementTypeEnum, "PACKAGE")
private val etParameter = buildEnumEntry(elementTypeEnum, "PARAMETER")
private val etType = buildEnumEntry(elementTypeEnum, "TYPE")
private val etTypeParameter = buildEnumEntry(elementTypeEnum, "TYPE_PARAMETER")
private val etTypeUse = buildEnumEntry(elementTypeEnum, "TYPE_USE")
private val targetConstructor = buildAnnotationConstructor(buildAnnotationClass("Target")).apply {
addValueParameter(Name.identifier("value"), elementTypeEnum.defaultType, IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB)
}
override fun lower(irClass: IrClass) {
if (!irClass.isAnnotationClass) return
generateDocumentedAnnotation(irClass)
generateRetentionAnnotation(irClass)
generateTargetAnnotation(irClass)
}
private fun generateDocumentedAnnotation(irClass: IrClass) {
if (irClass.hasAnnotation(KotlinBuiltIns.FQ_NAMES.mustBeDocumented) &&
!irClass.hasAnnotation(FqName("java.lang.annotation.Documented"))
) {
return
}
irClass.annotations.add(
IrCallImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, documentedConstructor.returnType, documentedConstructor.symbol
)
)
}
private val annotationRetentionMap = mapOf(
KotlinRetention.SOURCE to rpSource,
KotlinRetention.BINARY to rpClass,
KotlinRetention.RUNTIME to rpRuntime
)
private fun generateRetentionAnnotation(irClass: IrClass) {
if (irClass.hasAnnotation(FqName("java.lang.annotation.Retention"))) return
val kotlinRetentionPolicy = irClass.getAnnotation(FqName("kotlin.annotation.Retention"))
val javaRetentionPolicy = annotationRetentionMap[kotlinRetentionPolicy] ?: rpRuntime
irClass.annotations.add(
IrCallImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, retentionConstructor.returnType, retentionConstructor.symbol
).apply {
putValueArgument(
0,
IrGetEnumValueImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, retentionPolicyEnum.defaultType, javaRetentionPolicy.symbol
)
)
}
)
}
private val annotationTargetMaps: Map<JvmTarget, MutableMap<KotlinTarget, IrEnumEntry>> =
mapOf(
JvmTarget.JVM_1_6 to mutableMapOf(
KotlinTarget.CLASS to etType,
KotlinTarget.ANNOTATION_CLASS to etAnnotationType,
KotlinTarget.CONSTRUCTOR to etConstructor,
KotlinTarget.LOCAL_VARIABLE to etLocalVariable,
KotlinTarget.FUNCTION to etMethod,
KotlinTarget.PROPERTY_GETTER to etMethod,
KotlinTarget.PROPERTY_SETTER to etMethod,
KotlinTarget.FIELD to etField,
KotlinTarget.VALUE_PARAMETER to etParameter
),
// additional values for jvm8
JvmTarget.JVM_1_8 to mutableMapOf(
KotlinTarget.TYPE_PARAMETER to etTypeParameter,
KotlinTarget.TYPE to etTypeUse
)
)
init {
annotationTargetMaps[JvmTarget.JVM_1_8]!!.putAll(annotationTargetMaps[JvmTarget.JVM_1_6]!!.toList())
}
private fun generateTargetAnnotation(irClass: IrClass) {
if (irClass.hasAnnotation(FqName("java.lang.annotation.Target"))) return
val annotationTargetMap = annotationTargetMaps[typeMapper.jvmTarget]
?: throw AssertionError("No annotation target map for JVM target ${typeMapper.jvmTarget}")
val targets = irClass.applicableTargetSet() ?: return
val javaTargets = targets.mapNotNull { annotationTargetMap[it] }
val vararg = IrVarargImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
type = context.irBuiltIns.arrayClass.typeWith(elementTypeEnum.defaultType),
varargElementType = elementTypeEnum.defaultType
)
for (target in javaTargets) {
vararg.elements.add(
IrGetEnumValueImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, elementTypeEnum.defaultType, target.symbol
)
)
}
irClass.annotations.add(
IrCallImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, targetConstructor.returnType, targetConstructor.symbol
).apply {
putValueArgument(0, vararg)
}
)
// TODO
}
}
// To be generalized to IrMemberAccessExpression as soon as properties get symbols.
private fun IrCall.getValueArgument(name: Name): IrExpression? {
val index = symbol.owner.valueParameters.find { it.name == name }?.index ?: return null
return getValueArgument(index)
}
// Copied and modified from AnnotationChecker.kt
private val TARGET_ALLOWED_TARGETS = Name.identifier("allowedTargets")
private fun IrClass.applicableTargetSet(): Set<KotlinTarget>? {
val targetEntry = getAnnotation(KotlinBuiltIns.FQ_NAMES.target) ?: return null
return loadAnnotationTargets(targetEntry)
}
private fun loadAnnotationTargets(targetEntry: IrCall): Set<KotlinTarget>? {
val valueArgument = targetEntry.getValueArgument(TARGET_ALLOWED_TARGETS)
as? IrVararg ?: return null
return valueArgument.elements.filterIsInstance<IrGetEnumValue>().mapNotNull {
KotlinTarget.valueOrNull(it.symbol.owner.name.asString())
}.toSet()
}
@@ -346,6 +346,8 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
val function = this
parent = functionReferenceClass
overriddenSymbols.add(superFunction.symbol)
annotations.addAll(callee.annotations)
dispatchReceiverParameter = functionReferenceClass.thisReceiver?.copyTo(function)
val unboundArgsSet = unboundCalleeParameters.toSet()
@@ -220,6 +220,7 @@ private class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringP
enumEntry, (enumEntry.correspondingClass ?: enumEntry.parentAsClass).defaultType
).also {
it.initializer = IrExpressionBodyImpl(enumEntry.initializerExpression!!)
it.annotations.addAll(enumEntry.annotations)
enumEntryFields.add(it)
enumEntriesByField[it] = enumEntry
}
@@ -134,6 +134,7 @@ private class InterfaceDelegationLowering(val context: JvmBackendContext) : IrEl
parent = inheritedFun.parent
overriddenSymbols.addAll(inheritedFun.overriddenSymbols)
copyParameterDeclarationsFrom(inheritedFun)
annotations.addAll(inheritedFun.annotations)
}
} else context.declarationFactory.getDefaultImplsFunction(inheritedFun)
@@ -167,10 +167,12 @@ private class SingletonObjectJvmStaticLowering(
irClass.declarations.filter(::isJvmStaticFunction).forEach {
val jvmStaticFunction = it as IrSimpleFunction
val oldDispatchReceiverParameter = jvmStaticFunction.dispatchReceiverParameter!!
jvmStaticFunction.dispatchReceiverParameter = null
modifyBody(jvmStaticFunction, irClass, oldDispatchReceiverParameter)
functionsMadeStatic.add(jvmStaticFunction.symbol)
// dispatch receiver parameter is already null for synthetic property annotation methods
jvmStaticFunction.dispatchReceiverParameter?.let { oldDispatchReceiverParameter ->
jvmStaticFunction.dispatchReceiverParameter = null
modifyBody(jvmStaticFunction, irClass, oldDispatchReceiverParameter)
functionsMadeStatic.add(jvmStaticFunction.symbol)
}
}
}
@@ -18,10 +18,12 @@ package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
import org.jetbrains.kotlin.ir.expressions.IrBody
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.util.declareSimpleFunctionWithOverrides
import org.jetbrains.kotlin.psi.*
@@ -31,7 +33,10 @@ import org.jetbrains.kotlin.psi2ir.isConstructorDelegatingToSuper
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
import org.jetbrains.kotlin.resolve.descriptorUtil.isAnnotationConstructor
import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class FunctionGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGeneratorExtension(declarationGenerator) {
@@ -114,10 +119,10 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
generateValueParameterDeclarations(irAccessor, ktAccessor ?: ktProperty, ktProperty.receiverTypeReference)
val ktBodyExpression = ktAccessor?.bodyExpression
irAccessor.body =
if (ktBodyExpression != null)
createBodyGenerator(irAccessor.symbol).generateFunctionBody(ktBodyExpression)
else
generateDefaultAccessorBody(descriptor, irAccessor)
if (ktBodyExpression != null)
createBodyGenerator(irAccessor.symbol).generateFunctionBody(ktBodyExpression)
else
generateDefaultAccessorBody(descriptor, irAccessor)
}
fun generateDefaultAccessorForPrimaryConstructorParameter(
@@ -299,8 +304,13 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
): IrValueParameter =
declareParameter(valueParameterDescriptor, ktParameter, irOwnerElement).also { irValueParameter ->
if (withDefaultValues) {
irValueParameter.defaultValue = ktParameter?.defaultValue?.let {
bodyGenerator.generateExpressionBody(it)
irValueParameter.defaultValue = ktParameter?.defaultValue?.let { defaultValue ->
val inAnnotation =
valueParameterDescriptor.containingDeclaration.safeAs<ConstructorDescriptor>()?.isAnnotationConstructor() ?: false
if (inAnnotation) {
generateDefaultAnnotationParameterValue(defaultValue, valueParameterDescriptor)
} else
bodyGenerator.generateExpressionBody(defaultValue)
}
}
}
@@ -320,4 +330,19 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
descriptor, descriptor.type.toIrType(),
(descriptor as? ValueParameterDescriptor)?.varargElementType?.toIrType()
)
private fun generateDefaultAnnotationParameterValue(
valueExpression: KtExpression,
valueParameterDescriptor: ValueParameterDescriptor
): IrExpressionBody {
val constantDefaultValue =
ConstantExpressionEvaluator.getConstant(valueExpression, context.bindingContext)?.toConstantValue(valueParameterDescriptor.type)
?: error("Constant value expected for default parameter value in annotation, got $valueExpression")
return IrExpressionBodyImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
context.constantValueGenerator.generateConstantValueAsExpression(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, constantDefaultValue, valueParameterDescriptor.varargElementType
)
)
}
}
@@ -66,8 +66,6 @@ class IrLazyClass(
symbol.bind(this)
}
override val annotations: MutableList<IrCall> = arrayListOf()
override val descriptor: ClassDescriptor get() = symbol.descriptor
override var thisReceiver: IrValueParameter? by lazyVar {
@@ -50,7 +50,11 @@ abstract class IrLazyDeclarationBase(
createLazyParent()!!
}
override val annotations: MutableList<IrCall> = arrayListOf()
override val annotations: MutableList<IrCall> by lazy {
descriptor.annotations.map {
typeTranslator.constantValueGenerator.generateAnnotationConstructorCall(it)
}.toMutableList()
}
override var metadata: Nothing?
get() = null
@@ -14,10 +14,12 @@ import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.constants.*
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
import org.jetbrains.kotlin.resolve.source.PsiSourceFile
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -116,8 +118,8 @@ class ConstantValueGenerator(
val primaryConstructorSymbol = symbolTable.referenceConstructor(primaryConstructorDescriptor)
val psi = annotationDescriptor.source.safeAs<PsiSourceElement>()?.psi
val startOffset = psi?.startOffset ?: UNDEFINED_OFFSET
val endOffset = psi?.startOffset ?: UNDEFINED_OFFSET
val startOffset = psi?.takeUnless { it.containingFile.fileType.isBinary }?.startOffset ?: UNDEFINED_OFFSET
val endOffset = psi?.takeUnless { it.containingFile.fileType.isBinary }?.endOffset ?: UNDEFINED_OFFSET
val irCall = IrCallImpl(
startOffset, endOffset,
@@ -19,6 +19,8 @@ import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.types.isAny
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
@@ -278,6 +280,12 @@ 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 IrDeclarationWithName.fqNameWhenAvailable: FqName?
get() = when (val parent = parent) {
is IrDeclarationWithName -> parent.fqNameWhenAvailable?.child(name)
is IrPackageFragment -> parent.fqName.child(name)
else -> null
}
val IrDeclaration.parentAsClass get() = parent as IrClass
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// TARGET_BACKEND: JVM
// WITH_RUNTIME
+46
View File
@@ -0,0 +1,46 @@
// IGNORE_BACKEND: JS_IR
// TODO: muted automatically, investigate should it be ran for JS or not
// IGNORE_BACKEND: JS, NATIVE
// WITH_REFLECT
import kotlin.test.assertEquals
import kotlin.reflect.KClass
enum class E { E0 }
annotation class A
@Retention(AnnotationRetention.RUNTIME)
annotation class Anno(
val s: String,
val i: Int,
val f: Double,
val u: UInt,
val e: E,
val a: A,
val k: KClass<*>,
val arr: Array<String>,
val intArr: IntArray,
val arrOfE: Array<E>,
val arrOfA: Array<A>
)
@Anno("OK", 42, 2.718281828, 43u, E.E0, A(), A::class, emptyArray(), intArrayOf(1, 2), arrayOf(E.E0), arrayOf(A()))
class TTT
fun box(): String {
val anno = TTT::class.annotations.single() as Anno
assertEquals(anno.s, "OK")
assertEquals(anno.i, 42)
assert(anno.f > 2.0 && anno.f < 3.0)
assertEquals(anno.u, 43u)
assertEquals(anno.e, E.E0)
assert(anno.a is A)
// TODO: problems with KClass/Class conversion in JVM_IR, unrelated to annotation codegen
// assert(anno.k == A::class.java)
assert(anno.arr.isEmpty())
assert(anno.intArr.contentEquals(intArrayOf(1, 2)))
assert(anno.arrOfE.contentEquals(arrayOf(E.E0)))
assert(anno.arrOfA.size == 1)
return "OK"
}
@@ -1,4 +1,5 @@
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM_IR
// WITH_REFLECT
package test
@@ -1,5 +1,4 @@
// !LANGUAGE: +MultiPlatformProjects
// IGNORE_BACKEND: JVM_IR
// TARGET_BACKEND: JVM
// WITH_RUNTIME
// FILE: common.kt
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// TARGET_BACKEND: JVM
// WITH_RUNTIME
@@ -1,4 +1,5 @@
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM_IR
// FILE: A.kt
package lib
@@ -78,22 +78,64 @@ CLASS IR_EXTERNAL_DECLARATION_STUB CLASS name:Int modality:FINAL visibility:publ
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:<unbound IrClassSymbolImpl>
FUN IR_EXTERNAL_DECLARATION_STUB name:mod visibility:public modality:FINAL <> ($this:kotlin.Int, other:<unbound IrClassSymbolImpl>) returnType:kotlin.Int
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
annotations:
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
1: CONST String type=<unbound IrClassSymbolImpl> value="Use rem(other) instead"
2: CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
1: CONST String type=<unbound IrClassSymbolImpl> value="rem(other)"
2: VARARG type=<unbound IrClassSymbolImpl><out <unbound IrClassSymbolImpl>> varargElementType=<unbound IrClassSymbolImpl>
3: GET_ENUM 'UNBOUND IrEnumEntrySymbolImpl' type=<unbound IrClassSymbolImpl>
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:<unbound IrClassSymbolImpl>
FUN IR_EXTERNAL_DECLARATION_STUB name:mod visibility:public modality:FINAL <> ($this:kotlin.Int, other:<unbound IrClassSymbolImpl>) returnType:<unbound IrClassSymbolImpl>
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
annotations:
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
1: CONST String type=<unbound IrClassSymbolImpl> value="Use rem(other) instead"
2: CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
1: CONST String type=<unbound IrClassSymbolImpl> value="rem(other)"
2: VARARG type=<unbound IrClassSymbolImpl><out <unbound IrClassSymbolImpl>> varargElementType=<unbound IrClassSymbolImpl>
3: GET_ENUM 'UNBOUND IrEnumEntrySymbolImpl' type=<unbound IrClassSymbolImpl>
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:<unbound IrClassSymbolImpl>
FUN IR_EXTERNAL_DECLARATION_STUB name:mod visibility:public modality:FINAL <> ($this:kotlin.Int, other:<unbound IrClassSymbolImpl>) returnType:<unbound IrClassSymbolImpl>
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
annotations:
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
1: CONST String type=<unbound IrClassSymbolImpl> value="Use rem(other) instead"
2: CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
1: CONST String type=<unbound IrClassSymbolImpl> value="rem(other)"
2: VARARG type=<unbound IrClassSymbolImpl><out <unbound IrClassSymbolImpl>> varargElementType=<unbound IrClassSymbolImpl>
3: GET_ENUM 'UNBOUND IrEnumEntrySymbolImpl' type=<unbound IrClassSymbolImpl>
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:<unbound IrClassSymbolImpl>
FUN IR_EXTERNAL_DECLARATION_STUB name:mod visibility:public modality:FINAL <> ($this:kotlin.Int, other:kotlin.Int) returnType:kotlin.Int
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
annotations:
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
1: CONST String type=<unbound IrClassSymbolImpl> value="Use rem(other) instead"
2: CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
1: CONST String type=<unbound IrClassSymbolImpl> value="rem(other)"
2: VARARG type=<unbound IrClassSymbolImpl><out <unbound IrClassSymbolImpl>> varargElementType=<unbound IrClassSymbolImpl>
3: GET_ENUM 'UNBOUND IrEnumEntrySymbolImpl' type=<unbound IrClassSymbolImpl>
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:kotlin.Int
FUN IR_EXTERNAL_DECLARATION_STUB name:mod visibility:public modality:FINAL <> ($this:kotlin.Int, other:<unbound IrClassSymbolImpl>) returnType:<unbound IrClassSymbolImpl>
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
annotations:
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
1: CONST String type=<unbound IrClassSymbolImpl> value="Use rem(other) instead"
2: CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
1: CONST String type=<unbound IrClassSymbolImpl> value="rem(other)"
2: VARARG type=<unbound IrClassSymbolImpl><out <unbound IrClassSymbolImpl>> varargElementType=<unbound IrClassSymbolImpl>
3: GET_ENUM 'UNBOUND IrEnumEntrySymbolImpl' type=<unbound IrClassSymbolImpl>
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:<unbound IrClassSymbolImpl>
FUN IR_EXTERNAL_DECLARATION_STUB name:mod visibility:public modality:FINAL <> ($this:kotlin.Int, other:<unbound IrClassSymbolImpl>) returnType:kotlin.Int
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
annotations:
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
1: CONST String type=<unbound IrClassSymbolImpl> value="Use rem(other) instead"
2: CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
1: CONST String type=<unbound IrClassSymbolImpl> value="rem(other)"
2: VARARG type=<unbound IrClassSymbolImpl><out <unbound IrClassSymbolImpl>> varargElementType=<unbound IrClassSymbolImpl>
3: GET_ENUM 'UNBOUND IrEnumEntrySymbolImpl' type=<unbound IrClassSymbolImpl>
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:<unbound IrClassSymbolImpl>
FUN IR_EXTERNAL_DECLARATION_STUB name:or visibility:public modality:FINAL <> ($this:kotlin.Int, other:kotlin.Int) returnType:kotlin.Int
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
@@ -129,22 +171,40 @@ CLASS IR_EXTERNAL_DECLARATION_STUB CLASS name:Int modality:FINAL visibility:publ
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:<unbound IrClassSymbolImpl>
FUN IR_EXTERNAL_DECLARATION_STUB name:rem visibility:public modality:FINAL <> ($this:kotlin.Int, other:<unbound IrClassSymbolImpl>) returnType:kotlin.Int
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
annotations:
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
1: CONST String type=<unbound IrClassSymbolImpl> value="1.1"
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:<unbound IrClassSymbolImpl>
FUN IR_EXTERNAL_DECLARATION_STUB name:rem visibility:public modality:FINAL <> ($this:kotlin.Int, other:<unbound IrClassSymbolImpl>) returnType:<unbound IrClassSymbolImpl>
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
annotations:
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
1: CONST String type=<unbound IrClassSymbolImpl> value="1.1"
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:<unbound IrClassSymbolImpl>
FUN IR_EXTERNAL_DECLARATION_STUB name:rem visibility:public modality:FINAL <> ($this:kotlin.Int, other:<unbound IrClassSymbolImpl>) returnType:<unbound IrClassSymbolImpl>
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
annotations:
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
1: CONST String type=<unbound IrClassSymbolImpl> value="1.1"
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:<unbound IrClassSymbolImpl>
FUN IR_EXTERNAL_DECLARATION_STUB name:rem visibility:public modality:FINAL <> ($this:kotlin.Int, other:kotlin.Int) returnType:kotlin.Int
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
annotations:
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
1: CONST String type=<unbound IrClassSymbolImpl> value="1.1"
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:kotlin.Int
FUN IR_EXTERNAL_DECLARATION_STUB name:rem visibility:public modality:FINAL <> ($this:kotlin.Int, other:<unbound IrClassSymbolImpl>) returnType:<unbound IrClassSymbolImpl>
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
annotations:
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
1: CONST String type=<unbound IrClassSymbolImpl> value="1.1"
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:<unbound IrClassSymbolImpl>
FUN IR_EXTERNAL_DECLARATION_STUB name:rem visibility:public modality:FINAL <> ($this:kotlin.Int, other:<unbound IrClassSymbolImpl>) returnType:kotlin.Int
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
annotations:
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
1: CONST String type=<unbound IrClassSymbolImpl> value="1.1"
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:other index:0 type:<unbound IrClassSymbolImpl>
FUN IR_EXTERNAL_DECLARATION_STUB name:shl visibility:public modality:FINAL <> ($this:kotlin.Int, bitCount:kotlin.Int) returnType:kotlin.Int
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int
@@ -231,14 +291,20 @@ CLASS IR_EXTERNAL_DECLARATION_STUB CLASS name:Int modality:FINAL visibility:publ
correspondingProperty: PROPERTY IR_EXTERNAL_DECLARATION_STUB name:MIN_VALUE visibility:public modality:FINAL [const,val]
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int.Companion
PROPERTY IR_EXTERNAL_DECLARATION_STUB name:SIZE_BITS visibility:public modality:FINAL [const,val]
FIELD IR_EXTERNAL_DECLARATION_STUB name:SIZE_BITS type:kotlin.Int visibility:public [final]
annotations:
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
1: CONST String type=<unbound IrClassSymbolImpl> value="1.3"
FIELD IR_EXTERNAL_DECLARATION_STUB name:SIZE_BITS type:kotlin.Int visibility:public [final]
EXPRESSION_BODY
CONST Int type=kotlin.Int value=32
FUN IR_EXTERNAL_DECLARATION_STUB name:<get-SIZE_BITS> visibility:public modality:FINAL <> ($this:kotlin.Int.Companion) returnType:kotlin.Int
correspondingProperty: PROPERTY IR_EXTERNAL_DECLARATION_STUB name:SIZE_BITS visibility:public modality:FINAL [const,val]
$this: VALUE_PARAMETER IR_EXTERNAL_DECLARATION_STUB name:<this> type:kotlin.Int.Companion
PROPERTY IR_EXTERNAL_DECLARATION_STUB name:SIZE_BYTES visibility:public modality:FINAL [const,val]
FIELD IR_EXTERNAL_DECLARATION_STUB name:SIZE_BYTES type:kotlin.Int visibility:public [final]
annotations:
CALL 'UNBOUND IrConstructorSymbolImpl' type=<unbound IrClassSymbolImpl> origin=null
1: CONST String type=<unbound IrClassSymbolImpl> value="1.3"
FIELD IR_EXTERNAL_DECLARATION_STUB name:SIZE_BYTES type:kotlin.Int visibility:public [final]
EXPRESSION_BODY
CONST Int type=kotlin.Int value=4
FUN IR_EXTERNAL_DECLARATION_STUB name:<get-SIZE_BYTES> visibility:public modality:FINAL <> ($this:kotlin.Int.Companion) returnType:kotlin.Int
@@ -141,6 +141,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/annotations/parameterWithPrimitiveType.kt");
}
@TestMetadata("parameters.kt")
public void testParameters() throws Exception {
runTest("compiler/testData/codegen/box/annotations/parameters.kt");
}
@TestMetadata("propertyWithPropertyInInitializerAsParameter.kt")
public void testPropertyWithPropertyInInitializerAsParameter() throws Exception {
runTest("compiler/testData/codegen/box/annotations/propertyWithPropertyInInitializerAsParameter.kt");
@@ -146,6 +146,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/annotations/parameterWithPrimitiveType.kt");
}
@TestMetadata("parameters.kt")
public void testParameters() throws Exception {
runTest("compiler/testData/codegen/box/annotations/parameters.kt");
}
@TestMetadata("propertyWithPropertyInInitializerAsParameter.kt")
public void testPropertyWithPropertyInInitializerAsParameter() throws Exception {
runTest("compiler/testData/codegen/box/annotations/propertyWithPropertyInInitializerAsParameter.kt");
@@ -141,6 +141,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/annotations/parameterWithPrimitiveType.kt");
}
@TestMetadata("parameters.kt")
public void testParameters() throws Exception {
runTest("compiler/testData/codegen/box/annotations/parameters.kt");
}
@TestMetadata("propertyWithPropertyInInitializerAsParameter.kt")
public void testPropertyWithPropertyInInitializerAsParameter() throws Exception {
runTest("compiler/testData/codegen/box/annotations/propertyWithPropertyInInitializerAsParameter.kt");
@@ -46,6 +46,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/annotations/nestedClassesInAnnotations.kt");
}
@TestMetadata("parameters.kt")
public void testParameters() throws Exception {
runTest("compiler/testData/codegen/box/annotations/parameters.kt");
}
@TestMetadata("resolveWithLowPriorityAnnotation.kt")
public void testResolveWithLowPriorityAnnotation() throws Exception {
runTest("compiler/testData/codegen/box/annotations/resolveWithLowPriorityAnnotation.kt");
@@ -46,6 +46,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/annotations/nestedClassesInAnnotations.kt");
}
@TestMetadata("parameters.kt")
public void testParameters() throws Exception {
runTest("compiler/testData/codegen/box/annotations/parameters.kt");
}
@TestMetadata("resolveWithLowPriorityAnnotation.kt")
public void testResolveWithLowPriorityAnnotation() throws Exception {
runTest("compiler/testData/codegen/box/annotations/resolveWithLowPriorityAnnotation.kt");