Enum classes lowering.

This commit is contained in:
Dmitry Petrov
2016-09-28 15:11:37 +03:00
parent af76840826
commit fc754e533d
48 changed files with 1053 additions and 222 deletions
@@ -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(
@@ -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")
}
@@ -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)
}
@@ -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
}
}
@@ -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)
}
})
}
@@ -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 {
@@ -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
}
}
}
@@ -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<ClassDescriptor, PropertyDescriptor>()
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
)
}
}
@@ -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
}
}
@@ -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)
}
}
@@ -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)
}
}
}
}
@@ -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]
}
}
@@ -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>): 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<ClassDescriptor>()
private val loweredEnumConstructors = HashMap<ClassConstructorDescriptor, ClassConstructorDescriptor>()
private val loweredEnumConstructorParameters = HashMap<ValueParameterDescriptor, ValueParameterDescriptor>()
private val enumEntriesByField = HashMap<PropertyDescriptor, ClassDescriptor>()
private val enumEntryFields = ArrayList<PropertyDescriptor>()
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))
)
}
}
}
}
@@ -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<IrClass>()
val fileClassMembers = ArrayList<IrDeclaration>()
@@ -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)
@@ -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
@@ -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<SourceManager.FileEntry, JvmFileClassInfo>()
private val sourceElementByFileEntry = HashMap<SourceManager.FileEntry, SourceElement>()
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)
}
}
@@ -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<IrDeclaration>) {
val newDeclarations = ArrayList<IrDeclaration>()
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<IrDeclaration>? =
if (declaration is IrProperty)
ArrayList<IrDeclaration>(3).apply {
addIfNotNull(declaration.backingField)
addIfNotNull(declaration.getter)
addIfNotNull(declaration.setter)
}
else
null
}
@@ -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)
}
}
@@ -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)
@@ -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<KtLoopExpression, IrLoop>()
@@ -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)
}
}
@@ -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)
}
}
@@ -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)
@@ -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
}
@@ -16,6 +16,8 @@
package org.jetbrains.kotlin.ir.declarations
import org.jetbrains.kotlin.ir.util.transformFlat
interface IrDeclarationContainer {
val declarations: MutableList<IrDeclaration>
}
}
@@ -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
@@ -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<KotlinType>): IrBuiltinOperatorDescriptor {
fun defineOperator(name: String, returnType: KotlinType, valueParameterTypes: List<KotlinType>): 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")
}
}
@@ -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
@@ -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<IrStatement>
}
interface IrBlockBody : IrBody, IrStatementContainer
interface IrSyntheticBody : IrBody {
@@ -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
}
@@ -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
@@ -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<IrStatement>
}
@@ -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<TypeParameterDescriptor, KotlinType>? = null,
origin: IrStatementOrigin? = null,
superQualifier: ClassDescriptor? = null
) : this(startOffset, endOffset, descriptor.returnType!!, descriptor, typeArguments, origin, superQualifier)
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
visitor.visitCall(this, data)
@@ -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<TypeParameterDescriptor, KotlinType>?
override val descriptor: ClassConstructorDescriptor,
typeArguments: Map<TypeParameterDescriptor, KotlinType>? = null
) : IrCallWithIndexedArgumentsBase(startOffset, endOffset, descriptor.builtIns.unitType, descriptor.valueParameters.size, typeArguments),
IrDelegatingConstructorCall {
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R {
@@ -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 <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R {
@@ -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 <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
visitor.visitReturn(this, data)
@@ -34,4 +34,7 @@ class IrSyntheticBodyImpl(startOffset: Int, endOffset: Int, override val kind: I
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
// no children
}
override fun toString(): String =
"IrSyntheticBodyImpl($kind)"
}
@@ -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 =
@@ -119,11 +119,7 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
"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()}'"
@@ -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 <T> MutableList<T>.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 <T> MutableList<T>.transformFlat(transformation: (T) -> List<T>?) {
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)
}
}
+3
View File
@@ -0,0 +1,3 @@
enum class Test { OK }
fun box() = Test.OK.toString()
+1 -1
View File
@@ -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<TestEnumClass>
SYNTHETIC_BODY kind=ENUM_VALUES
+15 -15
View File
@@ -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<TestEnum1>
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<TestEnum2>
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
@@ -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()
}
@@ -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 <get-x>(): kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from='<get-x>(): 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<Test1>
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 <get-x>(): kotlin.Int
BLOCK_BODY
RETURN type=kotlin.Nothing from='<get-x>(): 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<Test2>
SYNTHETIC_BODY kind=ENUM_VALUES
FUN ENUM_CLASS_SPECIAL_MEMBER public final fun valueOf(value: kotlin.String): Test2
SYNTHETIC_BODY kind=ENUM_VALUEOF
+2 -2
View File
@@ -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<Enum>
SYNTHETIC_BODY kind=ENUM_VALUES
FUN ENUM_CLASS_SPECIAL_MEMBER public final fun valueOf(value: kotlin.String): Enum
@@ -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");
@@ -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");
@@ -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<ValueParameterDescriptor> unsubstitutedValueParameters,
@NotNull Visibility visibility,