Shared variables lowering.

This commit is contained in:
Dmitry Petrov
2016-10-07 15:01:09 +03:00
parent fedfd3de16
commit fb5298237a
19 changed files with 751 additions and 136 deletions
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.backend.jvm
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmSharedVariablesManager
import org.jetbrains.kotlin.backend.jvm.descriptors.SpecialDescriptorsFactory
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
@@ -27,6 +28,6 @@ class JvmBackendContext(
val irBuiltIns: IrBuiltIns
) {
val builtIns = state.module.builtIns
val specialDescriptorsFactory = SpecialDescriptorsFactory(psiSourceManager)
val specialDescriptorsFactory = SpecialDescriptorsFactory(psiSourceManager, builtIns)
val sharedVariablesManager = JvmSharedVariablesManager(irBuiltIns)
}
@@ -20,6 +20,7 @@ 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.IrFile
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.expressions.IrBody
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
@@ -31,13 +32,14 @@ class JvmLower(val context: JvmBackendContext) {
FileClassLowering(context).lower(irFile)
ConstAndJvmFieldPropertiesLowering().lower(irFile)
PropertiesLowering().lower(irFile)
InterfaceLowering(context.state).runOnFile(irFile)
InterfaceDelegationLowering(context.state).runOnFile(irFile)
LocalFunctionsLowering(context).runOnFile(irFile)
EnumClassLowering(context).runOnFile(irFile)
ObjectClassLowering(context).runOnFile(irFile)
InitializersLowering(context).runOnFile(irFile)
SingletonReferencesLowering(context).runOnFile(irFile)
InterfaceLowering(context.state).runOnFilePostfix(irFile)
InterfaceDelegationLowering(context.state).runOnFilePostfix(irFile)
SharedVariablesLowering(context).runOnFilePostfix(irFile)
LocalFunctionsLowering(context).runOnFilePostfix(irFile)
EnumClassLowering(context).runOnFilePostfix(irFile)
ObjectClassLowering(context).runOnFilePostfix(irFile)
InitializersLowering(context).runOnFilePostfix(irFile)
SingletonReferencesLowering(context).runOnFilePostfix(irFile)
}
}
@@ -49,11 +51,15 @@ interface ClassLoweringPass {
fun lower(irClass: IrClass)
}
interface FunctionLoweringPass {
fun lower(irFunction: IrFunction)
}
interface BodyLoweringPass {
fun lower(irBody: IrBody)
}
fun ClassLoweringPass.runOnFile(irFile: IrFile) {
fun ClassLoweringPass.runOnFilePostfix(irFile: IrFile) {
irFile.acceptVoid(object : IrElementVisitorVoid {
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
@@ -66,7 +72,7 @@ fun ClassLoweringPass.runOnFile(irFile: IrFile) {
})
}
fun BodyLoweringPass.runOnFile(irFile: IrFile) {
fun BodyLoweringPass.runOnFilePostfix(irFile: IrFile) {
irFile.acceptVoid(object : IrElementVisitorVoid {
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
@@ -77,4 +83,17 @@ fun BodyLoweringPass.runOnFile(irFile: IrFile) {
lower(body)
}
})
}
fun FunctionLoweringPass.runOnFilePostfix(irFile: IrFile) {
irFile.acceptVoid(object : IrElementVisitorVoid {
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
override fun visitFunction(declaration: IrFunction) {
declaration.acceptChildrenVoid(this)
lower(declaration)
}
})
}
@@ -20,7 +20,7 @@ import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmSpecialDescriptor
import org.jetbrains.kotlin.backend.jvm.lower.FileClassDescriptor
import org.jetbrains.kotlin.backend.jvm.descriptors.FileClassDescriptor
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.MemberCodegen.badDescriptor
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
@@ -0,0 +1,40 @@
/*
* 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.name.Name
import org.jetbrains.kotlin.types.KotlinType
interface FileClassDescriptor : ClassDescriptor
class FileClassDescriptorImpl(
name: Name,
containingDeclaration: PackageFragmentDescriptor,
supertypes: List<KotlinType>,
sourceElement: SourceElement,
annotations: Annotations
) : FileClassDescriptor, KnownClassDescriptor(
name, containingDeclaration, sourceElement,
ClassKind.CLASS, Modality.FINAL, Visibilities.PUBLIC,
annotations
) {
init {
initialize(emptyList(), supertypes)
}
}
@@ -0,0 +1,153 @@
/*
* 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.LazyClassReceiverParameterDescriptor
import org.jetbrains.kotlin.descriptors.impl.PackageFragmentDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.*
open class KnownPackageFragmentDescriptor(moduleDescriptor: ModuleDescriptor, fqName: FqName) :
PackageFragmentDescriptorImpl(moduleDescriptor, fqName) {
override fun getMemberScope(): MemberScope = MemberScope.Empty
}
open class KnownClassDescriptor(
private val name: Name,
private val containingDeclaration: DeclarationDescriptor,
private val sourceElement: SourceElement,
private val kind: ClassKind,
private val modality: Modality,
private val visibility: Visibility,
override val annotations: Annotations
) : ClassDescriptor {
private lateinit var typeConstructor: TypeConstructor
private lateinit var supertypes: List<KotlinType>
private lateinit var defaultType: SimpleType
private lateinit var declaredTypeParameters: List<TypeParameterDescriptor>
private val thisAsReceiverParameter = LazyClassReceiverParameterDescriptor(this)
fun initialize(declaredTypeParameters: List<TypeParameterDescriptor>, supertypes: List<KotlinType>) {
this.declaredTypeParameters = declaredTypeParameters
this.supertypes = supertypes
this.typeConstructor = ClassTypeConstructorImpl(this, annotations, true, declaredTypeParameters, supertypes)
this.defaultType = TypeUtils.makeUnsubstitutedType(this, unsubstitutedMemberScope)
}
companion object {
fun createClass(
name: Name,
containingDeclaration: DeclarationDescriptor,
supertypes: List<KotlinType>,
modality: Modality = Modality.FINAL,
visibility: Visibility = Visibilities.PUBLIC,
annotations: Annotations = Annotations.EMPTY
) =
KnownClassDescriptor(
name, containingDeclaration,
SourceElement.NO_SOURCE, ClassKind.CLASS,
modality, visibility,
annotations
).apply {
initialize(emptyList(), supertypes)
}
inline fun createClassWithTypeParameters(
name: Name,
containingDeclaration: DeclarationDescriptor,
supertypes: List<KotlinType>,
modality: Modality = Modality.FINAL,
visibility: Visibility = Visibilities.PUBLIC,
annotations: Annotations = Annotations.EMPTY,
createTypeParameters: (ClassDescriptor) -> List<TypeParameterDescriptor>
) =
KnownClassDescriptor(
name, containingDeclaration,
SourceElement.NO_SOURCE, ClassKind.CLASS,
modality, visibility,
annotations
).apply {
initialize(createTypeParameters(this), supertypes)
}
fun createClassWithTypeParameters(
name: Name,
containingDeclaration: DeclarationDescriptor,
supertypes: List<KotlinType>,
typeParameterNames: List<Name>,
modality: Modality = Modality.FINAL,
visibility: Visibility = Visibilities.PUBLIC,
annotations: Annotations = Annotations.EMPTY
) =
createClassWithTypeParameters(name, containingDeclaration, supertypes, modality, visibility, annotations) { classDescriptor ->
typeParameterNames.mapIndexed { index, name ->
TypeParameterDescriptorImpl.createWithDefaultBound(
classDescriptor, Annotations.EMPTY, true, Variance.INVARIANT, name, index
)
}
}
}
override fun getCompanionObjectDescriptor(): ClassDescriptor? = null
override fun getConstructors(): Collection<ClassConstructorDescriptor> = emptyList()
override fun getContainingDeclaration(): DeclarationDescriptor = containingDeclaration
override fun getDeclaredTypeParameters(): List<TypeParameterDescriptor> = declaredTypeParameters
override fun getKind(): ClassKind = kind
override fun getMemberScope(typeArguments: MutableList<out TypeProjection>): MemberScope = MemberScope.Empty
override fun getMemberScope(typeSubstitution: TypeSubstitution): MemberScope = MemberScope.Empty
override fun getStaticScope(): MemberScope = MemberScope.Empty
override fun getUnsubstitutedInnerClassesScope(): MemberScope = MemberScope.Empty
override fun getUnsubstitutedMemberScope(): MemberScope = MemberScope.Empty
override fun getUnsubstitutedPrimaryConstructor(): ClassConstructorDescriptor? = null
override fun substitute(substitutor: TypeSubstitutor): ClassDescriptor = error("Class $this can't be substituted")
override fun getThisAsReceiverParameter(): ReceiverParameterDescriptor = thisAsReceiverParameter
override fun getModality(): Modality = modality
override fun getOriginal(): ClassDescriptor = this
override fun getName(): Name = name
override fun getVisibility(): Visibility = visibility
override fun getSource(): SourceElement = sourceElement
override fun getTypeConstructor(): TypeConstructor = typeConstructor
override fun getDefaultType(): SimpleType = defaultType
override fun isCompanionObject(): Boolean = false
override fun isData(): Boolean = false
override fun isInner(): Boolean = false
override fun <R : Any?, D : Any?> accept(visitor: DeclarationDescriptorVisitor<R, D>, data: D): R {
return visitor.visitClassDescriptor(this, data)
}
override fun acceptVoid(visitor: DeclarationDescriptorVisitor<Void, Void>) {
visitor.visitClassDescriptor(this, null)
}
override fun toString(): String =
"KnownClassDescriptor($fqNameUnsafe)"
}
@@ -0,0 +1,209 @@
/*
* 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.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.PrimitiveType
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.LocalVariableDescriptor
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrGetValue
import org.jetbrains.kotlin.ir.expressions.IrSetVariable
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.*
interface SharedVariablesManager {
fun createSharedVariableDescriptor(variableDescriptor: VariableDescriptor): VariableDescriptor
fun defineSharedValue(sharedVariableDescriptor: VariableDescriptor, originalDeclaration: IrVariable): IrStatement
fun getSharedValue(sharedVariableDescriptor: VariableDescriptor, originalGet: IrGetValue): IrExpression
fun setSharedValue(sharedVariableDescriptor: VariableDescriptor, originalSet: IrSetVariable): IrExpression
}
class JvmSharedVariablesManager(val irBuiltIns: IrBuiltIns) : SharedVariablesManager {
private val builtIns = irBuiltIns.builtIns
private val fromAny = listOf(builtIns.anyType)
private val kotlinJvmInternalPackage = KnownPackageFragmentDescriptor(builtIns.builtInsModule, FqName("kotlin.jvm.internal"))
private val refNamespaceClass = KnownClassDescriptor.createClass(Name.identifier("Ref"), kotlinJvmInternalPackage, fromAny)
private class PrimitiveRefDescriptorsProvider(type: KotlinType, refClass: ClassDescriptor) {
val refType: KotlinType = refClass.defaultType
val refConstructor: ClassConstructorDescriptor =
ClassConstructorDescriptorImpl.create(refClass, Annotations.EMPTY, true, SourceElement.NO_SOURCE).apply {
initialize(emptyList(), Visibilities.PUBLIC, emptyList())
returnType = refType
}
val elementField: PropertyDescriptor =
PropertyDescriptorImpl.create(
refClass, Annotations.EMPTY, Modality.FINAL, Visibilities.PUBLIC, true,
Name.identifier("element"), CallableMemberDescriptor.Kind.DECLARATION, SourceElement.NO_SOURCE,
false, false
).initialize(type, dispatchReceiverParameter = refClass.thisAsReceiverParameter)
}
private val primitiveRefDescriptorProviders =
PrimitiveType.values().associate {
val type = builtIns.getPrimitiveKotlinType(it)
val refClassName = Name.identifier(it.typeName.asString() + "Ref")
val refClass = KnownClassDescriptor.createClass(refClassName, refNamespaceClass, fromAny)
it to PrimitiveRefDescriptorsProvider(type, refClass)
}
private inner class ObjectRefDescriptorsProvider {
val genericRefClass: ClassDescriptor =
KnownClassDescriptor.createClassWithTypeParameters(
Name.identifier("ObjectRef"), refNamespaceClass, fromAny, listOf(Name.identifier("T"))
)
val genericRefConstructor: ClassConstructorDescriptor =
ClassConstructorDescriptorImpl.create(genericRefClass, Annotations.EMPTY, true, SourceElement.NO_SOURCE).apply {
initialize(emptyList(), Visibilities.PUBLIC)
val typeParameter = typeParameters[0]
val typeParameterType = KotlinTypeFactory.simpleType(Annotations.EMPTY, typeParameter.typeConstructor, listOf(), false, MemberScope.Empty)
returnType = KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, genericRefClass, listOf(TypeProjectionImpl(Variance.INVARIANT, typeParameterType)))
}
val constructorTypeParameter: TypeParameterDescriptor =
genericRefConstructor.typeParameters[0]
fun getSubstitutedRefConstructor(valueType: KotlinType): ClassConstructorDescriptor =
genericRefConstructor.substitute(TypeSubstitutor.create(
mapOf(constructorTypeParameter.typeConstructor to TypeProjectionImpl(Variance.INVARIANT, valueType))
))
val genericElementField: PropertyDescriptor =
PropertyDescriptorImpl.create(
genericRefClass, Annotations.EMPTY, Modality.FINAL, Visibilities.PUBLIC, true,
Name.identifier("element"), CallableMemberDescriptor.Kind.DECLARATION, SourceElement.NO_SOURCE,
false, false
).initialize(
type = builtIns.anyType,
dispatchReceiverParameter = genericRefClass.thisAsReceiverParameter
)
fun getRefType(valueType: KotlinType) =
KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, genericRefClass, listOf(TypeProjectionImpl(Variance.INVARIANT, valueType)))
}
private val objectRefDescriptorsProvider = ObjectRefDescriptorsProvider()
override fun createSharedVariableDescriptor(variableDescriptor: VariableDescriptor): VariableDescriptor =
LocalVariableDescriptor(
variableDescriptor.containingDeclaration, variableDescriptor.annotations, variableDescriptor.name,
getSharedVariableType(variableDescriptor.type),
false, false, variableDescriptor.source
)
override fun defineSharedValue(sharedVariableDescriptor: VariableDescriptor, originalDeclaration: IrVariable): IrStatement {
val valueType = originalDeclaration.descriptor.type
val primitiveRefDescriptorsProvider = primitiveRefDescriptorProviders[getPrimitiveType(valueType)]
val refConstructor =
primitiveRefDescriptorsProvider?.refConstructor ?:
objectRefDescriptorsProvider.getSubstitutedRefConstructor(valueType)
val refConstructorTypeArguments =
if (primitiveRefDescriptorsProvider != null) null
else mapOf(objectRefDescriptorsProvider.constructorTypeParameter to valueType)
val elementPropertyDescriptor =
primitiveRefDescriptorsProvider?.elementField ?:
objectRefDescriptorsProvider.genericElementField
val refConstructorCall = IrCallImpl(
originalDeclaration.startOffset, originalDeclaration.endOffset,
refConstructor, refConstructorTypeArguments
)
val sharedVariableDeclaration = IrVariableImpl(
originalDeclaration.startOffset, originalDeclaration.endOffset, originalDeclaration.origin,
sharedVariableDescriptor, refConstructorCall
)
val initializer = originalDeclaration.initializer ?:
return sharedVariableDeclaration
val sharedVariableInitialization = IrSetFieldImpl(
initializer.startOffset, initializer.endOffset,
elementPropertyDescriptor,
IrGetValueImpl(initializer.startOffset, initializer.endOffset, sharedVariableDescriptor),
initializer
)
return IrCompositeImpl(
originalDeclaration.startOffset, originalDeclaration.endOffset, builtIns.unitType, null,
listOf(sharedVariableDeclaration, sharedVariableInitialization)
)
}
private fun getElementFieldDescriptor(valueType: KotlinType): PropertyDescriptor {
val primitiveRefDescriptorsProvider = primitiveRefDescriptorProviders[getPrimitiveType(valueType)]
return primitiveRefDescriptorsProvider?.elementField ?:
objectRefDescriptorsProvider.genericElementField
}
override fun getSharedValue(sharedVariableDescriptor: VariableDescriptor, originalGet: IrGetValue): IrExpression =
IrGetFieldImpl(
originalGet.startOffset, originalGet.endOffset,
getElementFieldDescriptor(originalGet.descriptor.type),
IrGetValueImpl(originalGet.startOffset, originalGet.endOffset, sharedVariableDescriptor),
originalGet.origin
)
override fun setSharedValue(sharedVariableDescriptor: VariableDescriptor, originalSet: IrSetVariable): IrExpression =
IrSetFieldImpl(
originalSet.startOffset, originalSet.endOffset,
getElementFieldDescriptor(originalSet.descriptor.type),
IrGetValueImpl(originalSet.startOffset, originalSet.endOffset, sharedVariableDescriptor),
originalSet.value,
originalSet.origin
)
private fun getSharedVariableType(valueType: KotlinType): KotlinType =
primitiveRefDescriptorProviders[getPrimitiveType(valueType)]?.refType ?:
objectRefDescriptorsProvider.getRefType(valueType)
private fun getPrimitiveType(type: KotlinType): PrimitiveType? =
when {
KotlinBuiltIns.isBoolean(type) -> PrimitiveType.BOOLEAN
KotlinBuiltIns.isChar(type) -> PrimitiveType.CHAR
KotlinBuiltIns.isByte(type) -> PrimitiveType.BYTE
KotlinBuiltIns.isShort(type) -> PrimitiveType.SHORT
KotlinBuiltIns.isInt(type) -> PrimitiveType.INT
KotlinBuiltIns.isLong(type) -> PrimitiveType.LONG
KotlinBuiltIns.isFloat(type) -> PrimitiveType.FLOAT
KotlinBuiltIns.isDouble(type) -> PrimitiveType.DOUBLE
else -> null
}
}
@@ -16,8 +16,7 @@
package org.jetbrains.kotlin.backend.jvm.descriptors
import org.jetbrains.kotlin.backend.jvm.lower.FileClassDescriptor
import org.jetbrains.kotlin.backend.jvm.lower.FileClassDescriptorImpl
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
@@ -29,7 +28,10 @@ import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
import org.jetbrains.org.objectweb.asm.Opcodes
import java.util.*
class SpecialDescriptorsFactory(val psiSourceManager: PsiSourceManager) {
class SpecialDescriptorsFactory(
val psiSourceManager: PsiSourceManager,
val builtIns: KotlinBuiltIns
) {
private val singletonFieldDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>()
fun getFieldDescriptorForEnumEntry(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor =
@@ -42,7 +44,12 @@ class SpecialDescriptorsFactory(val psiSourceManager: PsiSourceManager) {
?: throw AssertionError("Unexpected file entry: $fileEntry")
val fileClassInfo = JvmFileClassUtil.getFileClassInfoNoResolve(ktFile)
val sourceElement = KotlinSourceElement(ktFile)
return FileClassDescriptorImpl(fileClassInfo.fileClassFqName.shortName(), packageFragment, sourceElement)
return FileClassDescriptorImpl(
fileClassInfo.fileClassFqName.shortName(), packageFragment,
listOf(builtIns.anyType),
sourceElement,
Annotations.EMPTY // TODO file annotations
)
}
private fun createEnumEntryFieldDescriptor(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor {
@@ -76,8 +83,7 @@ class SpecialDescriptorsFactory(val psiSourceManager: PsiSourceManager) {
Annotations.EMPTY, Modality.FINAL, Visibilities.PUBLIC, false,
Name.identifier("INSTANCE"),
CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE, false, false
)
instanceFieldDescriptor.setType(objectDescriptor.defaultType, listOf(), null as ReceiverParameterDescriptor?, null as ReceiverParameterDescriptor?)
).initialize(objectDescriptor.defaultType)
return instanceFieldDescriptor
}
@@ -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.descriptors
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PropertySetterDescriptorImpl
import org.jetbrains.kotlin.types.KotlinType
fun PropertyDescriptorImpl.initialize(
type: KotlinType,
typeParameters: List<TypeParameterDescriptor> = emptyList(),
dispatchReceiverParameter: ReceiverParameterDescriptor? = null,
extensionReceiverParameter: ReceiverParameterDescriptor? = null,
getter: PropertyGetterDescriptorImpl? = null,
setter: PropertySetterDescriptorImpl? = null
): PropertyDescriptorImpl {
setType(type, typeParameters, dispatchReceiverParameter, extensionReceiverParameter)
initialize(getter, setter)
return this
}
@@ -83,6 +83,7 @@ class Concat : IntrinsicMethod() {
override fun genArg(expression: IrExpression, codegen: org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen, index: Int, data: BlockInfo) {
super.genArg(expression, codegen, index, data)
if (index == 0) {
codegen.mv.checkcast(AsmTypes.JAVA_STRING_TYPE)
codegen.mv.invokespecial("java/lang/StringBuilder", "<init>", "(Ljava/lang/String;)V", false)
}
}
@@ -1,78 +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.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.*
interface FileClassDescriptor : ClassDescriptor
class FileClassDescriptorImpl(
private val nameImpl: Name,
private val containingDeclarationImpl: PackageFragmentDescriptor,
private val sourceElement: SourceElement
) : FileClassDescriptor {
override fun getCompanionObjectDescriptor(): ClassDescriptor? = null
override fun getConstructors(): Collection<ClassConstructorDescriptor> = emptyList()
override fun getContainingDeclaration(): DeclarationDescriptor = containingDeclarationImpl
override fun getDeclaredTypeParameters(): List<TypeParameterDescriptor> = emptyList()
override fun getKind(): ClassKind = ClassKind.CLASS
override fun getMemberScope(typeSubstitution: TypeSubstitution): MemberScope = error("File class has no member scope")
override fun getModality(): Modality = Modality.FINAL
override fun getOriginal(): ClassDescriptor = this
override fun getName(): Name = nameImpl
override fun getStaticScope(): MemberScope = error("File class has no static scope")
override fun getThisAsReceiverParameter(): ReceiverParameterDescriptor = error("File class has no instances")
override fun getUnsubstitutedInnerClassesScope(): MemberScope = error("File class has no inner classes scope")
override fun getUnsubstitutedMemberScope(): MemberScope = error("File class has no member scope")
override fun getUnsubstitutedPrimaryConstructor(): ClassConstructorDescriptor? = null
override fun getVisibility(): Visibility = Visibilities.PUBLIC
override fun isCompanionObject(): Boolean = false
override fun isData(): Boolean = false
override fun substitute(substitutor: TypeSubstitutor): ClassDescriptor = error("File class can't be substituted")
override fun getSource(): SourceElement = sourceElement
override fun isInner(): Boolean = false
override val annotations = Annotations.EMPTY // TODO file annotations
private val typeConstructor = ClassTypeConstructorImpl(this, annotations, true, emptyList(), listOf(builtIns.anyType))
private val defaultType = KotlinTypeFactory.simpleNotNullType(annotations, this, emptyList())
override fun getTypeConstructor(): TypeConstructor = typeConstructor
override fun getDefaultType(): SimpleType = defaultType
override fun getMemberScope(typeArguments: MutableList<out TypeProjection>): MemberScope =
MemberScope.Empty // TODO do we need a more useful MemberScope here?
override fun <R : Any?, D : Any?> accept(visitor: DeclarationDescriptorVisitor<R, D>, data: D): R {
return visitor.visitClassDescriptor(this, data)
}
override fun acceptVoid(visitor: DeclarationDescriptorVisitor<Void, Void>) {
visitor.visitClassDescriptor(this, null)
}
override fun toString(): String =
"IrFileClassDescriptor($fqNameUnsafe)"
}
@@ -0,0 +1,124 @@
/*
* 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.FunctionLoweringPass
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.descriptors.ValueDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrGetValue
import org.jetbrains.kotlin.ir.expressions.IrSetVariable
import org.jetbrains.kotlin.ir.expressions.IrValueAccessExpression
import org.jetbrains.kotlin.ir.visitors.*
import java.util.*
class SharedVariablesLowering(val context: JvmBackendContext) : FunctionLoweringPass {
override fun lower(irFunction: IrFunction) {
SharedVariablesTransformer(irFunction).lowerSharedVariables()
}
private inner class SharedVariablesTransformer(val irFunction: IrFunction) {
val sharedVariables = HashSet<ValueDescriptor>()
fun lowerSharedVariables() {
collectSharedVariables()
if (sharedVariables.isEmpty()) return
rewriteSharedVariables()
}
private fun collectSharedVariables() {
irFunction.acceptVoid(object : IrElementVisitorVoid {
val declarationsStack = ArrayDeque<IrDeclaration>()
val declaredVariables = HashSet<VariableDescriptor>()
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
override fun visitFunction(declaration: IrFunction) {
declarationsStack.push(declaration)
declaration.acceptChildrenVoid(this)
declarationsStack.pop()
}
override fun visitVariable(declaration: IrVariable) {
declaredVariables.add(declaration.descriptor)
}
override fun visitVariableAccess(expression: IrValueAccessExpression) {
expression.acceptChildrenVoid(this)
val descriptor = expression.descriptor
if (descriptor in declaredVariables && descriptor.containingDeclaration != declarationsStack.peek()) {
sharedVariables.add(descriptor)
}
}
})
}
private fun rewriteSharedVariables() {
val transformedDescriptors = HashMap<ValueDescriptor, VariableDescriptor>()
irFunction.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitVariable(declaration: IrVariable): IrStatement {
declaration.transformChildrenVoid(this)
val oldDescriptor = declaration.descriptor
if (oldDescriptor !in sharedVariables) return declaration
val newDescriptor = context.sharedVariablesManager.createSharedVariableDescriptor(oldDescriptor)
transformedDescriptors[oldDescriptor] = newDescriptor
return context.sharedVariablesManager.defineSharedValue(newDescriptor, declaration)
}
})
irFunction.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitGetValue(expression: IrGetValue): IrExpression {
expression.transformChildrenVoid(this)
val newDescriptor = getTransformedDescriptor(expression.descriptor) ?: return expression
return context.sharedVariablesManager.getSharedValue(newDescriptor, expression)
}
override fun visitSetVariable(expression: IrSetVariable): IrExpression {
expression.transformChildrenVoid(this)
val newDescriptor = getTransformedDescriptor(expression.descriptor) ?: return expression
return context.sharedVariablesManager.setSharedValue(newDescriptor, expression)
}
private fun getTransformedDescriptor(oldDescriptor: ValueDescriptor): VariableDescriptor? =
transformedDescriptors.getOrElse(oldDescriptor) {
assert(oldDescriptor !in sharedVariables) {
"Shared variable is not transformed: $oldDescriptor"
}
null
}
})
}
}
}
@@ -22,12 +22,10 @@ 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 BuiltinsOperatorsBuilder(val packageFragment: PackageFragmentDescriptor, val builtIns: KotlinBuiltIns) {
@@ -36,6 +34,7 @@ class BuiltinsOperatorsBuilder(val packageFragment: PackageFragmentDescriptor, v
val anyN = builtIns.nullableAnyType
val int = builtIns.intType
val nothing = builtIns.nothingType
val unit = builtIns.unitType
fun defineOperator(name: String, returnType: KotlinType, valueParameterTypes: List<KotlinType>): IrBuiltinOperatorDescriptor {
val operatorDescriptor = IrSimpleBuiltinOperatorDescriptorImpl(packageFragment, Name.identifier(name), returnType)
@@ -60,13 +59,15 @@ class IrBuiltIns(val builtIns: KotlinBuiltIns) {
val throwNpe: FunctionDescriptor = builder.run { defineOperator("THROW_NPE", nothing, listOf()) }
val booleanNot: FunctionDescriptor = builder.run { defineOperator("NOT", bool, listOf(bool)) }
val noWhenBranchMatchedException: FunctionDescriptor = builder.run { defineOperator("noWhenBranchMatchedException", unit, listOf()) }
val enumValueOf: FunctionDescriptor =
SimpleFunctionDescriptorImpl.create(
packageFragment,
Annotations.EMPTY,
Name.identifier("enumValueOf"),
CallableMemberDescriptor.Kind.SYNTHESIZED,
org.jetbrains.kotlin.descriptors.SourceElement.NO_SOURCE
SourceElement.NO_SOURCE
).apply {
val typeParameterT = TypeParameterDescriptorImpl.createWithDefaultBound(
this, Annotations.EMPTY, true, Variance.INVARIANT, Name.identifier("T"), 0
@@ -82,19 +83,6 @@ class IrBuiltIns(val builtIns: KotlinBuiltIns) {
initialize(null, null, listOf(typeParameterT), listOf(valueParameterName), returnType, Modality.FINAL, Visibilities.PUBLIC)
}
val noWhenBranchMatchedException: FunctionDescriptor =
SimpleFunctionDescriptorImpl.create(
packageFragment,
Annotations.EMPTY,
Name.identifier("noWhenBranchMatchedException"),
CallableMemberDescriptor.Kind.SYNTHESIZED,
org.jetbrains.kotlin.descriptors.SourceElement.NO_SOURCE
).apply {
val returnType = KotlinTypeFactory.simpleType(Annotations.EMPTY, builtIns.unit.typeConstructor, listOf(), false)
initialize(null, null, listOf(), listOf(), returnType, Modality.FINAL, Visibilities.PUBLIC)
}
companion object {
val KOTLIN_INTERNAL_IR_FQN = FqName("kotlin.internal.ir")
}
@@ -0,0 +1,9 @@
fun box(): String {
var result = ""
fun add(s: String) {
result += s
}
add("O")
add("K")
return result
}
@@ -0,0 +1,85 @@
fun testBoolean(v: Boolean): Boolean {
var value = false
fun setValue(v: Boolean) {
value = v
}
setValue(v)
return value
}
fun testChar(v: Char): Char {
var value = 0.toChar()
fun setValue(v: Char) {
value = v
}
setValue(v)
return value
}
fun testByte(v: Byte): Byte {
var value = 0.toByte()
fun setValue(v: Byte) {
value = v
}
setValue(v)
return value
}
fun testShort(v: Short): Short {
var value = 0.toShort()
fun setValue(v: Short) {
value = v
}
setValue(v)
return value
}
fun testInt(v: Int): Int {
var value = 0.toInt()
fun setValue(v: Int) {
value = v
}
setValue(v)
return value
}
fun testLong(v: Long): Long {
var value = 0.toLong()
fun setValue(v: Long) {
value = v
}
setValue(v)
return value
}
fun testFloat(v: Float): Float {
var value = 0.toFloat()
fun setValue(v: Float) {
value = v
}
setValue(v)
return value
}
fun testDouble(v: Double): Double {
var value = 0.toDouble()
fun setValue(v: Double) {
value = v
}
setValue(v)
return value
}
fun box(): String {
return when {
testBoolean(true) != true -> "testBoolean"
testChar('a') != 'a' -> "testChar"
testByte(1) != 1.toByte() -> "testByte"
testShort(1) != 1.toShort() -> "testShort"
testInt(1) != 1 -> "testInt"
testLong(1) != 1L -> "testLong"
testFloat(1.0F) != 1.0F -> "testFloat"
testDouble(1.0) != 1.0 -> "testDouble"
else -> "OK"
}
}
@@ -41,30 +41,6 @@ public class IrOnlyBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTest
doTest(fileName);
}
@TestMetadata("closureConversion1.kt")
public void testClosureConversion1() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/box/closureConversion1.kt");
doTest(fileName);
}
@TestMetadata("closureConversion2.kt")
public void testClosureConversion2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/box/closureConversion2.kt");
doTest(fileName);
}
@TestMetadata("closureConversion3.kt")
public void testClosureConversion3() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/box/closureConversion3.kt");
doTest(fileName);
}
@TestMetadata("closureConversion4.kt")
public void testClosureConversion4() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/box/closureConversion4.kt");
doTest(fileName);
}
@TestMetadata("enumClass.kt")
public void testEnumClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/box/enumClass.kt");
@@ -100,4 +76,49 @@ public class IrOnlyBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTest
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/box/simple.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/ir/box/closureConversion")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClosureConversion extends AbstractIrBlackBoxCodegenTest {
public void testAllFilesPresentInClosureConversion() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/ir/box/closureConversion"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("closureConversion1.kt")
public void testClosureConversion1() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/box/closureConversion/closureConversion1.kt");
doTest(fileName);
}
@TestMetadata("closureConversion2.kt")
public void testClosureConversion2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/box/closureConversion/closureConversion2.kt");
doTest(fileName);
}
@TestMetadata("closureConversion3.kt")
public void testClosureConversion3() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/box/closureConversion/closureConversion3.kt");
doTest(fileName);
}
@TestMetadata("closureConversion4.kt")
public void testClosureConversion4() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/box/closureConversion/closureConversion4.kt");
doTest(fileName);
}
@TestMetadata("mutable1.kt")
public void testMutable1() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/box/closureConversion/mutable1.kt");
doTest(fileName);
}
@TestMetadata("mutablePrimitives.kt")
public void testMutablePrimitives() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/box/closureConversion/mutablePrimitives.kt");
doTest(fileName);
}
}
}