diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java index 915db7444ba..1ddaa3bdd85 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java @@ -1246,7 +1246,8 @@ public class KotlinTypeMapper { } ClassDescriptor containingDeclaration = descriptor.getContainingDeclaration(); - if (containingDeclaration.getKind() == ClassKind.ENUM_CLASS || containingDeclaration.getKind() == ClassKind.ENUM_ENTRY) { + if (descriptor.getKind() != CallableMemberDescriptor.Kind.SYNTHESIZED && + (containingDeclaration.getKind() == ClassKind.ENUM_CLASS || containingDeclaration.getKind() == ClassKind.ENUM_ENTRY)) { writeParameter( sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, DescriptorUtilsKt.getBuiltIns(descriptor).getStringType(), descriptor); writeParameter( diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/DeclarationOrigins.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/DeclarationOrigins.kt index 51c244e0054..3d6eefd734e 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/DeclarationOrigins.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/DeclarationOrigins.kt @@ -23,8 +23,11 @@ import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin { object CLASS_STATIC_INITIALIZER : IrDeclarationOriginImpl("CLASS_STATIC_INITIALIZER") object DEFAULT_IMPLS : IrDeclarationOriginImpl("DEFAULT_IMPL") + object FIELD_FOR_ENUM_ENTRY : IrDeclarationOriginImpl("FIELD_FOR_ENUM_ENTRY") + object FIELD_FOR_ENUM_VALUES : IrDeclarationOriginImpl("FIELD_FOR_ENUM_VALUES") } interface JvmLoweredStatementOrigin : IrStatementOrigin { object DEFAULT_IMPLS_DELEGATION : IrStatementOrigin.IrStatementOriginImpl("DEFAULT_IMPL_DELEGATION") + } \ No newline at end of file diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt index b3c54a25220..b87455e007c 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt @@ -16,12 +16,17 @@ package org.jetbrains.kotlin.backend.jvm -import org.jetbrains.kotlin.backend.jvm.lower.JvmFileClassProvider +import org.jetbrains.kotlin.backend.jvm.descriptors.SpecialDescriptorsFactory import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.psi2ir.PsiSourceManager class JvmBackendContext( val state: GenerationState, - val jvmFileClassProvider: JvmFileClassProvider, + val psiSourceManager: PsiSourceManager, val irBuiltIns: IrBuiltIns - ) +) { + val builtIns = state.module.builtIns + val specialDescriptorsFactory = SpecialDescriptorsFactory(psiSourceManager) +} + diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendFacade.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendFacade.kt index 5cd1c5de8f4..ffdd4985f59 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendFacade.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendFacade.kt @@ -16,14 +16,11 @@ package org.jetbrains.kotlin.backend.jvm -import org.jetbrains.kotlin.backend.jvm.lower.JvmFileClassProvider import org.jetbrains.kotlin.codegen.CompilationErrorHandler import org.jetbrains.kotlin.codegen.state.GenerationState -import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator -import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext object JvmBackendFacade { fun compileCorrectFiles(state: GenerationState, errorHandler: CompilationErrorHandler) { @@ -38,12 +35,11 @@ object JvmBackendFacade { val psi2ir = Psi2IrTranslator() val psi2irContext = psi2ir.createGeneratorContext(state.module, state.bindingContext) - val jvmBackendContext = createJvmBackendContext(psi2ir, state, psi2irContext.irBuiltIns) - - val jvmBackend = JvmBackend(jvmBackendContext) - val irModuleFragment = psi2ir.generateModuleFragment(psi2irContext, files) + val jvmBackendContext = JvmBackendContext(state, psi2irContext.sourceManager, psi2irContext.irBuiltIns) + val jvmBackend = JvmBackend(jvmBackendContext) + for (irFile in irModuleFragment.files) { try { jvmBackend.generateFile(irFile) @@ -55,12 +51,4 @@ object JvmBackendFacade { } } - fun createJvmBackendContext(psi2ir: Psi2IrTranslator, state: GenerationState, irBuiltIns: IrBuiltIns): JvmBackendContext { - val jvmFileClassProvider = JvmFileClassProvider() - psi2ir.add(jvmFileClassProvider) - - val jvmBackendContext = JvmBackendContext(state, jvmFileClassProvider, irBuiltIns) - - return jvmBackendContext - } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt index 0ae265dc5a3..459c2591dcb 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmLower.kt @@ -17,38 +17,62 @@ package org.jetbrains.kotlin.backend.jvm import org.jetbrains.kotlin.backend.jvm.lower.* +import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.expressions.IrBody +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.ir.visitors.acceptVoid class JvmLower(val context: JvmBackendContext) { fun lower(irFile: IrFile) { - FileClassLowering(context.jvmFileClassProvider).lower(irFile) + // TODO run lowering passes as callbacks in bottom-up visitor + FileClassLowering(context).lower(irFile) PropertiesLowering().lower(irFile) - InitializersLowering().runOnNormalizedFile(irFile) - InterfaceLowering(context.state).runOnNormalizedFile(irFile) - InterfaceDelegationLowering(context.state).runOnNormalizedFile(irFile) + InterfaceLowering(context.state).runOnFile(irFile) + InterfaceDelegationLowering(context.state).runOnFile(irFile) + EnumClassLowering(context).runOnFile(irFile) + InitializersLowering().runOnFile(irFile) + SingletonReferencesLowering(context).runOnFile(irFile) } } interface FileLoweringPass { - fun lower(irFile: IrFile - ) + fun lower(irFile: IrFile) } interface ClassLoweringPass { fun lower(irClass: IrClass) } -fun ClassLoweringPass.runOnNormalizedFile(irFile: IrFile) { - fun runPostfix(irDeclarationContainer: IrDeclarationContainer) { - irDeclarationContainer.declarations.forEach { - if (it is IrClass) { - runPostfix(it) - lower(it) - } - } - } +interface BodyLoweringPass { + fun lower(irBody: IrBody) +} - runPostfix(irFile) +fun ClassLoweringPass.runOnFile(irFile: IrFile) { + irFile.acceptVoid(object : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitClass(declaration: IrClass) { + declaration.acceptChildrenVoid(this) + lower(declaration) + } + }) +} + +fun BodyLoweringPass.runOnFile(irFile: IrFile) { + irFile.acceptVoid(object : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitBody(body: IrBody) { + body.acceptChildrenVoid(this) + lower(body) + } + }) } \ No newline at end of file diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index 12803795c3e..27267798a90 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_THROWABLE_TYPE @@ -195,7 +196,7 @@ class ExpressionCodegen( override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall, data: BlockInfo): StackValue { - return none() + throw AssertionError("IrInstanceInitializerCall should've been lowered before code generation: ${expression.render()}") } override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, data: BlockInfo): StackValue { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/descriptors/JvmSpecialDescriptor.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/descriptors/JvmSpecialDescriptor.kt new file mode 100644 index 00000000000..6a5572ee3d0 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/descriptors/JvmSpecialDescriptor.kt @@ -0,0 +1,73 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.backend.jvm.descriptors + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.types.KotlinType + +interface JvmSpecialDescriptor { + val extraFlags: Int +} + +class JvmPropertyDescriptorImpl( + containingDeclaration: DeclarationDescriptor, + original: PropertyDescriptor?, + annotations: Annotations, + modality: Modality, + visibility: Visibility, + override val extraFlags: Int, + isVar: Boolean, + name: Name, + kind: CallableMemberDescriptor.Kind, + source: SourceElement, + isLateInit: Boolean, + isConst: Boolean +) : JvmSpecialDescriptor, PropertyDescriptorImpl( + containingDeclaration, original, annotations, modality, visibility, isVar, + name, kind, source, isLateInit, isConst +) { + override fun createSubstitutedCopy(newOwner: DeclarationDescriptor, newModality: Modality, newVisibility: Visibility, original: PropertyDescriptor?, kind: CallableMemberDescriptor.Kind): PropertyDescriptorImpl = + JvmPropertyDescriptorImpl( + newOwner, original, annotations, newModality, newVisibility, extraFlags, isVar, name, kind, + SourceElement.NO_SOURCE, isLateInit, isConst + ) + + companion object { + fun createVal( + name: Name, + type: KotlinType, + containingDeclaration: DeclarationDescriptor, + annotations: Annotations, + modality: Modality, + visibility: Visibility, + extraFlags: Int, + source: SourceElement + ): PropertyDescriptorImpl = + JvmPropertyDescriptorImpl( + containingDeclaration, null, annotations, modality, visibility, extraFlags, false, name, + CallableMemberDescriptor.Kind.SYNTHESIZED, source, false, false + ).setTypeNoReceivers(type) + + private fun PropertyDescriptorImpl.setTypeNoReceivers(type: KotlinType): PropertyDescriptorImpl { + setType(type, emptyList(), null as ReceiverParameterDescriptor?, null as ReceiverParameterDescriptor?) + return this + } + } +} \ No newline at end of file diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/descriptors/SpecialDescriptorsFactory.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/descriptors/SpecialDescriptorsFactory.kt new file mode 100644 index 00000000000..c0cc7cc0923 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/descriptors/SpecialDescriptorsFactory.kt @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.backend.jvm.descriptors + +import org.jetbrains.kotlin.backend.jvm.descriptors.JvmPropertyDescriptorImpl +import org.jetbrains.kotlin.backend.jvm.lower.FileClassDescriptor +import org.jetbrains.kotlin.backend.jvm.lower.FileClassDescriptorImpl +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil +import org.jetbrains.kotlin.ir.SourceManager +import org.jetbrains.kotlin.psi2ir.PsiSourceManager +import org.jetbrains.kotlin.resolve.source.KotlinSourceElement +import org.jetbrains.org.objectweb.asm.Opcodes +import java.util.* + +class SpecialDescriptorsFactory(val psiSourceManager: PsiSourceManager) { + private val enumEntryFieldDescriptors = HashMap() + + fun getFieldDescriptorForEnumEntry(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor = + enumEntryFieldDescriptors.getOrPut(enumEntryDescriptor) { + createEnumEntryFieldDescriptor(enumEntryDescriptor) + } + + fun createFileClassDescriptor(fileEntry: SourceManager.FileEntry, packageFragment: PackageFragmentDescriptor): FileClassDescriptor { + val ktFile = psiSourceManager.getKtFile(fileEntry as PsiSourceManager.PsiFileEntry) + ?: throw AssertionError("Unexpected file entry: $fileEntry") + val fileClassInfo = JvmFileClassUtil.getFileClassInfoNoResolve(ktFile) + val sourceElement = KotlinSourceElement(ktFile) + return FileClassDescriptorImpl(fileClassInfo.fileClassFqName.shortName(), packageFragment, sourceElement) + } + + private fun createEnumEntryFieldDescriptor(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor { + assert(enumEntryDescriptor.kind == ClassKind.ENUM_ENTRY) { "Should be enum entry: $enumEntryDescriptor" } + + val enumClassDescriptor = enumEntryDescriptor.containingDeclaration as ClassDescriptor + assert(enumClassDescriptor.kind == ClassKind.ENUM_CLASS) { "Should be enum class: $enumClassDescriptor"} + + return JvmPropertyDescriptorImpl.createVal( + enumEntryDescriptor.name, + enumClassDescriptor.defaultType, + enumClassDescriptor, + enumEntryDescriptor.annotations, + Modality.FINAL, + Visibilities.PUBLIC, + Opcodes.ACC_ENUM, + enumEntryDescriptor.source + ) + } +} \ No newline at end of file diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayOf.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayOf.kt index 40cbae808d3..95afab25724 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayOf.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayOf.kt @@ -22,7 +22,7 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature class ArrayOf : IntrinsicMethod() { override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { - return IrIntrinsicFunction.create(expression, signature, context) { + return IrIntrinsicFunction.create(expression, signature, context, signature.returnType) { //do nothing all generated as vararg } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Clone.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Clone.kt index 2226f497852..b16e836a558 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Clone.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Clone.kt @@ -24,11 +24,12 @@ import org.jetbrains.org.objectweb.asm.Opcodes class Clone : IntrinsicMethod() { - /*TODO return type*/ override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { return IrIntrinsicFunction.create(expression, signature, context) { + val resultType = context.state.typeMapper.mapType(expression.type) val opcode = if (expression is IrCall && expression.superQualifier != null) Opcodes.INVOKESPECIAL else Opcodes.INVOKEVIRTUAL it.visitMethodInsn(opcode, "java/lang/Object", "clone", "()Ljava/lang/Object;", false) + it.checkcast(resultType) } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrEnumValueOf.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrEnumValueOf.kt new file mode 100644 index 00000000000..5f9e926fcdd --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrEnumValueOf.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.backend.jvm.codegen.BlockInfo +import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen +import org.jetbrains.kotlin.codegen.OwnerKind +import org.jetbrains.kotlin.codegen.StackValue +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.resolve.jvm.AsmTypes +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter + +class IrEnumValueOf : IntrinsicMethod() { + override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { + 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; + + 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.checkcast(enumType) + return StackValue.onStack(enumType) + } + } + } +} \ No newline at end of file diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt index f44eea4c7f4..4c091454ff5 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt @@ -36,12 +36,13 @@ class IrIntrinsicMethods(irBuiltIns: IrBuiltIns) { irMapping.put(irBuiltIns.lteq0, compare) irMapping.put(irBuiltIns.gt0, compare) irMapping.put(irBuiltIns.gteq0, compare) + irMapping.put(irBuiltIns.enumValueOf, IrEnumValueOf()) } fun getIntrinsic(descriptor: CallableMemberDescriptor): IntrinsicMethod? { return intrinsics.getIntrinsic(descriptor) ?: (if (descriptor is PropertyAccessorDescriptor) intrinsics.getIntrinsic(descriptor.correspondingProperty) else null) ?: - irMapping[descriptor] + irMapping[descriptor.original] } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/EnumClassLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/EnumClassLowering.kt new file mode 100644 index 00000000000..5f9ca36619a --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/EnumClassLowering.kt @@ -0,0 +1,430 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.backend.jvm.lower + +import gnu.trove.TObjectIntHashMap +import org.jetbrains.kotlin.backend.jvm.ClassLoweringPass +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin +import org.jetbrains.kotlin.backend.jvm.descriptors.JvmPropertyDescriptorImpl +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl +import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl +import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl +import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.util.dump +import org.jetbrains.kotlin.ir.util.transform +import org.jetbrains.kotlin.ir.util.transformFlat +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi2ir.findSingleFunction +import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.utils.addToStdlib.singletonList +import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList +import org.jetbrains.org.objectweb.asm.Opcodes +import java.util.* + +class EnumClassLowering(val context: JvmBackendContext) : ClassLoweringPass { + override fun lower(irClass: IrClass) { + val classDescriptor = irClass.descriptor + if (classDescriptor.kind != ClassKind.ENUM_CLASS) return + + EnumClassTransformer(irClass).run() + } + + private interface EnumConstructorCallTransformer { + fun transform(enumConstructorCall: IrEnumConstructorCall): IrExpression + } + + private val unsubstitutedArrayOfFun = context.builtIns.findSingleFunction(Name.identifier("arrayOf")) + + private fun createArrayOfExpression(arrayElementType: KotlinType, arrayElements: List): IrExpression { + val typeParameter0 = unsubstitutedArrayOfFun.typeParameters[0] + val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameter0.typeConstructor to TypeProjectionImpl(arrayElementType))) + val substitutedArrayOfFun = unsubstitutedArrayOfFun.substitute(typeSubstitutor) + + val typeArguments = mapOf(typeParameter0 to arrayElementType) + + val valueParameter0 = substitutedArrayOfFun.valueParameters[0] + val arg0VarargType = valueParameter0.type + val arg0VarargElementType = valueParameter0.varargElementType!! + val arg0 = IrVarargImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, arg0VarargType, arg0VarargElementType, arrayElements) + + return IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, substitutedArrayOfFun, typeArguments).apply { + putValueArgument(0, arg0) + } + } + + private inner class EnumClassTransformer(val irClass: IrClass) { + private val enumEntryOrdinals = TObjectIntHashMap() + private val loweredEnumConstructors = HashMap() + private val loweredEnumConstructorParameters = HashMap() + private val enumEntriesByField = HashMap() + private val enumEntryFields = ArrayList() + + private lateinit var valuesFieldDescriptor: PropertyDescriptor + private lateinit var valuesFunctionDescriptor: FunctionDescriptor + private lateinit var valueOfFunctionDescriptor: FunctionDescriptor + + fun run() { + assignOrdinalsToEnumEntries() + lowerEnumConstructors(irClass) + lowerEnumEntries() + setupSynthesizedEnumClassMembers() + lowerEnumClassBody() + } + + private fun assignOrdinalsToEnumEntries() { + var ordinal = 0 + irClass.declarations.forEach { + if (it is IrEnumEntry) { + enumEntryOrdinals.put(it.descriptor, ordinal) + ordinal++ + } + } + } + + private fun lowerEnumConstructors(irClass: IrClass) { + irClass.declarations.transform { declaration -> + if (declaration is IrConstructor) + transformEnumConstructor(declaration) + else + declaration + } + } + + private fun transformEnumConstructor(enumConstructor: IrConstructor): IrConstructor { + val constructorDescriptor = enumConstructor.descriptor + val loweredConstructorDescriptor = lowerEnumConstructor(constructorDescriptor) + val loweredEnumConstructor = IrConstructorImpl( + enumConstructor.startOffset, enumConstructor.endOffset, enumConstructor.origin, + loweredConstructorDescriptor, + enumConstructor.body!! // will be transformed later + ) + return loweredEnumConstructor + } + + private fun lowerEnumConstructor(constructorDescriptor: ClassConstructorDescriptor): ClassConstructorDescriptor { + val loweredConstructorDescriptor = ClassConstructorDescriptorImpl.createSynthesized( + constructorDescriptor.containingDeclaration, + constructorDescriptor.annotations, + constructorDescriptor.isPrimary, + constructorDescriptor.source + ) + + val valueParameters = + listOf( + loweredConstructorDescriptor.createSpecialParameter(0, "name", context.builtIns.stringType), + loweredConstructorDescriptor.createSpecialParameter(1, "ordinal", context.builtIns.intType) + ) + + constructorDescriptor.valueParameters.map { + lowerConstructorValueParameter(loweredConstructorDescriptor, it) + } + loweredConstructorDescriptor.initialize(valueParameters, Visibilities.PROTECTED) + + loweredConstructorDescriptor.returnType = constructorDescriptor.returnType + + loweredEnumConstructors[constructorDescriptor] = loweredConstructorDescriptor + + return loweredConstructorDescriptor + } + + private fun ClassConstructorDescriptor.createSpecialParameter(index: Int, name: String, type: KotlinType): ValueParameterDescriptor = + ValueParameterDescriptorImpl( + this, null, + index, + Annotations.EMPTY, + Name.identifier(name), + type, + false, false, false, false, null, SourceElement.NO_SOURCE + ) + + private fun lowerConstructorValueParameter( + loweredConstructorDescriptor: ClassConstructorDescriptor, + valueParameterDescriptor: ValueParameterDescriptor + ): ValueParameterDescriptor { + val loweredValueParameterDescriptor = valueParameterDescriptor.copy( + loweredConstructorDescriptor, + valueParameterDescriptor.name, + valueParameterDescriptor.index + 2 + ) + loweredEnumConstructorParameters[valueParameterDescriptor] = loweredValueParameterDescriptor + return loweredValueParameterDescriptor + } + + private fun lowerEnumEntries() { + irClass.declarations.transformFlat { declaration -> + if (declaration is IrEnumEntry) { + createFieldForEnumEntry(declaration).singletonList() + + lowerEnumEntryClass(declaration.correspondingClass).singletonOrEmptyList() + } + else null + } + } + + private fun lowerEnumEntryClass(enumEntryClass: IrClass?): IrClass? { + if (enumEntryClass == null) return null + + lowerEnumConstructors(enumEntryClass) + + return enumEntryClass + } + + private fun createFieldForEnumEntry(enumEntry: IrEnumEntry): IrField { + val fieldPropertyDescriptor = context.specialDescriptorsFactory.getFieldDescriptorForEnumEntry(enumEntry.descriptor) + + enumEntriesByField[fieldPropertyDescriptor] = enumEntry.descriptor + enumEntryFields.add(fieldPropertyDescriptor) + + val enumEntryInitializer = enumEntry.initializerExpression + return IrFieldImpl( + enumEntry.startOffset, enumEntry.endOffset, JvmLoweredDeclarationOrigin.FIELD_FOR_ENUM_ENTRY, + fieldPropertyDescriptor, + IrExpressionBodyImpl(enumEntryInitializer.startOffset, enumEntryInitializer.endOffset, enumEntryInitializer) + ) + } + + private fun setupSynthesizedEnumClassMembers() { + val irField = createSyntheticValuesFieldDeclaration() + + irClass.declarations.add(irField) + + valuesFunctionDescriptor = findFunctionDescriptorForMemberWithSyntheticBodyKind(IrSyntheticBodyKind.ENUM_VALUES) + valueOfFunctionDescriptor = findFunctionDescriptorForMemberWithSyntheticBodyKind(IrSyntheticBodyKind.ENUM_VALUEOF) + } + + private fun findFunctionDescriptorForMemberWithSyntheticBodyKind(kind: IrSyntheticBodyKind): FunctionDescriptor = + irClass.declarations + .first { + it is IrFunction && + it.body.let { body -> + body is IrSyntheticBody && body.kind == kind + } + } + .descriptor as FunctionDescriptor + + + private fun createSyntheticValuesFieldDeclaration(): IrFieldImpl { + val valuesArrayType = context.builtIns.getArrayType(Variance.INVARIANT, irClass.descriptor.defaultType) + valuesFieldDescriptor = createSyntheticValuesFieldDescriptor(valuesArrayType) + + val irValuesInitializer = createSyntheticValuesFieldInitializerExpression() + + val irField = IrFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, JvmLoweredDeclarationOrigin.FIELD_FOR_ENUM_VALUES, + valuesFieldDescriptor, + IrExpressionBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irValuesInitializer)) + return irField + } + + private fun createSyntheticValuesFieldInitializerExpression(): IrExpression = + createArrayOfExpression( + irClass.descriptor.defaultType, + enumEntryFields.map { fieldDescriptor -> + IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, fieldDescriptor) + }) + + private fun createSyntheticValuesFieldDescriptor(valuesArrayType: SimpleType): PropertyDescriptorImpl { + return JvmPropertyDescriptorImpl.createVal( + Name.identifier("\$VALUES"), + valuesArrayType, + irClass.descriptor, + Annotations.EMPTY, + Modality.FINAL, Visibilities.PRIVATE, Opcodes.ACC_SYNTHETIC, + irClass.descriptor.source + ) + } + + private fun lowerEnumClassBody() { + irClass.transformChildrenVoid(EnumClassBodyTransformer()) + } + + private inner class InEnumClassConstructor(val enumClassConstructor: ClassConstructorDescriptor) : + EnumConstructorCallTransformer { + override fun transform(enumConstructorCall: IrEnumConstructorCall): IrExpression { + val startOffset = enumConstructorCall.startOffset + val endOffset = enumConstructorCall.endOffset + val origin = enumConstructorCall.origin + + val result = IrDelegatingConstructorCallImpl(startOffset, endOffset, enumConstructorCall.descriptor) + + assert(result.descriptor.valueParameters.size == 2) { + "Enum(String, Int) constructor call expected:\n${result.dump()}" + } + + val nameParameter = enumClassConstructor.valueParameters.getOrElse(0) { + throw AssertionError("No 'name' parameter in enum constructor: $enumClassConstructor") + } + + val ordinalParameter = enumClassConstructor.valueParameters.getOrElse(1) { + throw AssertionError("No 'ordinal' parameter in enum constructor: $enumClassConstructor") + } + + result.putValueArgument(0, IrGetVariableImpl(startOffset, endOffset, nameParameter, origin)) + result.putValueArgument(1, IrGetVariableImpl(startOffset, endOffset, ordinalParameter, origin)) + + return result + } + } + + private abstract inner class InEnumEntry(private val enumEntry: ClassDescriptor) : EnumConstructorCallTransformer { + override fun transform(enumConstructorCall: IrEnumConstructorCall): IrExpression { + val name = enumEntry.name.asString() + val ordinal = enumEntryOrdinals[enumEntry] + + val descriptor = enumConstructorCall.descriptor + val startOffset = enumConstructorCall.startOffset + val endOffset = enumConstructorCall.endOffset + + val loweredConstructor = loweredEnumConstructors.getOrElse(descriptor) { + throw AssertionError("Constructor called in enum entry initializer should've been lowered: $descriptor") + } + + val result = createConstructorCall(startOffset, endOffset, loweredConstructor) + + result.putValueArgument(0, IrConstImpl.string(startOffset, endOffset, context.builtIns.stringType, name)) + result.putValueArgument(1, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, ordinal)) + + descriptor.valueParameters.forEach { valueParameter -> + val i = valueParameter.index + result.putValueArgument(i + 2, enumConstructorCall.getValueArgument(i)) + } + + return result + } + + abstract fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: ClassConstructorDescriptor): IrMemberAccessExpression + } + + private inner class InEnumEntryClassConstructor(enumEntry: ClassDescriptor) : InEnumEntry(enumEntry) { + override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: ClassConstructorDescriptor) = + IrDelegatingConstructorCallImpl(startOffset, endOffset, loweredConstructor) + } + + private inner class InEnumEntryInitializer(enumEntry: ClassDescriptor) : InEnumEntry(enumEntry) { + override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: ClassConstructorDescriptor) = + IrCallImpl(startOffset, endOffset, loweredConstructor) + } + + private inner class EnumClassBodyTransformer : IrElementTransformerVoid() { + private var enumConstructorCallTransformer: EnumConstructorCallTransformer? = null + + override fun visitField(declaration: IrField): IrStatement { + val enumEntry = enumEntriesByField[declaration.descriptor] ?: + return declaration + + assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}"} + + enumConstructorCallTransformer = InEnumEntryInitializer(enumEntry) + + val result = super.visitField(declaration) + + enumConstructorCallTransformer = null + + return result + } + + override fun visitConstructor(declaration: IrConstructor): IrStatement { + val constructorDescriptor = declaration.descriptor + val containingClass = constructorDescriptor.containingDeclaration + + // TODO local (non-enum) class in enum class constructor? + val previous = enumConstructorCallTransformer + + if (containingClass.kind == ClassKind.ENUM_ENTRY) { + assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}"} + enumConstructorCallTransformer = InEnumEntryClassConstructor(containingClass) + } + else if (containingClass.kind == ClassKind.ENUM_CLASS) { + assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}"} + enumConstructorCallTransformer = InEnumClassConstructor(constructorDescriptor) + } + + val result = super.visitConstructor(declaration) + + enumConstructorCallTransformer = previous + + return result + } + + override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrExpression { + expression.transformChildrenVoid(this) + + val callTransformer = enumConstructorCallTransformer ?: + throw AssertionError("Enum constructor call outside of enum entry initialization or enum class constructor:\n" + + irClass.dump()) + + return callTransformer.transform(expression) + } + + override fun visitGetVariable(expression: IrGetVariable): IrExpression = + loweredEnumConstructorParameters[expression.descriptor]?.let { loweredParameter -> + IrGetVariableImpl(expression.startOffset, expression.endOffset, loweredParameter, expression.origin) + } ?: expression + + override fun visitSyntheticBody(body: IrSyntheticBody): IrBody { + return when (body.kind) { + IrSyntheticBodyKind.ENUM_VALUES -> + createEnumValuesBody(valuesFieldDescriptor) + IrSyntheticBodyKind.ENUM_VALUEOF -> + createEnumValueOfBody() + else -> + body + } + } + + private fun createEnumValueOfBody(): IrBody { + val unsubstitutedValueOf = context.irBuiltIns.enumValueOf + val typeParameterT = unsubstitutedValueOf.typeParameters[0] + val enumClassType = irClass.descriptor.defaultType + val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(enumClassType))) + val substitutedValueOf = unsubstitutedValueOf.substitute(typeSubstitutor) + + val irValueOfCall = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, substitutedValueOf, mapOf(typeParameterT to enumClassType)) + irValueOfCall.putValueArgument( + 0, IrGetVariableImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valueOfFunctionDescriptor.valueParameters[0])) + + return IrBlockBodyImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, + listOf(IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valueOfFunctionDescriptor, irValueOfCall)) + ) + } + + private fun createEnumValuesBody(valuesFieldDescriptor: PropertyDescriptor): IrBody { + val cloneFun = valuesFieldDescriptor.type.memberScope.findSingleFunction(Name.identifier("clone")) + + val irCloneValues = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, cloneFun).apply { + dispatchReceiver = IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valuesFieldDescriptor) + } + + return IrBlockBodyImpl( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, + listOf(IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valuesFunctionDescriptor, irCloneValues)) + ) + } + } + } + + +} \ No newline at end of file diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FileClassLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FileClassLowering.kt index f7ba3817273..5684c96abdc 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FileClassLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/FileClassLowering.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.jvm.FileLoweringPass +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin @@ -24,7 +25,7 @@ import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl import java.util.* -class FileClassLowering(val jvmFileClassProvider: JvmFileClassProvider) : FileLoweringPass { +class FileClassLowering(val context: JvmBackendContext) : FileLoweringPass { override fun lower(irFile: IrFile) { val classes = ArrayList() val fileClassMembers = ArrayList() @@ -38,7 +39,7 @@ class FileClassLowering(val jvmFileClassProvider: JvmFileClassProvider) : FileLo if (fileClassMembers.isEmpty()) return - val fileClassDescriptor = jvmFileClassProvider.createFileClassDescriptor(irFile.fileEntry, irFile.packageFragmentDescriptor) + val fileClassDescriptor = context.specialDescriptorsFactory.createFileClassDescriptor(irFile.fileEntry, irFile.packageFragmentDescriptor) val irFileClass = IrClassImpl(0, irFile.fileEntry.maxOffset, IrDeclarationOrigin.DEFINED, fileClassDescriptor, fileClassMembers) classes.add(irFileClass) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InitializersLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InitializersLowering.kt index 8a9c762ed58..ad7fad48486 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InitializersLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InitializersLowering.kt @@ -38,6 +38,7 @@ import org.jetbrains.kotlin.ir.util.DeepCopyIrTree import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import java.util.* @@ -79,7 +80,7 @@ class InitializersLowering : ClassLoweringPass { null, null ) - if (declaration.descriptor.isStatic()) { + if (DescriptorUtils.isStaticDeclaration(declaration.descriptor)) { staticInitializerStatements.add(irSetField) } else { @@ -91,10 +92,6 @@ class InitializersLowering : ClassLoweringPass { instanceInitializerStatements.addAll(declaration.body.statements) } - private fun CallableMemberDescriptor.isStatic() = - AsmUtil.isStaticMethod(classMemberOwnerKind, this) // TODO what about properties? - - fun transformInstanceInitializerCallsInConstructors(irClass: IrClass) { for (irDeclaration in irClass.declarations) { if (irDeclaration !is IrConstructor) continue diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmFileClassProvider.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmFileClassProvider.kt deleted file mode 100644 index 8f7ca01d182..00000000000 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/JvmFileClassProvider.kt +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.backend.jvm.lower - -import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor -import org.jetbrains.kotlin.descriptors.SourceElement -import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo -import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil -import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.SourceManager -import org.jetbrains.kotlin.ir.declarations.IrFile -import org.jetbrains.kotlin.ir.declarations.IrModuleFragment -import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator -import org.jetbrains.kotlin.psi2ir.PsiSourceManager -import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext -import org.jetbrains.kotlin.resolve.source.KotlinSourceElement -import java.lang.AssertionError -import java.util.* - -class JvmFileClassProvider : Psi2IrTranslator.PostprocessingStep { - override fun postprocess(context: GeneratorContext, irElement: IrElement) { - when (irElement) { - is IrModuleFragment -> - irElement.files.forEach { postprocess(context, it) } - is IrFile -> - recordFileClassInfo(context, irElement) - } - } - - private val fileClassInfoByFileEntry = HashMap() - private val sourceElementByFileEntry = HashMap() - - private fun recordFileClassInfo(context: GeneratorContext, irFile: IrFile) { - context.sourceManager.getKtFile(irFile)?.let { ktFile -> - sourceElementByFileEntry[irFile.fileEntry] = KotlinSourceElement(ktFile) - } - val jvmFileClassInfo = context.sourceManager.getFileClassInfo(irFile) ?: return - fileClassInfoByFileEntry[irFile.fileEntry] = jvmFileClassInfo - } - - private fun PsiSourceManager.getFileClassInfo(irFile: IrFile): JvmFileClassInfo? { - val file = getKtFile(irFile) ?: return null - return JvmFileClassUtil.getFileClassInfoNoResolve(file) - } - - fun createFileClassDescriptor(fileEntry: SourceManager.FileEntry, packageFragment: PackageFragmentDescriptor): FileClassDescriptor { - val fileClassInfo = fileClassInfoByFileEntry[fileEntry] ?: throw AssertionError("No file class info for ${fileEntry.name})") - val sourceElement = sourceElementByFileEntry[fileEntry] ?: SourceElement.NO_SOURCE - return FileClassDescriptorImpl(fileClassInfo.fileClassFqName.shortName(), packageFragment, sourceElement) - } -} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/PropertiesLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/PropertiesLowering.kt index 65d0c5cc288..6fc3f09a06e 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/PropertiesLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/PropertiesLowering.kt @@ -18,13 +18,12 @@ package org.jetbrains.kotlin.backend.jvm.lower import org.jetbrains.kotlin.backend.jvm.FileLoweringPass import org.jetbrains.kotlin.ir.IrStatement -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrDeclaration -import org.jetbrains.kotlin.ir.declarations.IrFile -import org.jetbrains.kotlin.ir.declarations.IrProperty +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.util.transformFlat import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.utils.addIfNotNull +import org.jetbrains.kotlin.utils.addToStdlib.singletonList import java.util.* class PropertiesLowering : IrElementTransformerVoid(), FileLoweringPass { @@ -34,29 +33,23 @@ class PropertiesLowering : IrElementTransformerVoid(), FileLoweringPass { override fun visitFile(declaration: IrFile): IrFile { declaration.transformChildrenVoid(this) - transformDeclarations(declaration.declarations) + declaration.declarations.transformFlat { lowerProperty(it) } return declaration } override fun visitClass(declaration: IrClass): IrStatement { declaration.transformChildrenVoid(this) - transformDeclarations(declaration.declarations) + declaration.declarations.transformFlat { lowerProperty(it) } return declaration } - private fun transformDeclarations(declarations: MutableList) { - val newDeclarations = ArrayList() - for (declaration in declarations) { - if (declaration is IrProperty) { - newDeclarations.addIfNotNull(declaration.backingField) - newDeclarations.addIfNotNull(declaration.getter) - newDeclarations.addIfNotNull(declaration.setter) - } - else { - newDeclarations.add(declaration) - } - } - declarations.clear() - declarations.addAll(newDeclarations) - } + private fun lowerProperty(declaration: IrDeclaration): List? = + if (declaration is IrProperty) + ArrayList(3).apply { + addIfNotNull(declaration.backingField) + addIfNotNull(declaration.getter) + addIfNotNull(declaration.setter) + } + else + null } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SingletonReferencesLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SingletonReferencesLowering.kt new file mode 100644 index 00000000000..de885fbebcb --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SingletonReferencesLowering.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.backend.jvm.lower + +import org.jetbrains.kotlin.backend.jvm.BodyLoweringPass +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.ir.expressions.IrBody +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrGetEnumValue +import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid + +class SingletonReferencesLowering(val context: JvmBackendContext) : BodyLoweringPass, IrElementTransformerVoid() { + override fun lower(irBody: IrBody) { + irBody.transformChildrenVoid(this) + } + + override fun visitGetEnumValue(expression: IrGetEnumValue): IrExpression { + val enumValueFieldDescriptor = context.specialDescriptorsFactory.getFieldDescriptorForEnumEntry(expression.descriptor) + return IrGetFieldImpl(expression.startOffset, expression.endOffset, enumValueFieldDescriptor) + } +} \ No newline at end of file diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/KotlinUtils.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/KotlinUtils.kt index baa6258274e..38f8f126874 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/KotlinUtils.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/KotlinUtils.kt @@ -16,8 +16,10 @@ package org.jetbrains.kotlin.psi2ir +import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtElement @@ -70,3 +72,9 @@ inline fun ClassDescriptor.findFirstFunction(name: String, predicate: (CallableM inline fun MemberScope.findFirstFunction(name: String, predicate: (CallableMemberDescriptor) -> Boolean) = getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).first(predicate) + +fun MemberScope.findSingleFunction(name: Name): FunctionDescriptor = + getContributedFunctions(name, NoLookupLocation.FROM_BACKEND).single() + +fun KotlinBuiltIns.findSingleFunction(name: Name): FunctionDescriptor = + builtInsPackageScope.findSingleFunction(name) \ No newline at end of file diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt index 39ace11f8dd..f37c9704a9b 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/BodyGenerator.kt @@ -29,7 +29,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny import java.lang.AssertionError import java.util.* -class BodyGenerator(val scopeOwner: DeclarationDescriptor, override val context: GeneratorContext): GeneratorWithScope { +class BodyGenerator(val scopeOwner: DeclarationDescriptor, override val context: GeneratorContext) : GeneratorWithScope { override val scope = Scope(scopeOwner) private val loopTable = HashMap() @@ -63,7 +63,7 @@ class BodyGenerator(val scopeOwner: DeclarationDescriptor, override val context: fun generatePropertyInitializerBody(ktInitializer: KtExpression): IrExpressionBody = IrExpressionBodyImpl(ktInitializer.startOffset, ktInitializer.endOffset, - createStatementGenerator().generateExpression(ktInitializer)) + createStatementGenerator().generateExpression(ktInitializer)) fun generateLambdaBody(ktFun: KtFunctionLiteral): IrBody { val statementGenerator = createStatementGenerator() @@ -231,7 +231,7 @@ class BodyGenerator(val scopeOwner: DeclarationDescriptor, override val context: private fun generateEnumSuperConstructorCall(irBlockBody: IrBlockBodyImpl, ktElement: KtElement) { val enumConstructor = context.builtIns.enum.constructors.single() - irBlockBody.statements.add(IrEnumConstructorCallImpl(ktElement.startOffset, ktElement.endOffset, enumConstructor, null)) + irBlockBody.statements.add(IrEnumConstructorCallImpl(ktElement.startOffset, ktElement.endOffset, enumConstructor)) } private fun generateEnumEntrySuperConstructorCall(ktEnumEntry: KtEnumEntry, enumEntryDescriptor: ClassDescriptor): IrExpression { @@ -253,8 +253,7 @@ class BodyGenerator(val scopeOwner: DeclarationDescriptor, override val context: fun generateEnumEntryInitializer(ktEnumEntry: KtEnumEntry, enumEntryDescriptor: ClassDescriptor): IrExpression { if (ktEnumEntry.declarations.isNotEmpty()) { val enumEntryConstructor = enumEntryDescriptor.unsubstitutedPrimaryConstructor!! - return IrEnumConstructorCallImpl(ktEnumEntry.startOffset, ktEnumEntry.endOffset, - enumEntryConstructor, enumEntryDescriptor) + return IrEnumConstructorCallImpl(ktEnumEntry.startOffset, ktEnumEntry.endOffset, enumEntryConstructor) } return generateEnumConstructorCallOrSuperCall(ktEnumEntry, enumEntryDescriptor.containingDeclaration as ClassDescriptor, enumEntryDescriptor) @@ -278,8 +277,7 @@ class BodyGenerator(val scopeOwner: DeclarationDescriptor, override val context: // No-argument enum entry constructor val enumClassConstructor = enumClassDescriptor.unsubstitutedPrimaryConstructor!! - return IrEnumConstructorCallImpl(ktEnumEntry.startOffset, ktEnumEntry.endOffset, - enumClassConstructor, enumEntryOrNull) + return IrEnumConstructorCallImpl(ktEnumEntry.startOffset, ktEnumEntry.endOffset, enumClassConstructor) } } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt index 7702a26f418..171a79d3daa 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt @@ -58,7 +58,7 @@ class CallGenerator(statementGenerator: StatementGenerator): StatementGeneratorE fun generateDelegatingConstructorCall(startOffset: Int, endOffset: Int, call: CallBuilder) : IrExpression { val descriptor = call.descriptor - if (descriptor !is ConstructorDescriptor) throw AssertionError("Constructor expected: $descriptor") + if (descriptor !is ClassConstructorDescriptor) throw AssertionError("Class constructor expected: $descriptor") return call.callReceiver.call { dispatchReceiver, extensionReceiver -> val irCall = IrDelegatingConstructorCallImpl(startOffset, endOffset, descriptor, getTypeArguments(call.original)) @@ -78,7 +78,7 @@ class CallGenerator(statementGenerator: StatementGenerator): StatementGeneratorE return call.callReceiver.call { dispatchReceiver, extensionReceiver -> if (dispatchReceiver != null) throw AssertionError("Dispatch receiver should be null: $dispatchReceiver") if (extensionReceiver != null) throw AssertionError("Extension receiver should be null: $extensionReceiver") - val irCall = IrEnumConstructorCallImpl(startOffset, endOffset, constructorDescriptor, enumEntryDescriptor) + val irCall = IrEnumConstructorCallImpl(startOffset, endOffset, constructorDescriptor) addParametersToCall(startOffset, endOffset, call, irCall, constructorDescriptor.returnType) } } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt index ece5732786c..6d46a229a4a 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.psi2ir.generators import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.* @@ -88,7 +89,7 @@ class DeclarationGenerator(override val context: GeneratorContext) : Generator { if (ktConstructor.isConstructorDelegatingToSuper(context.bindingContext)) { return generateSecondaryConstructorWithNestedInitializers(ktConstructor) } - val constructorDescriptor = getOrFail(BindingContext.CONSTRUCTOR, ktConstructor) + val constructorDescriptor = getOrFail(BindingContext.CONSTRUCTOR, ktConstructor) as ClassConstructorDescriptor val irConstructor = IrConstructorImpl(ktConstructor.startOffset, ktConstructor.endOffset, IrDeclarationOrigin.DEFINED, constructorDescriptor) val bodyGenerator = createBodyGenerator(constructorDescriptor) bodyGenerator.generateDefaultParameters(ktConstructor, irConstructor) @@ -98,7 +99,7 @@ class DeclarationGenerator(override val context: GeneratorContext) : Generator { private fun generateSecondaryConstructorWithNestedInitializers(ktConstructor: KtSecondaryConstructor): IrFunction { - val constructorDescriptor = getOrFail(BindingContext.CONSTRUCTOR, ktConstructor) + val constructorDescriptor = getOrFail(BindingContext.CONSTRUCTOR, ktConstructor) as ClassConstructorDescriptor val irConstructor = IrConstructorImpl(ktConstructor.startOffset, ktConstructor.endOffset, IrDeclarationOrigin.DEFINED, constructorDescriptor) val bodyGenerator = createBodyGenerator(constructorDescriptor) bodyGenerator.generateDefaultParameters(ktConstructor, irConstructor) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrConstructor.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrConstructor.kt index fdc847f0067..3e0434a6837 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrConstructor.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrConstructor.kt @@ -16,13 +16,13 @@ package org.jetbrains.kotlin.ir.declarations -import org.jetbrains.kotlin.descriptors.ConstructorDescriptor +import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor interface IrConstructor : IrFunction { override val declarationKind: IrDeclarationKind get() = IrDeclarationKind.CONSTRUCTOR - override val descriptor: ConstructorDescriptor + override val descriptor: ClassConstructorDescriptor } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclarationContainer.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclarationContainer.kt index 45751c19a2a..5e8e6a321c2 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclarationContainer.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclarationContainer.kt @@ -16,6 +16,8 @@ package org.jetbrains.kotlin.ir.declarations +import org.jetbrains.kotlin.ir.util.transformFlat + interface IrDeclarationContainer { val declarations: MutableList -} \ No newline at end of file +} diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrConstructorImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrConstructorImpl.kt index 6fc510ba2e6..fc8146a9256 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrConstructorImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/impl/IrConstructorImpl.kt @@ -16,16 +16,18 @@ package org.jetbrains.kotlin.ir.declarations.impl -import org.jetbrains.kotlin.descriptors.ConstructorDescriptor +import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin import org.jetbrains.kotlin.ir.expressions.IrBody import org.jetbrains.kotlin.ir.visitors.IrElementVisitor -class IrConstructorImpl(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, override val descriptor: ConstructorDescriptor) : - IrFunctionBase(startOffset, endOffset, origin), IrConstructor { +class IrConstructorImpl( + startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, + override val descriptor: ClassConstructorDescriptor +) : IrFunctionBase(startOffset, endOffset, origin), IrConstructor { constructor( - startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ConstructorDescriptor, + startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, descriptor: ClassConstructorDescriptor, body: IrBody ) : this(startOffset, endOffset, origin, descriptor) { this.body = body diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt index 7e41cd27f01..8dab89a96d5 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt @@ -17,32 +17,27 @@ package org.jetbrains.kotlin.ir.descriptors import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.annotations.Annotations +import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl +import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl +import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.KotlinTypeFactory import org.jetbrains.kotlin.types.TypeSubstitution +import org.jetbrains.kotlin.types.Variance -class IrBuiltIns(val builtIns: KotlinBuiltIns) { - val packageFragment = IrBuiltinsPackageFragmentDescriptorImpl(builtIns.builtInsModule) - +class BuiltinsOperatorsBuilder(val packageFragment: PackageFragmentDescriptor, val builtIns: KotlinBuiltIns) { val bool = builtIns.booleanType val any = builtIns.anyType val anyN = builtIns.nullableAnyType val int = builtIns.intType val nothing = builtIns.nothingType - val eqeqeq: FunctionDescriptor = defineOperator("EQEQEQ", bool, listOf(anyN, anyN)) - val eqeq: FunctionDescriptor = defineOperator("EQEQ", bool, listOf(anyN, anyN)) - val lt0: FunctionDescriptor = defineOperator("LT0", bool, listOf(int)) - val lteq0: FunctionDescriptor = defineOperator("LTEQ0", bool, listOf(int)) - val gt0: FunctionDescriptor = defineOperator("GT0", bool, listOf(int)) - val gteq0: FunctionDescriptor = defineOperator("GTEQ0", bool, listOf(int)) - val throwNpe: FunctionDescriptor = defineOperator("THROW_NPE", nothing, listOf()) - val booleanNot: FunctionDescriptor = defineOperator("NOT", bool, listOf(bool)) - - private fun defineOperator(name: String, returnType: KotlinType, valueParameterTypes: List): IrBuiltinOperatorDescriptor { + fun defineOperator(name: String, returnType: KotlinType, valueParameterTypes: List): IrBuiltinOperatorDescriptor { val operatorDescriptor = IrSimpleBuiltinOperatorDescriptorImpl(packageFragment, Name.identifier(name), returnType) for ((i, valueParameterType) in valueParameterTypes.withIndex()) { operatorDescriptor.addValueParameter( @@ -50,7 +45,44 @@ class IrBuiltIns(val builtIns: KotlinBuiltIns) { } return operatorDescriptor } - - private fun ClassDescriptor.findSingleFunction(name: String): FunctionDescriptor = - getMemberScope(TypeSubstitution.EMPTY).getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BUILTINS).single() +} + +class IrBuiltIns(val builtIns: KotlinBuiltIns) { + private val packageFragment = IrBuiltinsPackageFragmentDescriptorImpl(builtIns.builtInsModule, KOTLIN_INTERNAL_IR_FQN) + private val builder = BuiltinsOperatorsBuilder(packageFragment, builtIns) + + val eqeqeq: FunctionDescriptor = builder.run { defineOperator("EQEQEQ", bool, listOf(anyN, anyN)) } + val eqeq: FunctionDescriptor = builder.run { defineOperator("EQEQ", bool, listOf(anyN, anyN)) } + val lt0: FunctionDescriptor = builder.run { defineOperator("LT0", bool, listOf(int)) } + val lteq0: FunctionDescriptor = builder.run { defineOperator("LTEQ0", bool, listOf(int)) } + val gt0: FunctionDescriptor = builder.run { defineOperator("GT0", bool, listOf(int)) } + val gteq0: FunctionDescriptor = builder.run { defineOperator("GTEQ0", bool, listOf(int)) } + val throwNpe: FunctionDescriptor = builder.run { defineOperator("THROW_NPE", nothing, listOf()) } + val booleanNot: FunctionDescriptor = builder.run { defineOperator("NOT", bool, listOf(bool)) } + + val enumValueOf: FunctionDescriptor = + SimpleFunctionDescriptorImpl.create( + packageFragment, + Annotations.EMPTY, + Name.identifier("enumValueOf"), + CallableMemberDescriptor.Kind.SYNTHESIZED, + org.jetbrains.kotlin.descriptors.SourceElement.NO_SOURCE + ).apply { + val typeParameterT = TypeParameterDescriptorImpl.createWithDefaultBound( + this, Annotations.EMPTY, true, Variance.INVARIANT, Name.identifier("T"), 0 + ) + + val valueParameterName = ValueParameterDescriptorImpl( + this, null, 0, Annotations.EMPTY, Name.identifier("name"), builtIns.stringType, + false, false, false, false, null, org.jetbrains.kotlin.descriptors.SourceElement.NO_SOURCE + ) + + val returnType = KotlinTypeFactory.simpleType(Annotations.EMPTY, typeParameterT.typeConstructor, listOf(), false) + + initialize(null, null, listOf(typeParameterT), listOf(valueParameterName), returnType, Modality.FINAL, Visibilities.PUBLIC) + } + + companion object { + val KOTLIN_INTERNAL_IR_FQN = FqName("kotlin.internal.ir") + } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltinsPackageFragmentDescriptor.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltinsPackageFragmentDescriptor.kt index 34e55d30b28..9783569648a 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltinsPackageFragmentDescriptor.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltinsPackageFragmentDescriptor.kt @@ -25,9 +25,13 @@ import org.jetbrains.kotlin.types.TypeSubstitutor interface IrBuiltinsPackageFragmentDescriptor : PackageFragmentDescriptor -class IrBuiltinsPackageFragmentDescriptorImpl(val containingModule: ModuleDescriptor) : IrBuiltinsPackageFragmentDescriptor { - override val fqName: FqName get() = FqName("kotlin.internal.ir") - override fun getName(): Name = Name.identifier("ir") +class IrBuiltinsPackageFragmentDescriptorImpl( + val containingModule: ModuleDescriptor, + override val fqName: FqName +) : IrBuiltinsPackageFragmentDescriptor { + private val shortName = fqName.shortName() + + override fun getName(): Name = shortName override fun getContainingDeclaration(): ModuleDescriptor = containingModule diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBody.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBody.kt index 0d61254f8e8..a2407e25d5f 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBody.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBody.kt @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.ir.expressions import org.jetbrains.kotlin.ir.IrElement -import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.visitors.IrElementTransformer interface IrBody : IrElement { @@ -29,10 +28,6 @@ interface IrExpressionBody : IrBody { var expression: IrExpression } -interface IrStatementContainer { - val statements: MutableList -} - interface IrBlockBody : IrBody, IrStatementContainer interface IrSyntheticBody : IrBody { diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDelegatingConstructorCall.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDelegatingConstructorCall.kt index b2266959da6..707dea7ffcb 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDelegatingConstructorCall.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDelegatingConstructorCall.kt @@ -16,9 +16,9 @@ package org.jetbrains.kotlin.ir.expressions -import org.jetbrains.kotlin.descriptors.ConstructorDescriptor +import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor interface IrDelegatingConstructorCall : IrMemberAccessExpression { - override val descriptor: ConstructorDescriptor + override val descriptor: ClassConstructorDescriptor } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrEnumConstructorCall.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrEnumConstructorCall.kt index 9beeef37b69..3e4d7bd43ae 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrEnumConstructorCall.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrEnumConstructorCall.kt @@ -16,15 +16,9 @@ package org.jetbrains.kotlin.ir.expressions -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.ConstructorDescriptor +import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor interface IrEnumConstructorCall : IrMemberAccessExpression { - override val descriptor: ConstructorDescriptor - val enumEntryDescriptor: ClassDescriptor? + override val descriptor: ClassConstructorDescriptor } - -val IrEnumConstructorCall.isSuper: Boolean - get() = enumEntryDescriptor == null - diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrStatementContainer.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrStatementContainer.kt new file mode 100644 index 00000000000..055ca1526f7 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrStatementContainer.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.ir.expressions + +import org.jetbrains.kotlin.ir.IrStatement + +interface IrStatementContainer { + val statements: MutableList +} diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrCallImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrCallImpl.kt index 6c9e6d97629..00155d7a505 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrCallImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrCallImpl.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrCallWithShallowCopy +import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.visitors.IrElementTransformer import org.jetbrains.kotlin.ir.visitors.IrElementVisitor @@ -35,6 +36,13 @@ class IrCallImpl( override val origin: IrStatementOrigin? = null, override val superQualifier: ClassDescriptor? = null ) : IrCallWithIndexedArgumentsBase(startOffset, endOffset, type, descriptor.valueParameters.size, typeArguments), IrCallWithShallowCopy { + constructor( + startOffset: Int, endOffset: Int, descriptor: CallableDescriptor, + typeArguments: Map? = null, + origin: IrStatementOrigin? = null, + superQualifier: ClassDescriptor? = null + ) : this(startOffset, endOffset, descriptor.returnType!!, descriptor, typeArguments, origin, superQualifier) + override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitCall(this, data) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrDelegatingConstructorCallImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrDelegatingConstructorCallImpl.kt index d8e1d39259d..24c0339eb28 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrDelegatingConstructorCallImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrDelegatingConstructorCallImpl.kt @@ -16,7 +16,7 @@ package org.jetbrains.kotlin.ir.expressions.impl -import org.jetbrains.kotlin.descriptors.ConstructorDescriptor +import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.ir.expressions.IrDelegatingConstructorCall import org.jetbrains.kotlin.ir.visitors.IrElementVisitor @@ -26,8 +26,8 @@ import org.jetbrains.kotlin.types.KotlinType class IrDelegatingConstructorCallImpl( startOffset: Int, endOffset: Int, - override val descriptor: ConstructorDescriptor, - typeArguments: Map? + override val descriptor: ClassConstructorDescriptor, + typeArguments: Map? = null ) : IrCallWithIndexedArgumentsBase(startOffset, endOffset, descriptor.builtIns.unitType, descriptor.valueParameters.size, typeArguments), IrDelegatingConstructorCall { override fun accept(visitor: IrElementVisitor, data: D): R { diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrEnumConstructorCallImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrEnumConstructorCallImpl.kt index 282b57bbb7c..0b01063a39f 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrEnumConstructorCallImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrEnumConstructorCallImpl.kt @@ -16,8 +16,7 @@ package org.jetbrains.kotlin.ir.expressions.impl -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.ConstructorDescriptor +import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor import org.jetbrains.kotlin.ir.expressions.IrEnumConstructorCall import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns @@ -25,8 +24,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns class IrEnumConstructorCallImpl( startOffset: Int, endOffset: Int, - override val descriptor: ConstructorDescriptor, - override val enumEntryDescriptor: ClassDescriptor? = null + override val descriptor: ClassConstructorDescriptor ) : IrCallWithIndexedArgumentsBase(startOffset, endOffset, descriptor.builtIns.unitType, descriptor.valueParameters.size, null), IrEnumConstructorCall { override fun accept(visitor: IrElementVisitor, data: D): R { diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrReturnImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrReturnImpl.kt index 528853898db..4f79e8f89f3 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrReturnImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrReturnImpl.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrReturn import org.jetbrains.kotlin.ir.visitors.IrElementTransformer import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.types.KotlinType class IrReturnImpl( @@ -30,6 +31,9 @@ class IrReturnImpl( override val returnTarget: CallableDescriptor, override var value: IrExpression ) : IrExpressionBase(startOffset, endOffset, type), IrReturn { + constructor(startOffset: Int, endOffset: Int, returnTarget: CallableDescriptor, value: IrExpression) : + this(startOffset, endOffset, returnTarget.builtIns.nothingType, returnTarget, value) + override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitReturn(this, data) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrSyntheticBodyImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrSyntheticBodyImpl.kt index 67bb7015c1f..82a16739b8f 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrSyntheticBodyImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrSyntheticBodyImpl.kt @@ -34,4 +34,7 @@ class IrSyntheticBodyImpl(startOffset: Int, endOffset: Int, override val kind: I override fun transformChildren(transformer: IrElementTransformer, data: D) { // no children } + + override fun toString(): String = + "IrSyntheticBodyImpl($kind)" } \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTree.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTree.kt index 395a0472d26..ba35511b0d8 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTree.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DeepCopyIrTree.kt @@ -38,7 +38,7 @@ open class DeepCopyIrTree : IrElementTransformerVoid() { protected open fun mapClassDeclaration(descriptor: ClassDescriptor) = descriptor protected open fun mapTypeAliasDeclaration(descriptor: TypeAliasDescriptor) = descriptor protected open fun mapFunctionDeclaration(descriptor: FunctionDescriptor) = descriptor - protected open fun mapConstructorDeclaration(descriptor: ConstructorDescriptor) = descriptor + protected open fun mapConstructorDeclaration(descriptor: ClassConstructorDescriptor) = descriptor protected open fun mapPropertyDeclaration(descriptor: PropertyDescriptor) = descriptor protected open fun mapLocalPropertyDeclaration(descriptor: VariableDescriptorWithAccessors) = descriptor protected open fun mapEnumEntryDeclaration(descriptor: ClassDescriptor) = descriptor @@ -52,9 +52,8 @@ open class DeepCopyIrTree : IrElementTransformerVoid() { protected open fun mapPropertyReference(descriptor: PropertyDescriptor) = descriptor protected open fun mapReceiverParameterReference(descriptor: ReceiverParameterDescriptor) = descriptor protected open fun mapCallee(descriptor: CallableDescriptor) = descriptor - protected open fun mapDelegatedConstructorCallee(descriptor: ConstructorDescriptor) = descriptor - protected open fun mapEnumConstructorCallee(descriptor: ConstructorDescriptor) = descriptor - protected open fun mapEnumEntryInConstructor(descriptor: ClassDescriptor?) = descriptor + protected open fun mapDelegatedConstructorCallee(descriptor: ClassConstructorDescriptor) = descriptor + protected open fun mapEnumConstructorCallee(descriptor: ClassConstructorDescriptor) = descriptor protected open fun mapCallableReference(descriptor: CallableDescriptor) = descriptor protected open fun mapClassifierReference(descriptor: ClassifierDescriptor) = descriptor protected open fun mapReturnTarget(descriptor: CallableDescriptor) = mapCallee(descriptor) @@ -346,8 +345,7 @@ open class DeepCopyIrTree : IrElementTransformerVoid() { override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrEnumConstructorCall = IrEnumConstructorCallImpl( expression.startOffset, expression.endOffset, - mapEnumConstructorCallee(expression.descriptor), - mapEnumEntryInConstructor(expression.enumEntryDescriptor) + mapEnumConstructorCallee(expression.descriptor) ).transformValueArguments(expression) override fun visitGetClass(expression: IrGetClass): IrGetClass = diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt index 77e8de6c4cc..4e280846fb6 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt @@ -119,11 +119,7 @@ class RenderIrElementVisitor : IrElementVisitor { "DELEGATING_CONSTRUCTOR_CALL '${expression.descriptor.ref()}'" override fun visitEnumConstructorCall(expression: IrEnumConstructorCall, data: Nothing?): String = - "ENUM_CONSTRUCTOR_CALL '${expression.descriptor.ref()}' " + - expression.enumEntryDescriptor.let { enumEntryDescriptor -> - if (enumEntryDescriptor == null) "super" - else enumEntryDescriptor.ref() - } + "ENUM_CONSTRUCTOR_CALL '${expression.descriptor.ref()}'" override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall, data: Nothing?): String = "INSTANCE_INITIALIZER_CALL classDescriptor='${expression.classDescriptor.ref()}'" diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/transform.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/transform.kt new file mode 100644 index 00000000000..9c2eaaa53e6 --- /dev/null +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/transform.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.ir.util + +inline fun MutableList.transform(transformation: (T) -> T) { + forEachIndexed { i, item -> + set(i, transformation(item)) + } +} + +/** + * Transforms a mutable list in place. + * Each element `it` is replaced with a result of `transformation(it)`, + * `null` means "keep existing element" (to avoid creating excessive singleton lists). + */ +inline fun MutableList.transformFlat(transformation: (T) -> List?) { + var i = 0 + while (i < size) { + val item = get(i) + + val transformed = transformation(item) + + if (transformed == null) { + i++ + continue + } + + addAll(i, transformed) + i += transformed.size + removeAt(i) + } +} \ No newline at end of file diff --git a/compiler/testData/ir/box/enumClass.kt b/compiler/testData/ir/box/enumClass.kt new file mode 100644 index 00000000000..f6cff0fca61 --- /dev/null +++ b/compiler/testData/ir/box/enumClass.kt @@ -0,0 +1,3 @@ +enum class Test { OK } + +fun box() = Test.OK.toString() \ No newline at end of file diff --git a/compiler/testData/ir/irText/classes/classes.txt b/compiler/testData/ir/irText/classes/classes.txt index f9876c77025..bb3d96975f4 100644 --- a/compiler/testData/ir/irText/classes/classes.txt +++ b/compiler/testData/ir/irText/classes/classes.txt @@ -14,7 +14,7 @@ FILE /classes.kt CLASS ENUM_CLASS TestEnumClass CONSTRUCTOR private constructor TestEnumClass() BLOCK_BODY - ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' super + ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' INSTANCE_INITIALIZER_CALL classDescriptor='TestEnumClass' FUN ENUM_CLASS_SPECIAL_MEMBER public final fun values(): kotlin.Array SYNTHETIC_BODY kind=ENUM_VALUES diff --git a/compiler/testData/ir/irText/classes/enum.txt b/compiler/testData/ir/irText/classes/enum.txt index 10477010513..1d8e558f76f 100644 --- a/compiler/testData/ir/irText/classes/enum.txt +++ b/compiler/testData/ir/irText/classes/enum.txt @@ -2,12 +2,12 @@ FILE /enum.kt CLASS ENUM_CLASS TestEnum1 CONSTRUCTOR private constructor TestEnum1() BLOCK_BODY - ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' super + ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' INSTANCE_INITIALIZER_CALL classDescriptor='TestEnum1' ENUM_ENTRY enum entry TEST1 - init: ENUM_CONSTRUCTOR_CALL 'constructor TestEnum1()' TEST1 + init: ENUM_CONSTRUCTOR_CALL 'constructor TestEnum1()' ENUM_ENTRY enum entry TEST2 - init: ENUM_CONSTRUCTOR_CALL 'constructor TestEnum1()' TEST2 + init: ENUM_CONSTRUCTOR_CALL 'constructor TestEnum1()' FUN ENUM_CLASS_SPECIAL_MEMBER public final fun values(): kotlin.Array SYNTHETIC_BODY kind=ENUM_VALUES FUN ENUM_CLASS_SPECIAL_MEMBER public final fun valueOf(value: kotlin.String): TestEnum1 @@ -15,7 +15,7 @@ FILE /enum.kt CLASS ENUM_CLASS TestEnum2 CONSTRUCTOR private constructor TestEnum2(x: kotlin.Int) BLOCK_BODY - ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' super + ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' INSTANCE_INITIALIZER_CALL classDescriptor='TestEnum2' PROPERTY public final val x: kotlin.Int FIELD PROPERTY_BACKING_FIELD public final val x: kotlin.Int @@ -27,13 +27,13 @@ FILE /enum.kt GET_FIELD 'x: Int' type=kotlin.Int origin=null receiver: THIS of 'TestEnum2' type=TestEnum2 ENUM_ENTRY enum entry TEST1 - init: ENUM_CONSTRUCTOR_CALL 'constructor TestEnum2(Int)' TEST1 + init: ENUM_CONSTRUCTOR_CALL 'constructor TestEnum2(Int)' x: CONST Int type=kotlin.Int value='1' ENUM_ENTRY enum entry TEST2 - init: ENUM_CONSTRUCTOR_CALL 'constructor TestEnum2(Int)' TEST2 + init: ENUM_CONSTRUCTOR_CALL 'constructor TestEnum2(Int)' x: CONST Int type=kotlin.Int value='2' ENUM_ENTRY enum entry TEST3 - init: ENUM_CONSTRUCTOR_CALL 'constructor TestEnum2(Int)' TEST3 + init: ENUM_CONSTRUCTOR_CALL 'constructor TestEnum2(Int)' x: CONST Int type=kotlin.Int value='3' FUN ENUM_CLASS_SPECIAL_MEMBER public final fun values(): kotlin.Array SYNTHETIC_BODY kind=ENUM_VALUES @@ -42,14 +42,14 @@ FILE /enum.kt CLASS ENUM_CLASS TestEnum3 CONSTRUCTOR private constructor TestEnum3() BLOCK_BODY - ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' super + ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' INSTANCE_INITIALIZER_CALL classDescriptor='TestEnum3' ENUM_ENTRY enum entry TEST - init: ENUM_CONSTRUCTOR_CALL 'constructor TEST()' TEST + init: ENUM_CONSTRUCTOR_CALL 'constructor TEST()' class: CLASS ENUM_ENTRY TEST CONSTRUCTOR private constructor TEST() BLOCK_BODY - ENUM_CONSTRUCTOR_CALL 'constructor TestEnum3()' super + ENUM_CONSTRUCTOR_CALL 'constructor TestEnum3()' INSTANCE_INITIALIZER_CALL classDescriptor='TEST' FUN public open override fun foo(): kotlin.Unit BLOCK_BODY @@ -63,7 +63,7 @@ FILE /enum.kt CLASS ENUM_CLASS TestEnum4 CONSTRUCTOR private constructor TestEnum4(x: kotlin.Int) BLOCK_BODY - ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' super + ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' INSTANCE_INITIALIZER_CALL classDescriptor='TestEnum4' PROPERTY public final val x: kotlin.Int FIELD PROPERTY_BACKING_FIELD public final val x: kotlin.Int @@ -75,11 +75,11 @@ FILE /enum.kt GET_FIELD 'x: Int' type=kotlin.Int origin=null receiver: THIS of 'TestEnum4' type=TestEnum4 ENUM_ENTRY enum entry TEST1 - init: ENUM_CONSTRUCTOR_CALL 'constructor TEST1()' TEST1 + init: ENUM_CONSTRUCTOR_CALL 'constructor TEST1()' class: CLASS ENUM_ENTRY TEST1 CONSTRUCTOR private constructor TEST1() BLOCK_BODY - ENUM_CONSTRUCTOR_CALL 'constructor TestEnum4(Int)' super + ENUM_CONSTRUCTOR_CALL 'constructor TestEnum4(Int)' x: CONST Int type=kotlin.Int value='1' INSTANCE_INITIALIZER_CALL classDescriptor='TEST1' FUN public open override fun foo(): kotlin.Unit @@ -87,11 +87,11 @@ FILE /enum.kt CALL 'println(Any?): Unit' type=kotlin.Unit origin=null message: GET_ENUM 'TEST1' type=TestEnum4 ENUM_ENTRY enum entry TEST2 - init: ENUM_CONSTRUCTOR_CALL 'constructor TEST2()' TEST2 + init: ENUM_CONSTRUCTOR_CALL 'constructor TEST2()' class: CLASS ENUM_ENTRY TEST2 CONSTRUCTOR private constructor TEST2() BLOCK_BODY - ENUM_CONSTRUCTOR_CALL 'constructor TestEnum4(Int)' super + ENUM_CONSTRUCTOR_CALL 'constructor TestEnum4(Int)' x: CONST Int type=kotlin.Int value='2' INSTANCE_INITIALIZER_CALL classDescriptor='TEST2' PROPERTY public final val z: kotlin.Int diff --git a/compiler/testData/ir/irText/classes/enumWithSecondaryCtor.kt b/compiler/testData/ir/irText/classes/enumWithSecondaryCtor.kt new file mode 100644 index 00000000000..9cc49a2aa03 --- /dev/null +++ b/compiler/testData/ir/irText/classes/enumWithSecondaryCtor.kt @@ -0,0 +1,21 @@ +// WITH_RUNTIME + +enum class Test1(val x: Int) { + ZERO, ONE(1); + constructor() : this(0) +} + +enum class Test2(val x: Int) { + ZERO { + override fun foo() { + println("ZERO") + } + }, + ONE(1) { + override fun foo() { + println("ONE") + } + }; + constructor() : this(0) + abstract fun foo() +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/classes/enumWithSecondaryCtor.txt b/compiler/testData/ir/irText/classes/enumWithSecondaryCtor.txt new file mode 100644 index 00000000000..3fea0492494 --- /dev/null +++ b/compiler/testData/ir/irText/classes/enumWithSecondaryCtor.txt @@ -0,0 +1,74 @@ +FILE /enumWithSecondaryCtor.kt + CLASS ENUM_CLASS Test1 + CONSTRUCTOR private constructor Test1(x: kotlin.Int) + BLOCK_BODY + ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' + INSTANCE_INITIALIZER_CALL classDescriptor='Test1' + PROPERTY public final val x: kotlin.Int + FIELD PROPERTY_BACKING_FIELD public final val x: kotlin.Int + EXPRESSION_BODY + GET_VAR 'value-parameter x: Int' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR public final fun (): kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Int' + GET_FIELD 'x: Int' type=kotlin.Int origin=null + receiver: THIS of 'Test1' type=Test1 + ENUM_ENTRY enum entry ZERO + init: ENUM_CONSTRUCTOR_CALL 'constructor Test1(Int)' + ENUM_ENTRY enum entry ONE + init: ENUM_CONSTRUCTOR_CALL 'constructor Test1(Int)' + x: CONST Int type=kotlin.Int value='1' + CONSTRUCTOR private constructor Test1() + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'constructor Test1(Int)' + x: CONST Int type=kotlin.Int value='0' + FUN ENUM_CLASS_SPECIAL_MEMBER public final fun values(): kotlin.Array + SYNTHETIC_BODY kind=ENUM_VALUES + FUN ENUM_CLASS_SPECIAL_MEMBER public final fun valueOf(value: kotlin.String): Test1 + SYNTHETIC_BODY kind=ENUM_VALUEOF + CLASS ENUM_CLASS Test2 + CONSTRUCTOR private constructor Test2(x: kotlin.Int) + BLOCK_BODY + ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' + INSTANCE_INITIALIZER_CALL classDescriptor='Test2' + PROPERTY public final val x: kotlin.Int + FIELD PROPERTY_BACKING_FIELD public final val x: kotlin.Int + EXPRESSION_BODY + GET_VAR 'value-parameter x: Int' type=kotlin.Int origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR public final fun (): kotlin.Int + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Int' + GET_FIELD 'x: Int' type=kotlin.Int origin=null + receiver: THIS of 'Test2' type=Test2 + ENUM_ENTRY enum entry ZERO + init: ENUM_CONSTRUCTOR_CALL 'constructor ZERO()' + class: CLASS ENUM_ENTRY ZERO + CONSTRUCTOR private constructor ZERO() + BLOCK_BODY + ENUM_CONSTRUCTOR_CALL 'constructor Test2(Int)' + INSTANCE_INITIALIZER_CALL classDescriptor='ZERO' + FUN public open override fun foo(): kotlin.Unit + BLOCK_BODY + CALL 'println(Any?): Unit' type=kotlin.Unit origin=null + message: CONST String type=kotlin.String value='ZERO' + ENUM_ENTRY enum entry ONE + init: ENUM_CONSTRUCTOR_CALL 'constructor ONE()' + class: CLASS ENUM_ENTRY ONE + CONSTRUCTOR private constructor ONE() + BLOCK_BODY + ENUM_CONSTRUCTOR_CALL 'constructor Test2(Int)' + x: CONST Int type=kotlin.Int value='1' + INSTANCE_INITIALIZER_CALL classDescriptor='ONE' + FUN public open override fun foo(): kotlin.Unit + BLOCK_BODY + CALL 'println(Any?): Unit' type=kotlin.Unit origin=null + message: CONST String type=kotlin.String value='ONE' + CONSTRUCTOR private constructor Test2() + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'constructor Test2(Int)' + x: CONST Int type=kotlin.Int value='0' + FUN public abstract fun foo(): kotlin.Unit + FUN ENUM_CLASS_SPECIAL_MEMBER public final fun values(): kotlin.Array + SYNTHETIC_BODY kind=ENUM_VALUES + FUN ENUM_CLASS_SPECIAL_MEMBER public final fun valueOf(value: kotlin.String): Test2 + SYNTHETIC_BODY kind=ENUM_VALUEOF diff --git a/compiler/testData/ir/irText/expressions/values.txt b/compiler/testData/ir/irText/expressions/values.txt index a802efe2b52..cd7d7a4dcb5 100644 --- a/compiler/testData/ir/irText/expressions/values.txt +++ b/compiler/testData/ir/irText/expressions/values.txt @@ -2,10 +2,10 @@ FILE /values.kt CLASS ENUM_CLASS Enum CONSTRUCTOR private constructor Enum() BLOCK_BODY - ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' super + ENUM_CONSTRUCTOR_CALL 'constructor Enum(String, Int)' INSTANCE_INITIALIZER_CALL classDescriptor='Enum' ENUM_ENTRY enum entry A - init: ENUM_CONSTRUCTOR_CALL 'constructor Enum()' A + init: ENUM_CONSTRUCTOR_CALL 'constructor Enum()' FUN ENUM_CLASS_SPECIAL_MEMBER public final fun values(): kotlin.Array SYNTHETIC_BODY kind=ENUM_VALUES FUN ENUM_CLASS_SPECIAL_MEMBER public final fun valueOf(value: kotlin.String): Enum diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrOnlyBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrOnlyBoxCodegenTestGenerated.java index be0bc5346fe..45c0c35d9c2 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrOnlyBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrOnlyBoxCodegenTestGenerated.java @@ -41,6 +41,12 @@ public class IrOnlyBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTest doTest(fileName); } + @TestMetadata("enumClass.kt") + public void testEnumClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/box/enumClass.kt"); + doTest(fileName); + } + @TestMetadata("fileClassInitializers.kt") public void testFileClassInitializers() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/box/fileClassInitializers.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index 15fc67d867e..75149c97c6c 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -97,6 +97,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { doTest(fileName); } + @TestMetadata("enumWithSecondaryCtor.kt") + public void testEnumWithSecondaryCtor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/classes/enumWithSecondaryCtor.kt"); + doTest(fileName); + } + @TestMetadata("initBlock.kt") public void testInitBlock() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/classes/initBlock.kt"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ClassConstructorDescriptorImpl.java b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ClassConstructorDescriptorImpl.java index f0c209ad3d1..cf0ad2eb707 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ClassConstructorDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/ClassConstructorDescriptorImpl.java @@ -55,6 +55,16 @@ public class ClassConstructorDescriptorImpl extends FunctionDescriptorImpl imple return new ClassConstructorDescriptorImpl(containingDeclaration, null, annotations, isPrimary, Kind.DECLARATION, source); } + @NotNull + public static ClassConstructorDescriptorImpl createSynthesized( + @NotNull ClassDescriptor containingDeclaration, + @NotNull Annotations annotations, + boolean isPrimary, + @NotNull SourceElement source + ) { + return new ClassConstructorDescriptorImpl(containingDeclaration, null, annotations, isPrimary, Kind.SYNTHESIZED, source); + } + public ClassConstructorDescriptorImpl initialize( @NotNull List unsubstitutedValueParameters, @NotNull Visibility visibility,