Fix secondary constructor lowering

This commit is contained in:
Roman Artemev
2018-04-23 21:05:20 +03:00
parent 8721990a7f
commit 8bc80a9829
25 changed files with 129 additions and 236 deletions
@@ -8,10 +8,11 @@ package org.jetbrains.kotlin.backend.common.descriptors
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
interface DescriptorsFactory {
fun getFieldDescriptorForEnumEntry(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor
fun getOuterThisFieldDescriptor(classDescriptor: ClassDescriptor): PropertyDescriptor
fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: ClassConstructorDescriptor): ClassConstructorDescriptor
fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: ClassConstructorDescriptor): IrConstructorSymbol
fun getFieldDescriptorForObjectInstance(objectDescriptor: ClassDescriptor): PropertyDescriptor
}
@@ -5,8 +5,7 @@
package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrStatement
@@ -73,11 +72,11 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass {
val startOffset = irConstructor.startOffset
val endOffset = irConstructor.endOffset
val newDescriptor = context.descriptorsFactory.getInnerClassConstructorWithOuterThisParameter(oldDescriptor)
val outerThisValueParameter = newDescriptor.valueParameters[0]
val newSymbol = context.descriptorsFactory.getInnerClassConstructorWithOuterThisParameter(oldDescriptor)
val outerThisValueParameter = newSymbol.descriptor.valueParameters[0]
oldDescriptor.valueParameters.forEach { oldValueParameter ->
oldConstructorParameterToNew[oldValueParameter] = newDescriptor.valueParameters[oldValueParameter.index + 1]
oldConstructorParameterToNew[oldValueParameter] = newSymbol.descriptor.valueParameters[oldValueParameter.index + 1]
}
val blockBody = irConstructor.body as? IrBlockBody ?: throw AssertionError("Unexpected constructor body: ${irConstructor.body}")
@@ -105,12 +104,12 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass {
}
return IrConstructorImpl(
startOffset, endOffset,
irConstructor.origin, // TODO special origin for lowered inner class constructors?
newDescriptor,
blockBody
startOffset, endOffset,
irConstructor.origin, // TODO special origin for lowered inner class constructors?
newSymbol,
blockBody
).apply {
newDescriptor.valueParameters.forEachIndexed { i, desc ->
newSymbol.descriptor.valueParameters.forEachIndexed { i, desc ->
val valueParameter = if (i == 0) {
IrValueParameterImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, FIELD_FOR_OUTER_THIS, desc, null)
} else {
@@ -159,7 +158,7 @@ class InnerClassesLowering(val context: BackendContext) : ClassLoweringPass {
val outerThisField = context.descriptorsFactory.getOuterThisFieldDescriptor(innerClass)
irThis = IrGetFieldImpl(startOffset, endOffset, outerThisField, irThis, origin)
val outer = classDescriptor.containingDeclaration
val outer = innerClass.containingDeclaration
innerClass = outer as? ClassDescriptor ?:
throw AssertionError("Unexpected containing declaration for inner class $innerClass: $outer")
}
@@ -193,13 +192,13 @@ class InnerClassConstructorCallsLowering(val context: BackendContext) : BodyLowe
val newCallee = context.descriptorsFactory.getInnerClassConstructorWithOuterThisParameter(callee)
val newCall = IrCallImpl(
expression.startOffset, expression.endOffset, newCallee,
expression.startOffset, expression.endOffset, newCallee, newCallee.descriptor,
null, // TODO type arguments map
expression.origin
)
newCall.putValueArgument(0, dispatchReceiver)
for (i in 1 .. newCallee.valueParameters.lastIndex) {
for (i in 1 .. newCallee.descriptor.valueParameters.lastIndex) {
newCall.putValueArgument(i, expression.getValueArgument(i - 1))
}
@@ -215,12 +214,12 @@ class InnerClassConstructorCallsLowering(val context: BackendContext) : BodyLowe
val newCallee = context.descriptorsFactory.getInnerClassConstructorWithOuterThisParameter(callee)
val newCall = IrDelegatingConstructorCallImpl(
expression.startOffset, expression.endOffset, newCallee,
expression.startOffset, expression.endOffset, newCallee, newCallee.descriptor,
null // TODO type arguments map
)
newCall.putValueArgument(0, dispatchReceiver)
for (i in 1 .. newCallee.valueParameters.lastIndex) {
for (i in 1 .. newCallee.descriptor.valueParameters.lastIndex) {
newCall.putValueArgument(i, expression.getValueArgument(i - 1))
}
@@ -235,6 +235,8 @@ val IrClass.defaultType: KotlinType
val IrSimpleFunction.isReal: Boolean get() = descriptor.kind.isReal
// This implementation is from kotlin-native
// TODO: use this implementation instead of any other
fun IrSimpleFunction.resolveFakeOverride(): IrSimpleFunction? {
if (isReal) return this
@@ -264,7 +266,7 @@ fun IrSimpleFunction.resolveFakeOverride(): IrSimpleFunction? {
}
visited.clear()
realOverrides.asSequence().forEach { excludeRepeated(it) }
realOverrides.toList().forEach { excludeRepeated(it) }
return realOverrides.singleOrNull { it.modality != Modality.ABSTRACT }
}
@@ -24,21 +24,20 @@ 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.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorUtils
import java.util.*
class JsSpecialDescriptorsFactory(
class JsDescriptorsFactory(
private val builtIns: KotlinBuiltIns
) : DescriptorsFactory {
private val singletonFieldDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>()
private val outerThisDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>()
private val innerClassConstructors = HashMap<ClassConstructorDescriptor, ClassConstructorDescriptor>()
private val innerClassConstructors = HashMap<ClassConstructorDescriptor, IrConstructorSymbol>()
override fun getFieldDescriptorForEnumEntry(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor = TODO()
// singletonFieldDescriptors.getOrPut(enumEntryDescriptor) {
// createEnumEntryFieldDescriptor(enumEntryDescriptor)
// }
override fun getOuterThisFieldDescriptor(innerClassDescriptor: ClassDescriptor): PropertyDescriptor =
if (!innerClassDescriptor.isInner) throw AssertionError("Class is not inner: $innerClassDescriptor")
@@ -46,10 +45,6 @@ class JsSpecialDescriptorsFactory(
val outerClassDescriptor = DescriptorUtils.getContainingClass(innerClassDescriptor)
?: throw AssertionError("No containing class for inner class $innerClassDescriptor")
// PropertyDescriptorImpl.create(innerClassDescriptor, Annotations.EMPTY. Mo
// Name.identifier("this$0"), outerClassDescriptor.defaultType, innerClassDescriptor,
// Annotations.EMPTY, JavaVisibilities.PACKAGE_VISIBILITY, Opcodes.ACC_SYNTHETIC, SourceElement.NO_SOURCE
// )
PropertyDescriptorImpl.create(
innerClassDescriptor,
Annotations.EMPTY,
@@ -76,7 +71,7 @@ class JsSpecialDescriptorsFactory(
}
}
override fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: ClassConstructorDescriptor): ClassConstructorDescriptor {
override fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: ClassConstructorDescriptor): IrConstructorSymbol {
val innerClass = innerClassConstructor.containingDeclaration
assert(innerClass.isInner) { "Class is not inner: $innerClass" }
@@ -85,7 +80,7 @@ class JsSpecialDescriptorsFactory(
}
}
private fun createInnerClassConstructorWithOuterThisParameter(oldDescriptor: ClassConstructorDescriptor): ClassConstructorDescriptor {
private fun createInnerClassConstructorWithOuterThisParameter(oldDescriptor: ClassConstructorDescriptor): IrConstructorSymbol {
val classDescriptor = oldDescriptor.containingDeclaration
val outerThisType = (classDescriptor.containingDeclaration as ClassDescriptor).defaultType
@@ -93,7 +88,6 @@ class JsSpecialDescriptorsFactory(
classDescriptor, oldDescriptor.annotations, oldDescriptor.isPrimary, oldDescriptor.source
)
// val outerThisValueParameter = newDescriptor.createValueParameter(0, "\$outer", outerThisType)
val outerThisValueParameter = ValueParameterDescriptorImpl(
newDescriptor,
null,
@@ -113,28 +107,9 @@ class JsSpecialDescriptorsFactory(
oldDescriptor.valueParameters.map { it.copy(newDescriptor, it.name, it.index + 1) }
newDescriptor.initialize(newValueParameters, oldDescriptor.visibility)
newDescriptor.returnType = oldDescriptor.returnType
return newDescriptor
return IrConstructorSymbolImpl(newDescriptor)
}
// 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.createStaticVal(
// enumEntryDescriptor.name,
// enumClassDescriptor.defaultType,
// enumClassDescriptor,
// enumEntryDescriptor.annotations,
// Modality.FINAL,
// Visibilities.PUBLIC,
// Opcodes.ACC_ENUM,
// enumEntryDescriptor.source
// )
// }
override fun getFieldDescriptorForObjectInstance(objectDescriptor: ClassDescriptor): PropertyDescriptor =
singletonFieldDescriptors.getOrPut(objectDescriptor) {
createObjectInstanceFieldDescriptor(objectDescriptor)
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.backend.common.ReflectionTypes
import org.jetbrains.kotlin.backend.common.descriptors.KnownPackageFragmentDescriptor
import org.jetbrains.kotlin.backend.common.ir.Ir
import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.backend.js.JsSpecialDescriptorsFactory
import org.jetbrains.kotlin.backend.js.JsDescriptorsFactory
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
@@ -40,7 +40,7 @@ class JsIrBackendContext(
override val builtIns = module.builtIns
override val sharedVariablesManager =
JsSharedVariablesManager(builtIns, KnownPackageFragmentDescriptor(builtIns.builtInsModule, FqName("kotlin.js.internal")))
override val descriptorsFactory = JsSpecialDescriptorsFactory(builtIns)
override val descriptorsFactory = JsDescriptorsFactory(builtIns)
override val reflectionTypes: ReflectionTypes by lazy(LazyThreadSafetyMode.PUBLICATION) {
// TODO
@@ -10,24 +10,33 @@ import org.jetbrains.kotlin.backend.common.descriptors.SharedVariablesManager
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.*
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.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
import org.jetbrains.kotlin.ir.expressions.*
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.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.symbols.impl.*
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.KotlinTypeFactory
import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.Variance
class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPackage: PackageFragmentDescriptor) : SharedVariablesManager {
override fun createSharedVariableDescriptor(variableDescriptor: VariableDescriptor): VariableDescriptor =
LocalVariableDescriptor(
variableDescriptor.containingDeclaration, Annotations.EMPTY, variableDescriptor.name,
variableDescriptor.containingDeclaration, variableDescriptor.annotations, variableDescriptor.name,
getSharedVariableType(variableDescriptor.type),
false, false, variableDescriptor.isLateInit, variableDescriptor.source
)
@@ -35,7 +44,7 @@ class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPack
override fun defineSharedValue(sharedVariableDescriptor: VariableDescriptor, originalDeclaration: IrVariable): IrStatement {
val valueType = originalDeclaration.descriptor.type
val boxConstructor = closureBoxConstructorTypeDescriptor
val boxConstructorSymbol = closureBoxConstrctorTypeSymbol
val boxConstructorSymbol = closureBoxConstructorTypeSymbol
val constructorTypeParam = closureBoxConstructorTypeDescriptor.typeParameters[0]
val boxConstructorTypeArgument = mapOf(constructorTypeParam to valueType)
val initializer = originalDeclaration.initializer ?: IrConstImpl.constNull(
@@ -93,8 +102,7 @@ class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPack
private val closureBoxConstructorTypeDescriptor = createClosureBoxClassConstructor()
private val closureBoxFieldDescriptor = createClosureBoxField()
private val closureBoxTypeSymbol = IrClassSymbolImpl(closureBoxTypeDescriptor)
val closureBoxConstrctorTypeSymbol = createFunctionSymbol(closureBoxConstructorTypeDescriptor)
val closureBoxConstructorTypeSymbol = createFunctionSymbol(closureBoxConstructorTypeDescriptor)
private val closureBoxFieldSymbol = IrFieldSymbolImpl(closureBoxFieldDescriptor)
@@ -112,13 +120,7 @@ class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPack
true,
SourceElement.NO_SOURCE
).apply {
/// constructor<T>(v: T) : T
val typeParameter = constructedClass.declaredTypeParameters[0]
// val typeParameter = typeParameters[0]
val typeParameterType = KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
Annotations.EMPTY,
typeParameter.typeConstructor,
@@ -180,18 +182,6 @@ class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPack
return desc
}
private fun getSubstitutedRefConstructor(valueType: KotlinType): ClassConstructorDescriptor =
closureBoxConstructorTypeDescriptor.substitute(
TypeSubstitutor.create(
closureBoxConstructorTypeDescriptor.typeParameters.associate {
it.typeConstructor to TypeProjectionImpl(
Variance.INVARIANT,
valueType
)
}
)
)!!
private fun getRefType(valueType: KotlinType) =
KotlinTypeFactory.simpleNotNullType(
Annotations.EMPTY,
@@ -62,7 +62,7 @@ fun JsIrBackendContext.lower(file: IrFile) {
InnerClassConstructorCallsLowering(this).runOnFilePostfix(file)
PropertiesLowering().lower(file)
InitializersLowering(this, JsLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER, false).runOnFilePostfix(file)
SecondaryCtorLowering(this).lower(file)
SecondaryCtorLowering(this).runOnFilePostfix(file)
IntrinsicifyCallsLowering(this).lower(file)
FunctionReferenceLowering(this).lower(file)
}
@@ -5,18 +5,17 @@
package org.jetbrains.kotlin.ir.backend.js.descriptors
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.*
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType
@@ -89,10 +88,10 @@ object JsSymbolBuilder {
}
fun <T : TypeParameterDescriptor> IrSimpleFunctionSymbol.initialize(
fun IrSimpleFunctionSymbol.initialize(
receiverParameterType: KotlinType? = null,
dispatchParameterDescriptor: ReceiverParameterDescriptor? = null,
typeParameters: List<T> = emptyList(),
typeParameters: List<TypeParameterDescriptor> = emptyList(),
valueParameters: List<ValueParameterDescriptor> = emptyList(),
type: KotlinType? = null,
modality: Modality = Modality.FINAL,
@@ -5,19 +5,17 @@
package org.jetbrains.kotlin.ir.backend.js.ir
import org.jetbrains.kotlin.backend.common.ir.Ir
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOriginImpl
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.types.KotlinType
object JsIrBuilder {
@@ -46,7 +44,6 @@ object JsIrBuilder {
fun buildGetValue(symbol: IrValueSymbol) = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol, SYNTHESIZED_STATEMENT)
fun buildBlockBody() = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET)
fun buildBlockBody(stmts: List<IrStatement>) = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, stmts)
fun buildFunctionReference(type: KotlinType, symbol: IrFunctionSymbol) =
@@ -15,16 +15,16 @@ import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.descriptors.JsSymbolBuilder
import org.jetbrains.kotlin.ir.backend.js.descriptors.initialize
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
import org.jetbrains.kotlin.ir.expressions.copyTypeArgumentsFrom
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.util.transformFlat
import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.types.KotlinType
@@ -32,8 +32,8 @@ import org.jetbrains.kotlin.types.KotlinType
// TODO replace with DeclarationContainerLowerPass && do flatTransform
class FunctionReferenceLowering(val context: JsIrBackendContext) : FileLoweringPass, DeclarationContainerLoweringPass {
val lambdas = mutableMapOf<IrDeclaration, KotlinType>()
val oldToNewDeclarationMap = mutableMapOf<IrSymbolOwner, IrFunction>()
private val lambdas = mutableMapOf<IrDeclaration, KotlinType>()
private val oldToNewDeclarationMap = mutableMapOf<IrFunctionSymbol, IrFunction>()
override fun lower(irFile: IrFile) {
irFile.acceptVoid(FunctionReferenceCollector())
@@ -42,7 +42,6 @@ class FunctionReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
}
inner class FunctionReferenceCollector : IrElementVisitorVoid {
override fun visitFunctionReference(expression: IrFunctionReference) {
lambdas[expression.symbol.owner as IrFunction] = expression.type
}
@@ -50,7 +49,6 @@ class FunctionReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
}
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
@@ -66,9 +64,9 @@ class FunctionReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
inner class FunctionReferenceVisitor : IrElementTransformerVoid() {
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
val newTarget = oldToNewDeclarationMap[expression.symbol.owner]
val newTarget = oldToNewDeclarationMap[expression.symbol]
return if (newTarget != null) IrCallImpl(expression.startOffset, expression.endOffset, newTarget.symbol).apply {
return if (newTarget != null) IrCallImpl(expression.startOffset, expression.endOffset, newTarget.symbol, expression.origin).apply {
copyTypeArgumentsFrom(expression)
var index = 0
for (i in 0 until expression.valueArgumentsCount) {
@@ -82,15 +80,17 @@ class FunctionReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
}
private fun lowerKFunctionReference(declaration: IrFunction, functionType: KotlinType): List<IrFunction> {
// TODO: property reference
// transform
// x = Foo::bar ->
// x = Foo_bar_referenceGet(c1: closure$C1, c2: closure$C2) {
// return function Foo_bar_closure(p0: Foo, p1: T2, p2: T3) {
// return p0.foo(c1, c2, p1, p2)
// x = Foo_bar_KreferenceGet(c1: closure$C1, c2: closure$C2) : KFunctionN<Foo, T2, ..., TN, TReturn> {
// return fun Foo_bar_KreferenceClosure(p0: Foo, p1: T2, p2: T3): TReturn {
// return p0.bar(c1, c2, p1, p2)
// }
// }
// KFunctionN<T1, T2, ..., TN, TReturn>, arguments.size = N + 1
// KFunctionN<Foo, T2, ..., TN, TReturn>, arguments.size = N + 1
val closureParams = functionType.arguments.dropLast(1) // drop return type
var kFunctionValueParamsCount = closureParams.size
@@ -99,7 +99,8 @@ class FunctionReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
assert(kFunctionValueParamsCount >= 0)
val getterValueParameters = declaration.valueParameters.drop(kFunctionValueParamsCount)
// The `getter` function takes only parameters which have to be closured
val getterValueParameters = declaration.valueParameters.dropLast(kFunctionValueParamsCount)
val getterName = "${declaration.descriptor.name}_KreferenceGet"
val refGetSymbol =
@@ -117,10 +118,11 @@ class FunctionReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
}
val closureName = "${declaration.descriptor.name}_KreferenceClosure"
val refClosureSymbol = JsSymbolBuilder.buildSimpleFunction(declaration.descriptor.containingDeclaration, closureName)
val refClosureSymbol = JsSymbolBuilder.buildSimpleFunction(refGetSymbol.descriptor, closureName)
// the params which are passed to closure
val closureParamSymbols = closureParams.mapIndexed { index, p ->
// TODO: re-use original parameter names
JsSymbolBuilder.buildValueParameter(refClosureSymbol, index, p.type)
}
@@ -161,7 +163,7 @@ class FunctionReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
body = JsIrBuilder.buildBlockBody(listOf(irGetterReturn))
}
oldToNewDeclarationMap[declaration] = refGetFunction
oldToNewDeclarationMap[declaration.symbol] = refGetFunction
return listOf(declaration, refGetFunction)
}
@@ -118,6 +118,7 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL
return irCall(call, it.symbol)
}
// TODO: get rid of unbound symbols
if (symbol.isBound) {
(symbol.owner as? IrFunction)?.dispatchReceiverParameter?.let {
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.impl.LazyClassReceiverParameterDescriptor
import org.jetbrains.kotlin.ir.IrElement
@@ -32,23 +32,18 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransformerVoid(), FileLoweringPass {
class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransformerVoid(), DeclarationContainerLoweringPass {
private val oldCtorToNewMap = mutableMapOf<IrConstructorSymbol, JsIrBackendContext.SecondaryCtorPair>()
override fun lower(irFile: IrFile) {
irFile.accept(this, null)
context.secondaryConstructorsMap.putAll(oldCtorToNewMap)
}
override fun visitFile(irFile: IrFile): IrFile {
irFile.declarations.transformFlat { declaration ->
if (declaration is IrClass) {
listOf(declaration) + lowerClass(declaration)
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
irDeclarationContainer.declarations.transformFlat {
if (it is IrClass) {
listOf(it) + lowerClass(it)
} else null
}
return irFile
context.secondaryConstructorsMap.putAll(oldCtorToNewMap)
}
private fun lowerClass(irClass: IrClass): List<IrSimpleFunction> {
@@ -142,7 +137,7 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
valueParameters += (declaration.valueParameters + thisParam)
typeParameters += declaration.typeParameters
parent = declaration.parent
// parent = declaration.parent
body = JsIrBuilder.buildBlockBody(statements + retStmt).apply {
transformChildrenVoid(ThisUsageReplaceTransformer(it, thisSymbol))
}
@@ -169,7 +164,7 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
valueParameters += ctorOrig.valueParameters
typeParameters += ctorOrig.typeParameters
parent = ctorOrig.parent
// parent = ctorOrig.parent
val returnType = ctorOrig.returnType
val createFunctionIntrinsic = context.intrinsics.jsObjectCreate
@@ -200,6 +195,9 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
override fun visitFunction(declaration: IrFunction, data: IrFunction?): IrStatement = super.visitFunction(declaration, declaration)
override fun visitCall(expression: IrCall, ownerFunc: IrFunction?): IrElement {
super.visitCall(expression, ownerFunc)
// TODO: figure out the reason why symbol is not bound
if (expression.symbol.isBound) {
val target = expression.symbol.owner as IrFunction
@@ -219,14 +217,16 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
}
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, ownerFunc: IrFunction?): IrElement {
val target = expression.symbol.owner
if (target.symbol.isPrimary) {
super.visitDelegatingConstructorCall(expression, ownerFunc)
val target = expression.symbol
if (target.isPrimary) {
// nothing to do here
return expression
}
val fromPrimary = ownerFunc!! is IrConstructor
val newCall = redirectCall(expression, context.secondaryConstructorsMap[target.symbol]!!.delegate)
val newCall = redirectCall(expression, context.secondaryConstructorsMap[target]!!.delegate)
val readThis = if (fromPrimary) {
IrGetValueImpl(
@@ -28,11 +28,6 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
if (left != neutralExpression) JsBinaryOperation(JsBinaryOperator.COMMA, left, right) else right
}
override fun visitBlock(expression: IrBlock, data: JsGenerationContext): JsExpression = visitContainerExpression(expression, data)
override fun visitComposite(expression: IrComposite, data: JsGenerationContext): JsExpression =
visitContainerExpression(expression, data)
override fun visitExpressionBody(body: IrExpressionBody, context: JsGenerationContext): JsExpression =
body.expression.accept(this, context)
@@ -78,6 +73,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
override fun visitGetObjectValue(expression: IrGetObjectValue, context: JsGenerationContext) = when (expression.symbol.kind) {
ClassKind.OBJECT -> {
// TODO:
if (expression.type.isUnit()) JsNullLiteral()
else {
val className = context.getNameForSymbol(expression.symbol)
@@ -133,7 +129,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
val targetName = context.getNameForSymbol(symbol)
val qPrototype = JsNameRef(targetName, prototypeOf(qualifierName))
val callRef = JsNameRef(Namer.CALL_FUNCTION, qPrototype)
return JsInvocation(callRef, jsDispatchReceiver?. let { listOf(it) + arguments } ?: arguments)
return JsInvocation(callRef, jsDispatchReceiver?.let { listOf(it) + arguments } ?: arguments)
}
return if (symbol is IrConstructorSymbol) {
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.js.backend.ast.JsStatement
class IrFileToJsTransformer : BaseIrElementToJsNodeTransformer<JsStatement, JsGenerationContext> {
override fun visitFile(declaration: IrFile, context: JsGenerationContext): JsStatement {
val fileContext = context.newDeclaration(JsDeclarationScope(context.currentScope, "scope for file ${declaration.name}"), null, declaration)
val fileContext = context.newDeclaration(JsDeclarationScope(context.currentScope, "scope for file ${declaration.name}"))
val block = fileContext.currentBlock
declaration.declarations.forEach {
@@ -127,9 +127,8 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
return emptyList()
}
val baseName = context.getNameForSymbol(baseClass.owner.symbol)
val createCall = jsAssignment(
classPrototypeRef, JsInvocation(Namer.JS_OBJECT_CREATE_FUNCTION, prototypeOf(baseName.makeRef()))
classPrototypeRef, JsInvocation(Namer.JS_OBJECT_CREATE_FUNCTION, prototypeOf(baseClassName!!.makeRef()))
).makeStmt()
val ctorAssign = jsAssignment(JsNameRef(Namer.CONSTRUCTOR_NAME, classPrototypeRef), classNameRef).makeStmt()
@@ -74,8 +74,7 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
val args = translateCallArguments(call, context)
val initializer = args[0]
val propertyInit = JsPropertyInitializer(JsNameRef("v"), initializer)
val objectLiteral = JsObjectLiteral()
objectLiteral.apply { propertyInitializers += propertyInit }
JsObjectLiteral(listOf(propertyInit))
}
addIfNotNull(intrinsics.jsCode) { call, context ->
@@ -5,21 +5,18 @@
package org.jetbrains.kotlin.ir.backend.js.utils
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.js.backend.ast.*
class JsGenerationContext {
fun newDeclaration(scope: JsScope, func: IrFunction? = null, file: IrFile? = null): JsGenerationContext {
return JsGenerationContext(this, JsBlock(), scope, func, file)
fun newDeclaration(scope: JsScope, func: IrFunction? = null): JsGenerationContext {
return JsGenerationContext(this, JsBlock(), scope, func)
}
val currentBlock: JsBlock
val currentScope: JsScope
val currentFile: IrFile?
val currentFunction: IrFunction?
val parent: JsGenerationContext?
val staticContext: JsStaticContext
@@ -33,21 +30,16 @@ class JsGenerationContext {
this.currentScope = rootScope
this.currentBlock = program.globalBlock
this.currentFunction = null
this.currentFile = null
}
constructor(parent: JsGenerationContext, block: JsBlock, scope: JsScope, func: IrFunction?, file: IrFile? = null) {
constructor(parent: JsGenerationContext, block: JsBlock, scope: JsScope, func: IrFunction?) {
this.parent = parent
this.program = parent.program
this.staticContext = parent.staticContext
this.currentBlock = block
this.currentScope = scope
this.currentFunction = func
this.currentFile = file ?: parent.currentFile
}
fun getNameForSymbol(symbol: IrSymbol): JsName = staticContext.getNameForSymbol(symbol, this)
val currentPackage: PackageFragmentDescriptor
get() = currentFile!!.packageFragmentDescriptor
}
@@ -21,6 +21,7 @@ class JsStaticContext(
backendContext: JsIrBackendContext
) {
val intrinsics = JsIntrinsicTransformers(backendContext)
// TODO: use IrSymbol instead of JsName
val classModels = mutableMapOf<JsName, JsClassModel>()
fun getNameForSymbol(irSymbol: IrSymbol, context: JsGenerationContext) = nameGenerator.getNameForSymbol(irSymbol, context)
@@ -20,8 +20,8 @@ import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.ReflectionTypes
import org.jetbrains.kotlin.backend.common.ir.Ir
import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmDescriptorsFactory
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmSharedVariablesManager
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmSpecialDescriptorsFactory
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
@@ -45,7 +45,7 @@ class JvmBackendContext(
irModuleFragment: IrModuleFragment, symbolTable: SymbolTable
) : CommonBackendContext {
override val builtIns = state.module.builtIns
override val descriptorsFactory: JvmSpecialDescriptorsFactory = JvmSpecialDescriptorsFactory(psiSourceManager, builtIns)
override val descriptorsFactory: JvmDescriptorsFactory = JvmDescriptorsFactory(psiSourceManager, builtIns)
override val sharedVariablesManager = JvmSharedVariablesManager(builtIns)
override val reflectionTypes: ReflectionTypes by lazy(LazyThreadSafetyMode.PUBLICATION) {
@@ -26,6 +26,8 @@ import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
import org.jetbrains.kotlin.ir.SourceManager
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
@@ -34,13 +36,13 @@ import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
import org.jetbrains.org.objectweb.asm.Opcodes
import java.util.*
class JvmSpecialDescriptorsFactory(
class JvmDescriptorsFactory(
private val psiSourceManager: PsiSourceManager,
private val builtIns: KotlinBuiltIns
) : DescriptorsFactory {
private val singletonFieldDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>()
private val outerThisDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>()
private val innerClassConstructors = HashMap<ClassConstructorDescriptor, ClassConstructorDescriptor>()
private val innerClassConstructors = HashMap<ClassConstructorDescriptor, IrConstructorSymbol>()
override fun getFieldDescriptorForEnumEntry(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor =
singletonFieldDescriptors.getOrPut(enumEntryDescriptor) {
@@ -72,7 +74,7 @@ class JvmSpecialDescriptorsFactory(
)
}
override fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: ClassConstructorDescriptor): ClassConstructorDescriptor {
override fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: ClassConstructorDescriptor): IrConstructorSymbol {
val innerClass = innerClassConstructor.containingDeclaration
assert(innerClass.isInner) { "Class is not inner: $innerClass" }
@@ -81,7 +83,7 @@ class JvmSpecialDescriptorsFactory(
}
}
private fun createInnerClassConstructorWithOuterThisParameter(oldDescriptor: ClassConstructorDescriptor): ClassConstructorDescriptor {
private fun createInnerClassConstructorWithOuterThisParameter(oldDescriptor: ClassConstructorDescriptor): IrConstructorSymbol {
val classDescriptor = oldDescriptor.containingDeclaration
val outerThisType = (classDescriptor.containingDeclaration as ClassDescriptor).defaultType
@@ -96,7 +98,7 @@ class JvmSpecialDescriptorsFactory(
oldDescriptor.valueParameters.map { it.copy(newDescriptor, it.name, it.index + 1) }
newDescriptor.initialize(newValueParameters, oldDescriptor.visibility)
newDescriptor.returnType = oldDescriptor.returnType
return newDescriptor
return IrConstructorSymbolImpl(newDescriptor)
}
@@ -18,9 +18,10 @@ package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.lower.DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER
import org.jetbrains.kotlin.backend.common.lower.InitializersLowering.Companion.clinitName
import org.jetbrains.kotlin.backend.common.lower.VariableRemapper
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.descriptors.DefaultImplsClassDescriptorImpl
import org.jetbrains.kotlin.backend.common.lower.InitializersLowering.Companion.clinitName
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
@@ -1,39 +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.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ValueDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrGetValue
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
abstract class AbstractVariableRemapper : IrElementTransformerVoid() {
protected abstract fun remapVariable(value: ValueDescriptor): ValueDescriptor?
override fun visitGetValue(expression: IrGetValue): IrExpression =
remapVariable(expression.descriptor)?.let {
IrGetValueImpl(expression.startOffset, expression.endOffset, it, expression.origin)
} ?: expression
}
class VariableRemapper(val mapping: Map<ValueDescriptor, ValueDescriptor>): AbstractVariableRemapper() {
override fun remapVariable(value: ValueDescriptor): ValueDescriptor? =
mapping[value]
}
@@ -42,13 +42,16 @@ class IrConstructorImpl(
startOffset: Int,
endOffset: Int,
origin: IrDeclarationOrigin,
symbol: IrConstructorSymbol
symbol: IrConstructorSymbol,
body: IrBody? = null
) : this(
startOffset, endOffset, origin, symbol,
symbol.descriptor.visibility,
symbol.descriptor.returnType,
symbol.descriptor.isInline
)
) {
this.body = body
}
constructor(
startOffset: Int,
@@ -57,6 +60,7 @@ class IrConstructorImpl(
descriptor: ClassConstructorDescriptor
) : this(startOffset, endOffset, origin, IrConstructorSymbolImpl(descriptor))
@Deprecated("Let use constructor which takes symbol instead of descriptor")
constructor(
startOffset: Int,
endOffset: Int,
@@ -141,8 +141,8 @@ class IrCallImpl(
copyTypeArgumentsFrom(typeArguments)
}
constructor(startOffset: Int, endOffset: Int, symbol: IrFunctionSymbol) :
this(startOffset, endOffset, symbol, symbol.descriptor)
constructor(startOffset: Int, endOffset: Int, symbol: IrFunctionSymbol, origin: IrStatementOrigin? = null) :
this(startOffset, endOffset, symbol, symbol.descriptor, origin = origin)
override val superQualifier: ClassDescriptor? = superQualifierSymbol?.descriptor
@@ -2,42 +2,14 @@
import kotlin.test.assertEquals
fun run(r: () -> Any) = r()
fun test(i: Int, j: Int, k: Int): String {
var i = 0
var j = 2
val k = 4
fun f(): String = "OK"
val funVal = {
println(k)
}
run(funVal)
val funLit = { i += 1
j += k
f() }
val ret = run(funLit) as String
if (i != 1 || j != 6 || k != 4) return "fail"
return ret
}
inline fun foo(x: String, block: (String) -> String) = block(x)
fun box(): String {
return test(1, 2, 3)
}
fun bar(y: String) = y + "cde"
//fun box(): String {
//// fun bar(y: String) = y + "cde"
//
//// val res = foo("abc") { bar(it) }
//
//// assertEquals("abccde", res)
//
// return "OK"
//}
val res = foo("abc") { bar(it) }
assertEquals("abccde", res)
return "OK"
}