Minor. Reformat

This commit is contained in:
Mikhael Bogdanov
2018-05-04 13:21:00 +02:00
parent e82170a04e
commit fdbc863e60
11 changed files with 620 additions and 496 deletions
@@ -24,25 +24,25 @@ import org.jetbrains.kotlin.serialization.deserialization.descriptors.Deserializ
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
fun ClassDescriptor?.getter2Descriptor(methodName: Name) = this?.let { fun ClassDescriptor?.getter2Descriptor(methodName: Name) = this?.let {
this.unsubstitutedMemberScope.getContributedDescriptors{true} this.unsubstitutedMemberScope.getContributedDescriptors { true }
.firstOrNull { .firstOrNull {
it.name == methodName it.name == methodName
} ?.let { }?.let {
return@let (it as? PropertyDescriptor)?.getter return@let (it as? PropertyDescriptor)?.getter
} }
} }
fun ClassDescriptor?.signature2Descriptor(methodName: Name, signature:Array<KotlinType> = emptyArray()) = this?.let { fun ClassDescriptor?.signature2Descriptor(methodName: Name, signature: Array<KotlinType> = emptyArray()) = this?.let {
this this
.unsubstitutedMemberScope .unsubstitutedMemberScope
.getContributedFunctions(methodName, NoLookupLocation.FROM_BACKEND) .getContributedFunctions(methodName, NoLookupLocation.FROM_BACKEND)
.firstOrNull { .firstOrNull {
return@firstOrNull it.valueParameters.size == signature.size return@firstOrNull it.valueParameters.size == signature.size
&& (signature.isEmpty() || it.valueParameters.any { && (signature.isEmpty() || it.valueParameters.any { p ->
p -> val index = it.valueParameters.indexOf(p) val index = it.valueParameters.indexOf(p)
return@any p.type == signature[index] return@any p.type == signature[index]
}) })
} }
} }
val String.synthesizedName get() = Name.identifier(this.synthesizedString) val String.synthesizedName get() = Name.identifier(this.synthesizedString)
@@ -51,13 +51,13 @@ val String.synthesizedString get() = "\$$this"
val DeclarationDescriptor.propertyIfAccessor val DeclarationDescriptor.propertyIfAccessor
get() = if (this is PropertyAccessorDescriptor) get() = if (this is PropertyAccessorDescriptor)
this.correspondingProperty this.correspondingProperty
else this else this
val CallableMemberDescriptor.propertyIfAccessor val CallableMemberDescriptor.propertyIfAccessor
get() = if (this is PropertyAccessorDescriptor) get() = if (this is PropertyAccessorDescriptor)
this.correspondingProperty this.correspondingProperty
else this else this
val FunctionDescriptor.deserializedPropertyIfAccessor: DeserializedCallableMemberDescriptor val FunctionDescriptor.deserializedPropertyIfAccessor: DeserializedCallableMemberDescriptor
get() { get() {
@@ -54,11 +54,12 @@ fun DeclarationDescriptor.createFakeOverrideDescriptor(owner: ClassDescriptor):
return when (this) { return when (this) {
is CallableMemberDescriptor -> is CallableMemberDescriptor ->
copy( copy(
/* newOwner = */ owner, /* newOwner = */ owner,
/* modality = */ modality, /* modality = */ modality,
/* visibility = */ visibility, /* visibility = */ visibility,
/* kind = */ CallableMemberDescriptor.Kind.FAKE_OVERRIDE, /* kind = */ CallableMemberDescriptor.Kind.FAKE_OVERRIDE,
/* copyOverrides = */ true).apply { /* copyOverrides = */ true
).apply {
overriddenDescriptors += this@createFakeOverrideDescriptor overriddenDescriptors += this@createFakeOverrideDescriptor
} }
else -> null else -> null
@@ -67,22 +68,26 @@ fun DeclarationDescriptor.createFakeOverrideDescriptor(owner: ClassDescriptor):
fun FunctionDescriptor.createOverriddenDescriptor(owner: ClassDescriptor, final: Boolean = true): FunctionDescriptor { fun FunctionDescriptor.createOverriddenDescriptor(owner: ClassDescriptor, final: Boolean = true): FunctionDescriptor {
return this.newCopyBuilder() return this.newCopyBuilder()
.setOwner(owner) .setOwner(owner)
.setCopyOverrides(true) .setCopyOverrides(true)
.setModality(if (final) Modality.FINAL else Modality.OPEN) .setModality(if (final) Modality.FINAL else Modality.OPEN)
.setDispatchReceiverParameter(owner.thisAsReceiverParameter) .setDispatchReceiverParameter(owner.thisAsReceiverParameter)
.build()!!.apply { .build()!!.apply {
overriddenDescriptors += this@createOverriddenDescriptor overriddenDescriptors += this@createOverriddenDescriptor
} }
} }
fun ClassDescriptor.createSimpleDelegatingConstructorDescriptor(superConstructorDescriptor: ClassConstructorDescriptor, isPrimary: Boolean = false) fun ClassDescriptor.createSimpleDelegatingConstructorDescriptor(
superConstructorDescriptor: ClassConstructorDescriptor,
isPrimary: Boolean = false
)
: ClassConstructorDescriptor { : ClassConstructorDescriptor {
val constructorDescriptor = ClassConstructorDescriptorImpl.createSynthesized( val constructorDescriptor = ClassConstructorDescriptorImpl.createSynthesized(
/* containingDeclaration = */ this, /* containingDeclaration = */ this,
/* annotations = */ Annotations.EMPTY, /* annotations = */ Annotations.EMPTY,
/* isPrimary = */ isPrimary, /* isPrimary = */ isPrimary,
/* source = */ SourceElement.NO_SOURCE) /* source = */ SourceElement.NO_SOURCE
)
val valueParameters = superConstructorDescriptor.valueParameters.map { val valueParameters = superConstructorDescriptor.valueParameters.map {
it.copy(constructorDescriptor, it.name, it.index) it.copy(constructorDescriptor, it.name, it.index)
} }
@@ -91,26 +96,29 @@ fun ClassDescriptor.createSimpleDelegatingConstructorDescriptor(superConstructor
return constructorDescriptor return constructorDescriptor
} }
fun IrClass.addSimpleDelegatingConstructor(superConstructorSymbol: IrConstructorSymbol, fun IrClass.addSimpleDelegatingConstructor(
constructorDescriptor: ClassConstructorDescriptor, superConstructorSymbol: IrConstructorSymbol,
origin: IrDeclarationOrigin) constructorDescriptor: ClassConstructorDescriptor,
origin: IrDeclarationOrigin
)
: IrConstructor { : IrConstructor {
return IrConstructorImpl(startOffset, endOffset, origin, constructorDescriptor).also { constructor -> return IrConstructorImpl(startOffset, endOffset, origin, constructorDescriptor).also { constructor ->
constructor.createParameterDeclarations() constructor.createParameterDeclarations()
constructor.body = IrBlockBodyImpl(startOffset, endOffset, constructor.body = IrBlockBodyImpl(
listOf( startOffset, endOffset,
IrDelegatingConstructorCallImpl( listOf(
startOffset, endOffset, IrDelegatingConstructorCallImpl(
superConstructorSymbol, superConstructorSymbol.descriptor startOffset, endOffset,
).apply { superConstructorSymbol, superConstructorSymbol.descriptor
constructor.valueParameters.forEachIndexed { idx, parameter -> ).apply {
putValueArgument(idx, IrGetValueImpl(startOffset, endOffset, parameter.symbol)) constructor.valueParameters.forEachIndexed { idx, parameter ->
} putValueArgument(idx, IrGetValueImpl(startOffset, endOffset, parameter.symbol))
}, }
IrInstanceInitializerCallImpl(startOffset, endOffset, this.symbol) },
) IrInstanceInitializerCallImpl(startOffset, endOffset, this.symbol)
)
) )
constructor.parent = this constructor.parent = this
@@ -118,9 +126,11 @@ fun IrClass.addSimpleDelegatingConstructor(superConstructorSymbol: IrConstructor
} }
} }
fun CommonBackendContext.createArrayOfExpression(arrayElementType: KotlinType, fun CommonBackendContext.createArrayOfExpression(
arrayElements: List<IrExpression>, arrayElementType: KotlinType,
startOffset: Int, endOffset: Int): IrExpression { arrayElements: List<IrExpression>,
startOffset: Int, endOffset: Int
): IrExpression {
val genericArrayOfFunSymbol = ir.symbols.arrayOf val genericArrayOfFunSymbol = ir.symbols.arrayOf
val genericArrayOfFun = genericArrayOfFunSymbol.descriptor val genericArrayOfFun = genericArrayOfFunSymbol.descriptor
@@ -55,7 +55,8 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.builtIns import org.jetbrains.kotlin.types.typeUtil.builtIns
open class DefaultArgumentStubGenerator constructor(val context: CommonBackendContext, private val skipInlineMethods: Boolean = true): DeclarationContainerLoweringPass { open class DefaultArgumentStubGenerator constructor(val context: CommonBackendContext, private val skipInlineMethods: Boolean = true) :
DeclarationContainerLoweringPass {
override fun lower(irDeclarationContainer: IrDeclarationContainer) { override fun lower(irDeclarationContainer: IrDeclarationContainer) {
irDeclarationContainer.declarations.transformFlat { memberDeclaration -> irDeclarationContainer.declarations.transformFlat { memberDeclaration ->
if (memberDeclaration is IrFunction) if (memberDeclaration is IrFunction)
@@ -75,11 +76,11 @@ open class DefaultArgumentStubGenerator constructor(val context: CommonBackendCo
return listOf(irFunction) return listOf(irFunction)
val bodies = functionDescriptor.valueParameters val bodies = functionDescriptor.valueParameters
.mapNotNull{irFunction.getDefault(it)} .mapNotNull { irFunction.getDefault(it) }
log { "detected ${functionDescriptor.name.asString()} has got #${bodies.size} default expressions" } log { "detected ${functionDescriptor.name.asString()} has got #${bodies.size} default expressions" }
functionDescriptor.overriddenDescriptors.forEach { context.log{"DEFAULT-REPLACER: $it"} } functionDescriptor.overriddenDescriptors.forEach { context.log { "DEFAULT-REPLACER: $it" } }
if (bodies.isNotEmpty()) { if (bodies.isNotEmpty()) {
val newIrFunction = functionDescriptor.generateDefaultsFunction(context) val newIrFunction = functionDescriptor.generateDefaultsFunction(context)
val descriptor = newIrFunction.descriptor val descriptor = newIrFunction.descriptor
@@ -96,7 +97,7 @@ open class DefaultArgumentStubGenerator constructor(val context: CommonBackendCo
for (valueParameter in functionDescriptor.valueParameters) { for (valueParameter in functionDescriptor.valueParameters) {
val parameterSymbol = newIrFunction.valueParameters[valueParameter.index].symbol val parameterSymbol = newIrFunction.valueParameters[valueParameter.index].symbol
val temporaryVariableSymbol = val temporaryVariableSymbol =
IrVariableSymbolImpl(scope.createTemporaryVariableDescriptor(parameterSymbol.descriptor)) IrVariableSymbolImpl(scope.createTemporaryVariableDescriptor(parameterSymbol.descriptor))
params.add(temporaryVariableSymbol) params.add(temporaryVariableSymbol)
variables.put(valueParameter, temporaryVariableSymbol) variables.put(valueParameter, temporaryVariableSymbol)
if (valueParameter.hasDefaultValue()) { if (valueParameter.hasDefaultValue()) {
@@ -108,7 +109,7 @@ open class DefaultArgumentStubGenerator constructor(val context: CommonBackendCo
val expressionBody = getDefaultParameterExpressionBody(irFunction, valueParameter) val expressionBody = getDefaultParameterExpressionBody(irFunction, valueParameter)
/* Use previously calculated values in next expression. */ /* Use previously calculated values in next expression. */
expressionBody.transformChildrenVoid(object: IrElementTransformerVoid() { expressionBody.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitGetValue(expression: IrGetValue): IrExpression { override fun visitGetValue(expression: IrGetValue): IrExpression {
log { "GetValue: ${expression.descriptor}" } log { "GetValue: ${expression.descriptor}" }
val valueSymbol = variables[expression.descriptor] ?: return expression val valueSymbol = variables[expression.descriptor] ?: return expression
@@ -116,25 +117,28 @@ open class DefaultArgumentStubGenerator constructor(val context: CommonBackendCo
} }
}) })
val variableInitialization = irIfThenElse( val variableInitialization = irIfThenElse(
type = temporaryVariableSymbol.descriptor.type, type = temporaryVariableSymbol.descriptor.type,
condition = condition, condition = condition,
thenPart = expressionBody.expression, thenPart = expressionBody.expression,
elsePart = irGet(parameterSymbol)) elsePart = irGet(parameterSymbol)
+ scope.createTemporaryVariable( )
symbol = temporaryVariableSymbol, +scope.createTemporaryVariable(
initializer = variableInitialization) symbol = temporaryVariableSymbol,
initializer = variableInitialization
)
/* Mapping calculated values with its origin variables. */ /* Mapping calculated values with its origin variables. */
} else { } else {
+ scope.createTemporaryVariable( +scope.createTemporaryVariable(
symbol = temporaryVariableSymbol, symbol = temporaryVariableSymbol,
initializer = irGet(parameterSymbol)) initializer = irGet(parameterSymbol)
)
} }
} }
if (irFunction is IrConstructor) { if (irFunction is IrConstructor) {
+ IrDelegatingConstructorCallImpl( +IrDelegatingConstructorCallImpl(
startOffset = irFunction.startOffset, startOffset = irFunction.startOffset,
endOffset = irFunction.endOffset, endOffset = irFunction.endOffset,
symbol = irFunction.symbol, descriptor = irFunction.symbol.descriptor symbol = irFunction.symbol, descriptor = irFunction.symbol.descriptor
).apply { ).apply {
params.forEachIndexed { i, variable -> params.forEachIndexed { i, variable ->
putValueArgument(i, irGet(variable)) putValueArgument(i, irGet(variable))
@@ -173,48 +177,52 @@ open class DefaultArgumentStubGenerator constructor(val context: CommonBackendCo
} }
private fun Scope.createTemporaryVariableDescriptor(parameterDescriptor: ParameterDescriptor?): VariableDescriptor = private fun Scope.createTemporaryVariableDescriptor(parameterDescriptor: ParameterDescriptor?): VariableDescriptor =
IrTemporaryVariableDescriptorImpl( IrTemporaryVariableDescriptorImpl(
containingDeclaration = this.scopeOwner, containingDeclaration = this.scopeOwner,
name = parameterDescriptor!!.name.asString().synthesizedName, name = parameterDescriptor!!.name.asString().synthesizedName,
outType = parameterDescriptor.type, outType = parameterDescriptor.type,
isMutable = false) isMutable = false
)
private fun Scope.createTemporaryVariable(symbol: IrVariableSymbol, initializer: IrExpression) = private fun Scope.createTemporaryVariable(symbol: IrVariableSymbol, initializer: IrExpression) =
IrVariableImpl( IrVariableImpl(
startOffset = initializer.startOffset, startOffset = initializer.startOffset,
endOffset = initializer.endOffset, endOffset = initializer.endOffset,
origin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE, origin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
symbol = symbol).apply { symbol = symbol
).apply {
this.initializer = initializer this.initializer = initializer
} }
private fun getDefaultParameterExpressionBody(irFunction: IrFunction, valueParameter: ValueParameterDescriptor): IrExpressionBody { private fun getDefaultParameterExpressionBody(irFunction: IrFunction, valueParameter: ValueParameterDescriptor): IrExpressionBody {
return irFunction.getDefault(valueParameter) ?: TODO("FIXME!!!") return irFunction.getDefault(valueParameter) ?: TODO("FIXME!!!")
} }
private fun maskParameterDescriptor(function: IrFunction, number: Int) = private fun maskParameterDescriptor(function: IrFunction, number: Int) =
maskParameterSymbol(function, number).descriptor as ValueParameterDescriptor maskParameterSymbol(function, number).descriptor as ValueParameterDescriptor
private fun maskParameterSymbol(function: IrFunction, number: Int) =
function.valueParameters.single { it.descriptor.name == parameterMaskName(number) }.symbol
private fun markerParameterDescriptor(descriptor: FunctionDescriptor) = descriptor.valueParameters.single { it.name == kConstructorMarkerName } private fun maskParameterSymbol(function: IrFunction, number: Int) =
function.valueParameters.single { it.descriptor.name == parameterMaskName(number) }.symbol
private fun markerParameterDescriptor(descriptor: FunctionDescriptor) =
descriptor.valueParameters.single { it.name == kConstructorMarkerName }
private fun nullConst(expression: IrElement, type: KotlinType): IrExpression? { private fun nullConst(expression: IrElement, type: KotlinType): IrExpression? {
when { when {
KotlinBuiltIns.isFloat(type) -> return IrConstImpl.float (expression.startOffset, expression.endOffset, type, 0.0F) KotlinBuiltIns.isFloat(type) -> return IrConstImpl.float(expression.startOffset, expression.endOffset, type, 0.0F)
KotlinBuiltIns.isDouble(type) -> return IrConstImpl.double (expression.startOffset, expression.endOffset, type, 0.0) KotlinBuiltIns.isDouble(type) -> return IrConstImpl.double(expression.startOffset, expression.endOffset, type, 0.0)
KotlinBuiltIns.isBoolean(type) -> return IrConstImpl.boolean (expression.startOffset, expression.endOffset, type, false) KotlinBuiltIns.isBoolean(type) -> return IrConstImpl.boolean(expression.startOffset, expression.endOffset, type, false)
KotlinBuiltIns.isByte(type) -> return IrConstImpl.byte (expression.startOffset, expression.endOffset, type, 0) KotlinBuiltIns.isByte(type) -> return IrConstImpl.byte(expression.startOffset, expression.endOffset, type, 0)
KotlinBuiltIns.isChar(type) -> return IrConstImpl.char (expression.startOffset, expression.endOffset, type, 0.toChar()) KotlinBuiltIns.isChar(type) -> return IrConstImpl.char(expression.startOffset, expression.endOffset, type, 0.toChar())
KotlinBuiltIns.isShort(type) -> return IrConstImpl.short (expression.startOffset, expression.endOffset, type, 0) KotlinBuiltIns.isShort(type) -> return IrConstImpl.short(expression.startOffset, expression.endOffset, type, 0)
KotlinBuiltIns.isInt(type) -> return IrConstImpl.int (expression.startOffset, expression.endOffset, type, 0) KotlinBuiltIns.isInt(type) -> return IrConstImpl.int(expression.startOffset, expression.endOffset, type, 0)
KotlinBuiltIns.isLong(type) -> return IrConstImpl.long (expression.startOffset, expression.endOffset, type, 0) KotlinBuiltIns.isLong(type) -> return IrConstImpl.long(expression.startOffset, expression.endOffset, type, 0)
else -> return IrConstImpl.constNull (expression.startOffset, expression.endOffset, type.builtIns.nullableNothingType) else -> return IrConstImpl.constNull(expression.startOffset, expression.endOffset, type.builtIns.nullableNothingType)
} }
} }
class DefaultParameterInjector constructor(val context: CommonBackendContext, private val skipInline: Boolean = true): BodyLoweringPass { class DefaultParameterInjector constructor(val context: CommonBackendContext, private val skipInline: Boolean = true) : BodyLoweringPass {
override fun lower(irBody: IrBody) { override fun lower(irBody: IrBody) {
irBody.transformChildrenVoid(object : IrElementTransformerVoid() { irBody.transformChildrenVoid(object : IrElementTransformerVoid() {
@@ -228,17 +236,18 @@ class DefaultParameterInjector constructor(val context: CommonBackendContext, pr
return expression return expression
val (symbolForCall, params) = parametersForCall(expression) val (symbolForCall, params) = parametersForCall(expression)
return IrDelegatingConstructorCallImpl( return IrDelegatingConstructorCallImpl(
startOffset = expression.startOffset, startOffset = expression.startOffset,
endOffset = expression.endOffset, endOffset = expression.endOffset,
symbol = symbolForCall as IrConstructorSymbol, symbol = symbolForCall as IrConstructorSymbol,
descriptor = symbolForCall.descriptor) descriptor = symbolForCall.descriptor
.apply { )
params.forEach { .apply {
log { "call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}" } params.forEach {
putValueArgument(it.first.index, it.second) log { "call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}" }
} putValueArgument(it.first.index, it.second)
dispatchReceiver = expression.dispatchReceiver
} }
dispatchReceiver = expression.dispatchReceiver
}
} }
@@ -257,25 +266,28 @@ class DefaultParameterInjector constructor(val context: CommonBackendContext, pr
descriptor.typeParameters.forEach { log { "$descriptor [${it.index}]: $it" } } descriptor.typeParameters.forEach { log { "$descriptor [${it.index}]: $it" } }
descriptor.original.typeParameters.forEach { log { "${descriptor.original}[${it.index}] : $it" } } descriptor.original.typeParameters.forEach { log { "${descriptor.original}[${it.index}] : $it" } }
return IrCallImpl( return IrCallImpl(
startOffset = expression.startOffset, startOffset = expression.startOffset,
endOffset = expression.endOffset, endOffset = expression.endOffset,
symbol = symbol, symbol = symbol,
descriptor = descriptor, descriptor = descriptor,
typeArguments = expression.descriptor.typeParameters.map{it to (expression.getTypeArgument(it) ?: it.defaultType) }.toMap()) typeArguments = expression.descriptor.typeParameters.map {
.apply { it to (expression.getTypeArgument(it) ?: it.defaultType)
params.forEach { }.toMap()
log { "call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}" } )
putValueArgument(it.first.index, it.second) .apply {
} params.forEach {
expression.extensionReceiver?.apply{ log { "call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}" }
extensionReceiver = expression.extensionReceiver putValueArgument(it.first.index, it.second)
}
expression.dispatchReceiver?.apply {
dispatchReceiver = expression.dispatchReceiver
}
log { "call::extension@: ${ir2string(expression.extensionReceiver)}" }
log { "call::dispatch@: ${ir2string(expression.dispatchReceiver)}" }
} }
expression.extensionReceiver?.apply {
extensionReceiver = expression.extensionReceiver
}
expression.dispatchReceiver?.apply {
dispatchReceiver = expression.dispatchReceiver
}
log { "call::extension@: ${ir2string(expression.extensionReceiver)}" }
log { "call::dispatch@: ${ir2string(expression.dispatchReceiver)}" }
}
} }
private fun parametersForCall(expression: IrMemberAccessExpression): Pair<IrFunctionSymbol, List<Pair<ValueParameterDescriptor, IrExpression?>>> { private fun parametersForCall(expression: IrMemberAccessExpression): Pair<IrFunctionSymbol, List<Pair<ValueParameterDescriptor, IrExpression?>>> {
@@ -302,20 +314,21 @@ class DefaultParameterInjector constructor(val context: CommonBackendContext, pr
}) })
maskValues.forEachIndexed { i, maskValue -> maskValues.forEachIndexed { i, maskValue ->
params += maskParameterDescriptor(realFunction, i) to IrConstImpl.int( params += maskParameterDescriptor(realFunction, i) to IrConstImpl.int(
startOffset = irBody.startOffset, startOffset = irBody.startOffset,
endOffset = irBody.endOffset, endOffset = irBody.endOffset,
type = descriptor.builtIns.intType, type = descriptor.builtIns.intType,
value = maskValue) value = maskValue
)
} }
if (expression.descriptor is ClassConstructorDescriptor) { if (expression.descriptor is ClassConstructorDescriptor) {
val defaultArgumentMarker = context.ir.symbols.defaultConstructorMarker val defaultArgumentMarker = context.ir.symbols.defaultConstructorMarker
params += markerParameterDescriptor(realDescriptor) to IrGetObjectValueImpl( params += markerParameterDescriptor(realDescriptor) to IrGetObjectValueImpl(
startOffset = irBody.startOffset, startOffset = irBody.startOffset,
endOffset = irBody.endOffset, endOffset = irBody.endOffset,
type = defaultArgumentMarker.owner.defaultType, type = defaultArgumentMarker.owner.defaultType,
symbol = defaultArgumentMarker) symbol = defaultArgumentMarker
} )
else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) { } else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) {
params += realDescriptor.valueParameters.last() to params += realDescriptor.valueParameters.last() to
IrConstImpl.constNull(irBody.startOffset, irBody.endOffset, context.builtIns.any.defaultType) IrConstImpl.constNull(irBody.startOffset, irBody.endOffset, context.builtIns.any.defaultType)
} }
@@ -326,7 +339,7 @@ class DefaultParameterInjector constructor(val context: CommonBackendContext, pr
} }
private fun argumentCount(expression: IrMemberAccessExpression) = private fun argumentCount(expression: IrMemberAccessExpression) =
expression.descriptor.valueParameters.count { expression.getValueArgument(it) != null } expression.descriptor.valueParameters.count { expression.getValueArgument(it) != null }
}) })
} }
@@ -341,19 +354,21 @@ private fun FunctionDescriptor.generateDefaultsFunction(context: CommonBackendCo
val descriptor = when (this) { val descriptor = when (this) {
is ClassConstructorDescriptor -> is ClassConstructorDescriptor ->
ClassConstructorDescriptorImpl.create( ClassConstructorDescriptorImpl.create(
/* containingDeclaration = */ containingDeclaration, /* containingDeclaration = */ containingDeclaration,
/* annotations = */ annotations, /* annotations = */ annotations,
/* isPrimary = */ false, /* isPrimary = */ false,
/* source = */ source) /* source = */ source
)
else -> { else -> {
val name = Name.identifier("$name\$default") val name = Name.identifier("$name\$default")
SimpleFunctionDescriptorImpl.create( SimpleFunctionDescriptorImpl.create(
/* containingDeclaration = */ containingDeclaration, /* containingDeclaration = */ containingDeclaration,
/* annotations = */ annotations, /* annotations = */ annotations,
/* name = */ name, /* name = */ name,
/* kind = */ CallableMemberDescriptor.Kind.SYNTHESIZED, /* kind = */ CallableMemberDescriptor.Kind.SYNTHESIZED,
/* source = */ source) /* source = */ source
)
} }
} }
@@ -361,21 +376,24 @@ private fun FunctionDescriptor.generateDefaultsFunction(context: CommonBackendCo
valueParameter(descriptor, valueParameters.size + i, parameterMaskName(i), descriptor.builtIns.intType) valueParameter(descriptor, valueParameters.size + i, parameterMaskName(i), descriptor.builtIns.intType)
} }
if (this is ClassConstructorDescriptor) { if (this is ClassConstructorDescriptor) {
syntheticParameters += valueParameter(descriptor, syntheticParameters.last().index + 1, syntheticParameters += valueParameter(
kConstructorMarkerName, descriptor, syntheticParameters.last().index + 1,
context.ir.symbols.defaultConstructorMarker.owner.defaultType) kConstructorMarkerName,
} context.ir.symbols.defaultConstructorMarker.owner.defaultType
else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) { )
syntheticParameters += valueParameter(descriptor, syntheticParameters.last().index + 1, } else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) {
"handler".synthesizedName, syntheticParameters += valueParameter(
context.ir.symbols.any.owner.defaultType) descriptor, syntheticParameters.last().index + 1,
"handler".synthesizedName,
context.ir.symbols.any.owner.defaultType
)
} }
descriptor.initialize( descriptor.initialize(
/* receiverParameterType = */ extensionReceiverParameter?.type, /* receiverParameterType = */ extensionReceiverParameter?.type,
/* dispatchReceiverParameter = */ dispatchReceiverParameter, /* dispatchReceiverParameter = */ dispatchReceiverParameter,
/* typeParameters = */ typeParameters.map { /* typeParameters = */ typeParameters.map {
TypeParameterDescriptorImpl.createForFurtherModification( TypeParameterDescriptorImpl.createForFurtherModification(
/* containingDeclaration = */ descriptor, /* containingDeclaration = */ descriptor,
/* annotations = */ it.annotations, /* annotations = */ it.annotations,
/* reified = */ it.isReified, /* reified = */ it.isReified,
@@ -385,45 +403,46 @@ private fun FunctionDescriptor.generateDefaultsFunction(context: CommonBackendCo
/* source = */ it.source, /* source = */ it.source,
/* reportCycleError = */ null, /* reportCycleError = */ null,
/* supertypeLoopsChecker = */ SupertypeLoopChecker.EMPTY /* supertypeLoopsChecker = */ SupertypeLoopChecker.EMPTY
).apply { ).apply {
it.upperBounds.forEach { addUpperBound(it) } it.upperBounds.forEach { addUpperBound(it) }
setInitialized() setInitialized()
} }
}, },
/* unsubstitutedValueParameters = */ valueParameters.map { /* unsubstitutedValueParameters = */ valueParameters.map {
ValueParameterDescriptorImpl( ValueParameterDescriptorImpl(
containingDeclaration = descriptor, containingDeclaration = descriptor,
original = null, /* ValueParameterDescriptorImpl::copy do not save original. */ original = null, /* ValueParameterDescriptorImpl::copy do not save original. */
index = it.index, index = it.index,
annotations = it.annotations, annotations = it.annotations,
name = it.name, name = it.name,
outType = it.type, outType = it.type,
declaresDefaultValue = false, declaresDefaultValue = false,
isCrossinline = it.isCrossinline, isCrossinline = it.isCrossinline,
isNoinline = it.isNoinline, isNoinline = it.isNoinline,
varargElementType = it.varargElementType, varargElementType = it.varargElementType,
source = it.source) source = it.source
} + syntheticParameters, )
/* unsubstitutedReturnType = */ returnType, } + syntheticParameters,
/* modality = */ Modality.FINAL, /* unsubstitutedReturnType = */ returnType,
/* visibility = */ this.visibility) /* modality = */ Modality.FINAL,
/* visibility = */ this.visibility)
descriptor.isSuspend = this.isSuspend descriptor.isSuspend = this.isSuspend
context.log{"adds to cache[$this] = $descriptor"} context.log { "adds to cache[$this] = $descriptor" }
val startOffset = this.startOffsetOrUndefined val startOffset = this.startOffsetOrUndefined
val endOffset = this.endOffsetOrUndefined val endOffset = this.endOffsetOrUndefined
val result: IrFunction = when (descriptor) { val result: IrFunction = when (descriptor) {
is ClassConstructorDescriptor -> IrConstructorImpl( is ClassConstructorDescriptor -> IrConstructorImpl(
startOffset, endOffset, startOffset, endOffset,
DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER, DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER,
descriptor descriptor
) )
else -> IrFunctionImpl( else -> IrFunctionImpl(
startOffset, endOffset, startOffset, endOffset,
DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER, DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER,
descriptor descriptor
) )
} }
@@ -434,21 +453,21 @@ private fun FunctionDescriptor.generateDefaultsFunction(context: CommonBackendCo
} }
object DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER : object DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER :
IrDeclarationOriginImpl("DEFAULT_PARAMETER_EXTENT") IrDeclarationOriginImpl("DEFAULT_PARAMETER_EXTENT")
private fun valueParameter(descriptor: FunctionDescriptor, index: Int, name: Name, type: KotlinType): ValueParameterDescriptor { private fun valueParameter(descriptor: FunctionDescriptor, index: Int, name: Name, type: KotlinType): ValueParameterDescriptor {
return ValueParameterDescriptorImpl( return ValueParameterDescriptorImpl(
containingDeclaration = descriptor, containingDeclaration = descriptor,
original = null, original = null,
index = index, index = index,
annotations = Annotations.EMPTY, annotations = Annotations.EMPTY,
name = name, name = name,
outType = type, outType = type,
declaresDefaultValue = false, declaresDefaultValue = false,
isCrossinline = false, isCrossinline = false,
isNoinline = false, isNoinline = false,
varargElementType = null, varargElementType = null,
source = SourceElement.NO_SOURCE source = SourceElement.NO_SOURCE
) )
} }
@@ -64,12 +64,12 @@ private class KCallableNamePropertyTransformer(val lower: KCallableNamePropertyL
} }
statements.add( statements.add(
IrConstImpl.string( IrConstImpl.string(
expression.startOffset, expression.startOffset,
expression.endOffset, expression.endOffset,
context.builtIns.stringType, context.builtIns.stringType,
callableReference.descriptor.name.asString() callableReference.descriptor.name.asString()
) )
) )
} }
@@ -85,20 +85,22 @@ private class KCallableNamePropertyTransformer(val lower: KCallableNamePropertyL
return kind == FunctionClassDescriptor.Kind.KFunction return kind == FunctionClassDescriptor.Kind.KFunction
} }
fun BackendContext.createIrBuilder(symbol: IrSymbol, fun BackendContext.createIrBuilder(
startOffset: Int = UNDEFINED_OFFSET, symbol: IrSymbol,
endOffset: Int = UNDEFINED_OFFSET) = startOffset: Int = UNDEFINED_OFFSET,
DeclarationIrBuilder(this, symbol, startOffset, endOffset) endOffset: Int = UNDEFINED_OFFSET
) =
DeclarationIrBuilder(this, symbol, startOffset, endOffset)
class DeclarationIrBuilder( class DeclarationIrBuilder(
backendContext: BackendContext, backendContext: BackendContext,
symbol: IrSymbol, symbol: IrSymbol,
startOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET startOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET
) : IrBuilderWithScope( ) : IrBuilderWithScope(
IrLoweringContext(backendContext), IrLoweringContext(backendContext),
Scope(symbol), Scope(symbol),
startOffset, startOffset,
endOffset endOffset
) )
class IrLoweringContext(backendContext: BackendContext) : IrGeneratorContext(backendContext.irBuiltIns) class IrLoweringContext(backendContext: BackendContext) : IrGeneratorContext(backendContext.irBuiltIns)
@@ -40,7 +40,8 @@ import java.util.*
interface LocalNameProvider { interface LocalNameProvider {
fun localName(descriptor: DeclarationDescriptor): String = fun localName(descriptor: DeclarationDescriptor): String =
descriptor.name.asString() descriptor.name.asString()
companion object { companion object {
val DEFAULT = object : LocalNameProvider {} val DEFAULT = object : LocalNameProvider {}
} }
@@ -49,14 +50,15 @@ interface LocalNameProvider {
class LocalDeclarationsLowering(val context: BackendContext, val localNameProvider: LocalNameProvider = LocalNameProvider.DEFAULT) : DeclarationContainerLoweringPass { class LocalDeclarationsLowering(val context: BackendContext, val localNameProvider: LocalNameProvider = LocalNameProvider.DEFAULT) : DeclarationContainerLoweringPass {
private object DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE : private object DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE :
IrDeclarationOriginImpl("FIELD_FOR_CAPTURED_VALUE") {} IrDeclarationOriginImpl("FIELD_FOR_CAPTURED_VALUE") {}
private object STATEMENT_ORIGIN_INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE : private object STATEMENT_ORIGIN_INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE :
IrStatementOriginImpl("INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE") {} IrStatementOriginImpl("INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE") {}
override fun lower(irDeclarationContainer: IrDeclarationContainer) { override fun lower(irDeclarationContainer: IrDeclarationContainer) {
if (irDeclarationContainer is IrDeclaration && if (irDeclarationContainer is IrDeclaration &&
irDeclarationContainer.descriptor.parents.any { it is CallableDescriptor }) { irDeclarationContainer.descriptor.parents.any { it is CallableDescriptor }
) {
// Lowering of non-local declarations handles all local declarations inside. // Lowering of non-local declarations handles all local declarations inside.
// This declaration is local and shouldn't be considered. // This declaration is local and shouldn't be considered.
@@ -73,7 +75,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
is IrProperty -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations() is IrProperty -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations()
is IrField -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations() is IrField -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations()
is IrAnonymousInitializer -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations() is IrAnonymousInitializer -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations()
// TODO: visit children as well // TODO: visit children as well
else -> null else -> null
} }
} }
@@ -115,7 +117,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
var index: Int = -1 var index: Int = -1
override fun toString(): String = override fun toString(): String =
"LocalFunctionContext for $descriptor" "LocalFunctionContext for $descriptor"
} }
private class LocalClassConstructorContext(override val declaration: IrConstructor) : LocalContextWithClosureAsParameters() { private class LocalClassConstructorContext(override val declaration: IrConstructor) : LocalContextWithClosureAsParameters() {
@@ -126,7 +128,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
override lateinit var transformedDeclaration: IrConstructor override lateinit var transformedDeclaration: IrConstructor
override fun toString(): String = override fun toString(): String =
"LocalClassConstructorContext for $descriptor" "LocalClassConstructorContext for $descriptor"
} }
private class LocalClassContext(val declaration: IrClass) : LocalContext() { private class LocalClassContext(val declaration: IrClass) : LocalContext() {
@@ -140,13 +142,14 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? { override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? {
val field = capturedValueToField[descriptor] ?: return null val field = capturedValueToField[descriptor] ?: return null
return IrGetFieldImpl(startOffset, endOffset, field.symbol, return IrGetFieldImpl(
receiver = IrGetValueImpl(startOffset, endOffset, declaration.thisReceiver!!.symbol) startOffset, endOffset, field.symbol,
receiver = IrGetValueImpl(startOffset, endOffset, declaration.thisReceiver!!.symbol)
) )
} }
override fun toString(): String = override fun toString(): String =
"LocalClassContext for ${descriptor}" "LocalClassContext for ${descriptor}"
} }
private inner class LocalDeclarationsTransformer(val memberDeclaration: IrDeclaration) { private inner class LocalDeclarationsTransformer(val memberDeclaration: IrDeclaration) {
@@ -178,26 +181,26 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
} }
private fun collectRewrittenDeclarations(): ArrayList<IrDeclaration> = private fun collectRewrittenDeclarations(): ArrayList<IrDeclaration> =
ArrayList<IrDeclaration>(localFunctions.size + localClasses.size + 1).apply { ArrayList<IrDeclaration>(localFunctions.size + localClasses.size + 1).apply {
localFunctions.values.mapTo(this) { localFunctions.values.mapTo(this) {
val original = it.declaration val original = it.declaration
it.transformedDeclaration.apply { it.transformedDeclaration.apply {
this.body = original.body this.body = original.body
original.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument -> original.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument ->
val body = original.getDefault(argument)!! val body = original.getDefault(argument)!!
oldParameterToNew[argument]!!.owner.defaultValue = body oldParameterToNew[argument]!!.owner.defaultValue = body
}
} }
} }
localClasses.values.mapTo(this) {
it.declaration
}
add(memberDeclaration)
} }
localClasses.values.mapTo(this) {
it.declaration
}
add(memberDeclaration)
}
private inner class FunctionBodiesRewriter(val localContext: LocalContext?) : IrElementTransformerVoid() { private inner class FunctionBodiesRewriter(val localContext: LocalContext?) : IrElementTransformerVoid() {
override fun visitClass(declaration: IrClass): IrStatement { override fun visitClass(declaration: IrClass): IrStatement {
@@ -268,10 +271,10 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
val newCallee = transformedDeclarations[oldCallee] as IrConstructorSymbol? ?: return expression val newCallee = transformedDeclarations[oldCallee] as IrConstructorSymbol? ?: return expression
val newExpression = IrDelegatingConstructorCallImpl( val newExpression = IrDelegatingConstructorCallImpl(
expression.startOffset, expression.endOffset, expression.startOffset, expression.endOffset,
newCallee, newCallee,
newCallee.descriptor, newCallee.descriptor,
remapTypeArguments(expression, newCallee.descriptor) remapTypeArguments(expression, newCallee.descriptor)
).fillArguments(expression) ).fillArguments(expression)
return newExpression return newExpression
@@ -287,17 +290,19 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
} else { } else {
// The callee expects captured value as argument. // The callee expects captured value as argument.
val capturedValueSymbol = val capturedValueSymbol =
newParameterToCaptured[newValueParameterDescriptor] ?: newParameterToCaptured[newValueParameterDescriptor]
throw AssertionError("Non-mapped parameter $newValueParameterDescriptor") ?: throw AssertionError("Non-mapped parameter $newValueParameterDescriptor")
val capturedValueDescriptor = capturedValueSymbol.descriptor val capturedValueDescriptor = capturedValueSymbol.descriptor
localContext?.irGet( localContext?.irGet(
oldExpression.startOffset, oldExpression.endOffset, oldExpression.startOffset, oldExpression.endOffset,
capturedValueDescriptor capturedValueDescriptor
) ?: ) ?:
// Captured value is directly available for the caller. // Captured value is directly available for the caller.
IrGetValueImpl(oldExpression.startOffset, oldExpression.endOffset, IrGetValueImpl(
oldParameterToNew[capturedValueDescriptor] ?: capturedValueSymbol) oldExpression.startOffset, oldExpression.endOffset,
oldParameterToNew[capturedValueDescriptor] ?: capturedValueSymbol
)
} }
} }
@@ -315,12 +320,12 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
val newCallee = oldCallee.transformed ?: return expression val newCallee = oldCallee.transformed ?: return expression
val newCallableReference = IrFunctionReferenceImpl( val newCallableReference = IrFunctionReferenceImpl(
expression.startOffset, expression.endOffset, expression.startOffset, expression.endOffset,
expression.type, // TODO functional type for transformed descriptor expression.type, // TODO functional type for transformed descriptor
newCallee, newCallee,
newCallee.descriptor, newCallee.descriptor,
remapTypeArguments(expression, newCallee.descriptor), remapTypeArguments(expression, newCallee.descriptor),
expression.origin expression.origin
).fillArguments(expression) ).fillArguments(expression)
return newCallableReference return newCallableReference
@@ -359,8 +364,8 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
val classDescriptor = irClass.descriptor val classDescriptor = irClass.descriptor
val constructorsCallingSuper = classDescriptor.constructors val constructorsCallingSuper = classDescriptor.constructors
.map { localClassConstructors[it]!! } .map { localClassConstructors[it]!! }
.filter { it.declaration.callsSuper() } .filter { it.declaration.callsSuper() }
assert(constructorsCallingSuper.any(), { "Expected at least one constructor calling super; class: $classDescriptor" }) assert(constructorsCallingSuper.any(), { "Expected at least one constructor calling super; class: $classDescriptor" })
localClassContext.capturedValueToField.forEach { capturedValue, field -> localClassContext.capturedValueToField.forEach { capturedValue, field ->
@@ -372,10 +377,14 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
val blockBody = constructorContext.declaration.body as? IrBlockBody val blockBody = constructorContext.declaration.body as? IrBlockBody
?: throw AssertionError("Unexpected constructor body: ${constructorContext.declaration.body}") ?: throw AssertionError("Unexpected constructor body: ${constructorContext.declaration.body}")
val capturedValueExpression = constructorContext.irGet(startOffset, endOffset, capturedValue)!! val capturedValueExpression = constructorContext.irGet(startOffset, endOffset, capturedValue)!!
blockBody.statements.add(0, blockBody.statements.add(
IrSetFieldImpl(startOffset, endOffset, field.symbol, 0,
IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol), IrSetFieldImpl(
capturedValueExpression, STATEMENT_ORIGIN_INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE)) startOffset, endOffset, field.symbol,
IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol),
capturedValueExpression, STATEMENT_ORIGIN_INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE
)
)
} }
} }
} }
@@ -397,25 +406,28 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
} }
private fun createNewCall(oldCall: IrCall, newCallee: IrFunctionSymbol) = private fun createNewCall(oldCall: IrCall, newCallee: IrFunctionSymbol) =
if (oldCall is IrCallWithShallowCopy) if (oldCall is IrCallWithShallowCopy)
oldCall.shallowCopy(oldCall.origin, newCallee, oldCall.superQualifierSymbol) oldCall.shallowCopy(oldCall.origin, newCallee, oldCall.superQualifierSymbol)
else else
IrCallImpl( IrCallImpl(
oldCall.startOffset, oldCall.endOffset, oldCall.startOffset, oldCall.endOffset,
newCallee, newCallee,
newCallee.descriptor, newCallee.descriptor,
remapTypeArguments(oldCall, newCallee.descriptor), remapTypeArguments(oldCall, newCallee.descriptor),
oldCall.origin, oldCall.superQualifierSymbol oldCall.origin, oldCall.superQualifierSymbol
) )
private fun remapTypeArguments(oldExpression: IrMemberAccessExpression, newCallee: CallableDescriptor): Map<TypeParameterDescriptor, KotlinType>? { private fun remapTypeArguments(
oldExpression: IrMemberAccessExpression,
newCallee: CallableDescriptor
): Map<TypeParameterDescriptor, KotlinType>? {
val oldCallee = oldExpression.descriptor.original val oldCallee = oldExpression.descriptor.original
return if (oldCallee.typeParameters.isEmpty()) return if (oldCallee.typeParameters.isEmpty())
null null
else oldCallee.typeParameters.associateBy( else oldCallee.typeParameters.associateBy(
{ newCallee.typeParameters[it.index] }, { newCallee.typeParameters[it.index] },
{ oldExpression.getTypeArgumentOrDefault(it) } { oldExpression.getTypeArgumentOrDefault(it) }
) )
} }
@@ -442,26 +454,28 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
return localNameProvider.localName(descriptor) return localNameProvider.localName(descriptor)
} }
private fun generateNameForLiftedDeclaration(descriptor: DeclarationDescriptor, private fun generateNameForLiftedDeclaration(
newOwner: DeclarationDescriptor): Name = descriptor: DeclarationDescriptor,
Name.identifier( newOwner: DeclarationDescriptor
descriptor.parentsWithSelf ): Name =
.takeWhile { it != newOwner } Name.identifier(
.toList().reversed() descriptor.parentsWithSelf
.map { suggestLocalName(it) } .takeWhile { it != newOwner }
.joinToString(separator = "$") .toList().reversed()
) .map { suggestLocalName(it) }
.joinToString(separator = "$")
)
private fun createLiftedDescriptor(localFunctionContext: LocalFunctionContext) { private fun createLiftedDescriptor(localFunctionContext: LocalFunctionContext) {
val oldDescriptor = localFunctionContext.descriptor val oldDescriptor = localFunctionContext.descriptor
val memberOwner = memberDeclaration.descriptor.containingDeclaration!! val memberOwner = memberDeclaration.descriptor.containingDeclaration!!
val newDescriptor = SimpleFunctionDescriptorImpl.create( val newDescriptor = SimpleFunctionDescriptorImpl.create(
memberOwner, memberOwner,
oldDescriptor.annotations, oldDescriptor.annotations,
generateNameForLiftedDeclaration(oldDescriptor, memberOwner), generateNameForLiftedDeclaration(oldDescriptor, memberOwner),
CallableMemberDescriptor.Kind.SYNTHESIZED, CallableMemberDescriptor.Kind.SYNTHESIZED,
oldDescriptor.source oldDescriptor.source
).apply { ).apply {
isTailrec = oldDescriptor.isTailrec isTailrec = oldDescriptor.isTailrec
isSuspend = oldDescriptor.isSuspend isSuspend = oldDescriptor.isSuspend
@@ -485,13 +499,13 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
val newValueParameters = createTransformedValueParameters(localFunctionContext, capturedValues) val newValueParameters = createTransformedValueParameters(localFunctionContext, capturedValues)
newDescriptor.initialize( newDescriptor.initialize(
oldDescriptor.extensionReceiverParameter?.type, oldDescriptor.extensionReceiverParameter?.type,
newDispatchReceiverParameter, newDispatchReceiverParameter,
newTypeParameters, newTypeParameters,
newValueParameters, newValueParameters,
oldDescriptor.returnType, oldDescriptor.returnType,
Modality.FINAL, Modality.FINAL,
Visibilities.PRIVATE Visibilities.PRIVATE
) )
oldDescriptor.extensionReceiverParameter?.let { oldDescriptor.extensionReceiverParameter?.let {
@@ -507,8 +521,10 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
} }
} }
private fun createTransformedValueParameters(localContext: LocalContextWithClosureAsParameters, private fun createTransformedValueParameters(
capturedValues: List<IrValueSymbol>) localContext: LocalContextWithClosureAsParameters,
capturedValues: List<IrValueSymbol>
)
: List<ValueParameterDescriptor> { : List<ValueParameterDescriptor> {
val oldDescriptor = localContext.descriptor val oldDescriptor = localContext.descriptor
@@ -555,8 +571,9 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
val oldDescriptor = constructorContext.descriptor val oldDescriptor = constructorContext.descriptor
val localClassContext = localClasses[oldDescriptor.containingDeclaration]!! val localClassContext = localClasses[oldDescriptor.containingDeclaration]!!
val newDescriptor = ClassConstructorDescriptorImpl.create( val newDescriptor = ClassConstructorDescriptorImpl.create(
localClassContext.descriptor, localClassContext.descriptor,
Annotations.EMPTY, oldDescriptor.isPrimary, oldDescriptor.source) Annotations.EMPTY, oldDescriptor.isPrimary, oldDescriptor.source
)
constructorContext.transformedDescriptor = newDescriptor constructorContext.transformedDescriptor = newDescriptor
@@ -568,9 +585,9 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
val newValueParameters = createTransformedValueParameters(constructorContext, capturedValues) val newValueParameters = createTransformedValueParameters(constructorContext, capturedValues)
newDescriptor.initialize( newDescriptor.initialize(
newValueParameters, newValueParameters,
Visibilities.PRIVATE, Visibilities.PRIVATE,
newTypeParameters newTypeParameters
) )
newDescriptor.returnType = oldDescriptor.returnType newDescriptor.returnType = oldDescriptor.returnType
@@ -596,35 +613,37 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
localClassContext.closure.capturedValues.forEach { capturedValue -> localClassContext.closure.capturedValues.forEach { capturedValue ->
val fieldDescriptor = PropertyDescriptorImpl.create( val fieldDescriptor = PropertyDescriptorImpl.create(
classDescriptor, classDescriptor,
Annotations.EMPTY, Annotations.EMPTY,
Modality.FINAL, Modality.FINAL,
Visibilities.PRIVATE, Visibilities.PRIVATE,
/* isVar = */ false, /* isVar = */ false,
suggestNameForCapturedValue(capturedValue.descriptor), suggestNameForCapturedValue(capturedValue.descriptor),
CallableMemberDescriptor.Kind.SYNTHESIZED, CallableMemberDescriptor.Kind.SYNTHESIZED,
SourceElement.NO_SOURCE, SourceElement.NO_SOURCE,
/* lateInit = */ false, /* lateInit = */ false,
/* isConst = */ false, /* isConst = */ false,
/* isExpect = */ false, /* isExpect = */ false,
/* isActual = */ false, /* isActual = */ false,
/* isExternal = */ false, /* isExternal = */ false,
/* isDelegated = */ false) /* isDelegated = */ false
)
fieldDescriptor.initialize(/* getter = */ null, /* setter = */ null) fieldDescriptor.initialize(/* getter = */ null, /* setter = */ null)
val extensionReceiverParameter: ReceiverParameterDescriptor? = null val extensionReceiverParameter: ReceiverParameterDescriptor? = null
fieldDescriptor.setType( fieldDescriptor.setType(
capturedValue.descriptor.type, capturedValue.descriptor.type,
emptyList<TypeParameterDescriptor>(), emptyList<TypeParameterDescriptor>(),
classDescriptor.thisAsReceiverParameter, classDescriptor.thisAsReceiverParameter,
extensionReceiverParameter) extensionReceiverParameter
)
localClassContext.capturedValueToField[capturedValue.descriptor] = IrFieldImpl( localClassContext.capturedValueToField[capturedValue.descriptor] = IrFieldImpl(
localClassContext.declaration.startOffset, localClassContext.declaration.endOffset, localClassContext.declaration.startOffset, localClassContext.declaration.endOffset,
DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE, DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE,
fieldDescriptor fieldDescriptor
) )
} }
} }
@@ -638,31 +657,31 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
} }
private fun suggestNameForCapturedValue(valueDescriptor: ValueDescriptor): Name = private fun suggestNameForCapturedValue(valueDescriptor: ValueDescriptor): Name =
if (valueDescriptor.name.isSpecial) { if (valueDescriptor.name.isSpecial) {
val oldNameStr = valueDescriptor.name.asString() val oldNameStr = valueDescriptor.name.asString()
oldNameStr.substring(1, oldNameStr.length - 1).synthesizedName oldNameStr.substring(1, oldNameStr.length - 1).synthesizedName
} else } else
valueDescriptor.name valueDescriptor.name
private fun createUnsubstitutedCapturedValueParameter( private fun createUnsubstitutedCapturedValueParameter(
newParameterOwner: CallableMemberDescriptor, newParameterOwner: CallableMemberDescriptor,
valueDescriptor: ValueDescriptor, valueDescriptor: ValueDescriptor,
index: Int index: Int
): ValueParameterDescriptor = ): ValueParameterDescriptor =
ValueParameterDescriptorImpl( ValueParameterDescriptorImpl(
newParameterOwner, null, index, newParameterOwner, null, index,
valueDescriptor.annotations, valueDescriptor.annotations,
suggestNameForCapturedValue(valueDescriptor), suggestNameForCapturedValue(valueDescriptor),
valueDescriptor.type, valueDescriptor.type,
false, false, false, null, valueDescriptor.source false, false, false, null, valueDescriptor.source
) )
private fun createUnsubstitutedParameter( private fun createUnsubstitutedParameter(
newParameterOwner: CallableMemberDescriptor, newParameterOwner: CallableMemberDescriptor,
valueParameterDescriptor: ValueParameterDescriptor, valueParameterDescriptor: ValueParameterDescriptor,
newIndex: Int newIndex: Int
): ValueParameterDescriptor = ): ValueParameterDescriptor =
valueParameterDescriptor.copy(newParameterOwner, valueParameterDescriptor.name, newIndex) valueParameterDescriptor.copy(newParameterOwner, valueParameterDescriptor.name, newIndex)
private fun collectClosures() { private fun collectClosures() {
@@ -70,8 +70,10 @@ private fun lowerTailRecursionCalls(context: BackendContext, irFunction: IrFunct
it to irTemporary(irGet(variable), nameHint = it.suggestVariableName()).symbol it to irTemporary(irGet(variable), nameHint = it.suggestVariableName()).symbol
} }
val transformer = BodyTransformer(builder, irFunction, loop, val transformer = BodyTransformer(
parameterToNew, parameterToVariable, tailRecursionCalls) builder, irFunction, loop,
parameterToNew, parameterToVariable, tailRecursionCalls
)
oldBody.statements.forEach { oldBody.statements.forEach {
+it.transform(transformer, null) +it.transform(transformer, null)
@@ -84,12 +86,12 @@ private fun lowerTailRecursionCalls(context: BackendContext, irFunction: IrFunct
} }
private class BodyTransformer( private class BodyTransformer(
val builder: IrBuilderWithScope, val builder: IrBuilderWithScope,
val irFunction: IrFunction, val irFunction: IrFunction,
val loop: IrLoop, val loop: IrLoop,
val parameterToNew: Map<IrValueParameterSymbol, IrValueSymbol>, val parameterToNew: Map<IrValueParameterSymbol, IrValueSymbol>,
val parameterToVariable: Map<IrValueParameterSymbol, IrVariableSymbol>, val parameterToVariable: Map<IrValueParameterSymbol, IrVariableSymbol>,
val tailRecursionCalls: Set<IrCall> val tailRecursionCalls: Set<IrCall>
) : IrElementTransformerVoid() { ) : IrElementTransformerVoid() {
val parameters = irFunction.explicitParameters val parameters = irFunction.explicitParameters
@@ -128,24 +130,23 @@ private class BodyTransformer(
// For each unspecified argument set the corresponding variable to default: // For each unspecified argument set the corresponding variable to default:
parameters.filter { it !in specifiedParameters }.forEach { parameter -> parameters.filter { it !in specifiedParameters }.forEach { parameter ->
val originalDefaultValue = parameter.owner.defaultValue?.expression ?: val originalDefaultValue = parameter.owner.defaultValue?.expression ?: throw Error("no argument specified for $parameter")
throw Error("no argument specified for $parameter")
// Copy default value, mapping parameters to variables containing freshly computed arguments: // Copy default value, mapping parameters to variables containing freshly computed arguments:
val defaultValue = originalDefaultValue val defaultValue = originalDefaultValue
.deepCopyWithVariables() .deepCopyWithVariables()
.transform(object : IrElementTransformerVoid() { .transform(object : IrElementTransformerVoid() {
override fun visitGetValue(expression: IrGetValue): IrExpression { override fun visitGetValue(expression: IrGetValue): IrExpression {
expression.transformChildrenVoid(this) expression.transformChildrenVoid(this)
val variableSymbol = parameterToVariable[expression.symbol] ?: return expression val variableSymbol = parameterToVariable[expression.symbol] ?: return expression
return IrGetValueImpl( return IrGetValueImpl(
expression.startOffset, expression.endOffset, expression.startOffset, expression.endOffset,
variableSymbol, expression.origin variableSymbol, expression.origin
) )
} }
}, data = null) }, data = null)
+irSetVar(parameterToVariable[parameter]!!, defaultValue) +irSetVar(parameterToVariable[parameter]!!, defaultValue)
} }
@@ -21,10 +21,10 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmDescriptorWithExtraFlags import org.jetbrains.kotlin.backend.jvm.descriptors.JvmDescriptorWithExtraFlags
import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.MemberCodegen.badDescriptor
import org.jetbrains.kotlin.codegen.binding.CodegenBinding import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.util.dump
import org.jetbrains.kotlin.load.java.JavaVisibilities import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
@@ -40,9 +40,9 @@ import org.jetbrains.org.objectweb.asm.Type
import java.lang.RuntimeException import java.lang.RuntimeException
class ClassCodegen private constructor( class ClassCodegen private constructor(
private val irClass: IrClass, private val irClass: IrClass,
val context: JvmBackendContext, val context: JvmBackendContext,
private val parentClassCodegen: ClassCodegen? = null private val parentClassCodegen: ClassCodegen? = null
) : InnerClassConsumer { ) : InnerClassConsumer {
private val innerClasses = mutableListOf<ClassDescriptor>() private val innerClasses = mutableListOf<ClassDescriptor>()
@@ -55,7 +55,10 @@ class ClassCodegen private constructor(
private val isAnonymous = DescriptorUtils.isAnonymousObject(irClass.descriptor) private val isAnonymous = DescriptorUtils.isAnonymousObject(irClass.descriptor)
val type: Type = if (isAnonymous) CodegenBinding.asmTypeForAnonymousClass(state.bindingContext, descriptor.source.getPsi() as KtElement) else typeMapper.mapType(descriptor) val type: Type = if (isAnonymous) CodegenBinding.asmTypeForAnonymousClass(
state.bindingContext,
descriptor.source.getPsi() as KtElement
) else typeMapper.mapType(descriptor)
val psiElement = irClass.descriptor.psiElement!! val psiElement = irClass.descriptor.psiElement!!
@@ -66,13 +69,13 @@ class ClassCodegen private constructor(
val signature = ImplementationBodyCodegen.signature(descriptor, type, superClassInfo, typeMapper) val signature = ImplementationBodyCodegen.signature(descriptor, type, superClassInfo, typeMapper)
visitor.defineClass( visitor.defineClass(
psiElement, psiElement,
state.classFileVersion, state.classFileVersion,
descriptor.calculateClassFlags(), descriptor.calculateClassFlags(),
signature.name, signature.name,
signature.javaGenericSignature, signature.javaGenericSignature,
signature.superclassName, signature.superclassName,
signature.interfaces.toTypedArray() signature.interfaces.toTypedArray()
) )
AnnotationCodegen.forClass(visitor.visitor, this, typeMapper).genAnnotations(descriptor, null) AnnotationCodegen.forClass(visitor.visitor, this, typeMapper).genAnnotations(descriptor, null)
@@ -91,16 +94,22 @@ class ClassCodegen private constructor(
val state = context.state val state = context.state
if (ErrorUtils.isError(descriptor)) { if (ErrorUtils.isError(descriptor)) {
badDescriptor(descriptor, state.classBuilderMode) badDescriptor(irClass, state.classBuilderMode)
return return
} }
if (descriptor.name == SpecialNames.NO_NAME_PROVIDED) { if (irClass.name == SpecialNames.NO_NAME_PROVIDED) {
badDescriptor(descriptor, state.classBuilderMode) badDescriptor(irClass, state.classBuilderMode)
} }
ClassCodegen(irClass, context).generate() ClassCodegen(irClass, context).generate()
} }
private fun badDescriptor(irClass: IrClass, mode: ClassBuilderMode) {
if (mode.generateBodies) {
throw IllegalStateException("Generating bad class in ClassBuilderMode = $mode: ${irClass.dump()}")
}
}
} }
fun generateDeclaration(declaration: IrDeclaration) { fun generateDeclaration(declaration: IrDeclaration) {
@@ -128,13 +137,14 @@ class ClassCodegen private constructor(
if (field.origin == IrDeclarationOrigin.FAKE_OVERRIDE) return if (field.origin == IrDeclarationOrigin.FAKE_OVERRIDE) return
val fieldType = typeMapper.mapType(field.descriptor) val fieldType = typeMapper.mapType(field.descriptor)
val fieldSignature = typeMapper.mapFieldSignature(field.descriptor.type, field.descriptor) val fieldSignature = typeMapper.mapFieldSignature(field.descriptor.type, field.descriptor)
val fv = visitor.newField(field.OtherOrigin, field.descriptor.calculateCommonFlags(), field.descriptor.name.asString(), fieldType.descriptor, val fv = visitor.newField(
fieldSignature, null/*TODO support default values*/) field.OtherOrigin, field.descriptor.calculateCommonFlags(), field.descriptor.name.asString(), fieldType.descriptor,
fieldSignature, null/*TODO support default values*/
)
if (field.origin == JvmLoweredDeclarationOrigin.FIELD_FOR_ENUM_ENTRY) { if (field.origin == JvmLoweredDeclarationOrigin.FIELD_FOR_ENUM_ENTRY) {
AnnotationCodegen.forField(fv, this, typeMapper).genAnnotations(field.descriptor, null) AnnotationCodegen.forField(fv, this, typeMapper).genAnnotations(field.descriptor, null)
} } else {
else {
} }
} }
@@ -200,21 +210,17 @@ fun MemberDescriptor.calculateCommonFlags(): Int {
var flags = 0 var flags = 0
if (Visibilities.isPrivate(visibility)) { if (Visibilities.isPrivate(visibility)) {
flags = flags.or(Opcodes.ACC_PRIVATE) flags = flags.or(Opcodes.ACC_PRIVATE)
} } else if (visibility == Visibilities.PUBLIC || visibility == Visibilities.INTERNAL) {
else if (visibility == Visibilities.PUBLIC || visibility == Visibilities.INTERNAL) {
flags = flags.or(Opcodes.ACC_PUBLIC) flags = flags.or(Opcodes.ACC_PUBLIC)
} } else if (visibility == Visibilities.PROTECTED) {
else if (visibility == Visibilities.PROTECTED) {
flags = flags.or(Opcodes.ACC_PROTECTED) flags = flags.or(Opcodes.ACC_PROTECTED)
} } else if (visibility == JavaVisibilities.PACKAGE_VISIBILITY) {
else if (visibility == JavaVisibilities.PACKAGE_VISIBILITY) {
// default visibility // default visibility
} } else {
else {
throw RuntimeException("Unsupported visibility $visibility for descriptor $this") throw RuntimeException("Unsupported visibility $visibility for descriptor $this")
} }
flags = flags.or(calcModalityFlag()) flags = flags.or(calcModalityFlag())
if (this is JvmDescriptorWithExtraFlags) { if (this is JvmDescriptorWithExtraFlags) {
flags = flags or extraFlags flags = flags or extraFlags
@@ -257,7 +263,8 @@ private val MemberDescriptor.effectiveModality: Modality
} }
if (DescriptorUtils.isSealedClass(this) || if (DescriptorUtils.isSealedClass(this) ||
DescriptorUtils.isAnnotationClass(this) || DescriptorUtils.isAnnotationClass(this) ||
DescriptorUtils.isAnnotationClass(this.containingDeclaration)) { DescriptorUtils.isAnnotationClass(this.containingDeclaration)
) {
return Modality.ABSTRACT return Modality.ABSTRACT
} }
@@ -37,42 +37,42 @@ import org.jetbrains.org.objectweb.asm.Opcodes
import java.util.* import java.util.*
class JvmDescriptorsFactory( class JvmDescriptorsFactory(
private val psiSourceManager: PsiSourceManager, private val psiSourceManager: PsiSourceManager,
private val builtIns: KotlinBuiltIns private val builtIns: KotlinBuiltIns
) : DescriptorsFactory { ) : DescriptorsFactory {
private val singletonFieldDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>() private val singletonFieldDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>()
private val outerThisDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>() private val outerThisDescriptors = HashMap<ClassDescriptor, PropertyDescriptor>()
private val innerClassConstructors = HashMap<ClassConstructorDescriptor, IrConstructorSymbol>() private val innerClassConstructors = HashMap<ClassConstructorDescriptor, IrConstructorSymbol>()
override fun getFieldDescriptorForEnumEntry(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor = override fun getFieldDescriptorForEnumEntry(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor =
singletonFieldDescriptors.getOrPut(enumEntryDescriptor) { singletonFieldDescriptors.getOrPut(enumEntryDescriptor) {
createEnumEntryFieldDescriptor(enumEntryDescriptor) createEnumEntryFieldDescriptor(enumEntryDescriptor)
} }
fun createFileClassDescriptor(fileEntry: SourceManager.FileEntry, packageFragment: PackageFragmentDescriptor): FileClassDescriptor { fun createFileClassDescriptor(fileEntry: SourceManager.FileEntry, packageFragment: PackageFragmentDescriptor): FileClassDescriptor {
val ktFile = psiSourceManager.getKtFile(fileEntry as PsiSourceManager.PsiFileEntry) val ktFile = psiSourceManager.getKtFile(fileEntry as PsiSourceManager.PsiFileEntry)
?: throw AssertionError("Unexpected file entry: $fileEntry") ?: throw AssertionError("Unexpected file entry: $fileEntry")
val fileClassInfo = JvmFileClassUtil.getFileClassInfoNoResolve(ktFile) val fileClassInfo = JvmFileClassUtil.getFileClassInfoNoResolve(ktFile)
val sourceElement = KotlinSourceElement(ktFile) val sourceElement = KotlinSourceElement(ktFile)
return FileClassDescriptorImpl( return FileClassDescriptorImpl(
fileClassInfo.fileClassFqName.shortName(), packageFragment, fileClassInfo.fileClassFqName.shortName(), packageFragment,
listOf(builtIns.anyType), listOf(builtIns.anyType),
sourceElement, sourceElement,
Annotations.EMPTY // TODO file annotations Annotations.EMPTY // TODO file annotations
) )
} }
override fun getOuterThisFieldDescriptor(innerClassDescriptor: ClassDescriptor): PropertyDescriptor = override fun getOuterThisFieldDescriptor(innerClassDescriptor: ClassDescriptor): PropertyDescriptor =
if (!innerClassDescriptor.isInner) throw AssertionError("Class is not inner: $innerClassDescriptor") if (!innerClassDescriptor.isInner) throw AssertionError("Class is not inner: $innerClassDescriptor")
else outerThisDescriptors.getOrPut(innerClassDescriptor) { else outerThisDescriptors.getOrPut(innerClassDescriptor) {
val outerClassDescriptor = DescriptorUtils.getContainingClass(innerClassDescriptor) ?: val outerClassDescriptor = DescriptorUtils.getContainingClass(innerClassDescriptor)
throw AssertionError("No containing class for inner class $innerClassDescriptor") ?: throw AssertionError("No containing class for inner class $innerClassDescriptor")
JvmPropertyDescriptorImpl.createFinalField( JvmPropertyDescriptorImpl.createFinalField(
Name.identifier("this$0"), outerClassDescriptor.defaultType, innerClassDescriptor, Name.identifier("this$0"), outerClassDescriptor.defaultType, innerClassDescriptor,
Annotations.EMPTY, JavaVisibilities.PACKAGE_VISIBILITY, Opcodes.ACC_SYNTHETIC, SourceElement.NO_SOURCE Annotations.EMPTY, JavaVisibilities.PACKAGE_VISIBILITY, Opcodes.ACC_SYNTHETIC, SourceElement.NO_SOURCE
) )
} }
override fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: ClassConstructorDescriptor): IrConstructorSymbol { override fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: ClassConstructorDescriptor): IrConstructorSymbol {
val innerClass = innerClassConstructor.containingDeclaration val innerClass = innerClassConstructor.containingDeclaration
@@ -88,43 +88,42 @@ class JvmDescriptorsFactory(
val outerThisType = (classDescriptor.containingDeclaration as ClassDescriptor).defaultType val outerThisType = (classDescriptor.containingDeclaration as ClassDescriptor).defaultType
val newDescriptor = ClassConstructorDescriptorImpl.createSynthesized( val newDescriptor = ClassConstructorDescriptorImpl.createSynthesized(
classDescriptor, oldDescriptor.annotations, oldDescriptor.isPrimary, oldDescriptor.source classDescriptor, oldDescriptor.annotations, oldDescriptor.isPrimary, oldDescriptor.source
) )
val outerThisValueParameter = newDescriptor.createValueParameter(0, "\$outer", outerThisType) val outerThisValueParameter = newDescriptor.createValueParameter(0, "\$outer", outerThisType)
val newValueParameters = val newValueParameters =
listOf(outerThisValueParameter) + listOf(outerThisValueParameter) +
oldDescriptor.valueParameters.map { it.copy(newDescriptor, it.name, it.index + 1) } oldDescriptor.valueParameters.map { it.copy(newDescriptor, it.name, it.index + 1) }
newDescriptor.initialize(newValueParameters, oldDescriptor.visibility) newDescriptor.initialize(newValueParameters, oldDescriptor.visibility)
newDescriptor.returnType = oldDescriptor.returnType newDescriptor.returnType = oldDescriptor.returnType
return IrConstructorSymbolImpl(newDescriptor) return IrConstructorSymbolImpl(newDescriptor)
} }
private fun createEnumEntryFieldDescriptor(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor { private fun createEnumEntryFieldDescriptor(enumEntryDescriptor: ClassDescriptor): PropertyDescriptor {
assert(enumEntryDescriptor.kind == ClassKind.ENUM_ENTRY) { "Should be enum entry: $enumEntryDescriptor" } assert(enumEntryDescriptor.kind == ClassKind.ENUM_ENTRY) { "Should be enum entry: $enumEntryDescriptor" }
val enumClassDescriptor = enumEntryDescriptor.containingDeclaration as ClassDescriptor val enumClassDescriptor = enumEntryDescriptor.containingDeclaration as ClassDescriptor
assert(enumClassDescriptor.kind == ClassKind.ENUM_CLASS) { "Should be enum class: $enumClassDescriptor"} assert(enumClassDescriptor.kind == ClassKind.ENUM_CLASS) { "Should be enum class: $enumClassDescriptor" }
return JvmPropertyDescriptorImpl.createStaticVal( return JvmPropertyDescriptorImpl.createStaticVal(
enumEntryDescriptor.name, enumEntryDescriptor.name,
enumClassDescriptor.defaultType, enumClassDescriptor.defaultType,
enumClassDescriptor, enumClassDescriptor,
enumEntryDescriptor.annotations, enumEntryDescriptor.annotations,
Modality.FINAL, Modality.FINAL,
Visibilities.PUBLIC, Visibilities.PUBLIC,
Opcodes.ACC_ENUM, Opcodes.ACC_ENUM,
enumEntryDescriptor.source enumEntryDescriptor.source
) )
} }
override fun getFieldDescriptorForObjectInstance(objectDescriptor: ClassDescriptor): PropertyDescriptor = override fun getFieldDescriptorForObjectInstance(objectDescriptor: ClassDescriptor): PropertyDescriptor =
singletonFieldDescriptors.getOrPut(objectDescriptor) { singletonFieldDescriptors.getOrPut(objectDescriptor) {
createObjectInstanceFieldDescriptor(objectDescriptor) createObjectInstanceFieldDescriptor(objectDescriptor)
} }
private fun createObjectInstanceFieldDescriptor(objectDescriptor: ClassDescriptor): PropertyDescriptor { private fun createObjectInstanceFieldDescriptor(objectDescriptor: ClassDescriptor): PropertyDescriptor {
assert(objectDescriptor.kind == ClassKind.OBJECT) { "Should be an object: $objectDescriptor" } assert(objectDescriptor.kind == ClassKind.OBJECT) { "Should be an object: $objectDescriptor" }
@@ -133,11 +132,11 @@ class JvmDescriptorsFactory(
val name = if (isNotMappedCompanion) objectDescriptor.name else Name.identifier("INSTANCE") val name = if (isNotMappedCompanion) objectDescriptor.name else Name.identifier("INSTANCE")
val containingDeclaration = if (isNotMappedCompanion) objectDescriptor.containingDeclaration else objectDescriptor val containingDeclaration = if (isNotMappedCompanion) objectDescriptor.containingDeclaration else objectDescriptor
return PropertyDescriptorImpl.create( return PropertyDescriptorImpl.create(
containingDeclaration, containingDeclaration,
Annotations.EMPTY, Modality.FINAL, Visibilities.PUBLIC, false, Annotations.EMPTY, Modality.FINAL, Visibilities.PUBLIC, false,
name, name,
CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE, /* lateInit = */ false, /* isConst = */ false, CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE, /* lateInit = */ false, /* isConst = */ false,
/* isExpect = */ false, /* isActual = */ false, /* isExternal = */ false, /* isDelegated = */ false /* isExpect = */ false, /* isActual = */ false, /* isExternal = */ false, /* isDelegated = */ false
).initialize(objectDescriptor.defaultType) ).initialize(objectDescriptor.defaultType)
} }
} }
@@ -67,12 +67,10 @@ class ConstAndJvmFieldPropertiesLowering : IrElementTransformerVoid(), FileLower
if (JvmCodegenUtil.isConstOrHasJvmFieldAnnotation(property)) { if (JvmCodegenUtil.isConstOrHasJvmFieldAnnotation(property)) {
return if (descriptor is PropertyGetterDescriptor) { return if (descriptor is PropertyGetterDescriptor) {
substituteGetter(descriptor, expression) substituteGetter(descriptor, expression)
} } else {
else {
substituteSetter(descriptor, expression) substituteSetter(descriptor, expression)
} }
} } else if (property is SyntheticJavaPropertyDescriptor) {
else if (property is SyntheticJavaPropertyDescriptor) {
expression.dispatchReceiver = expression.extensionReceiver expression.dispatchReceiver = expression.extensionReceiver
expression.extensionReceiver = null expression.extensionReceiver = null
} }
@@ -81,24 +79,24 @@ class ConstAndJvmFieldPropertiesLowering : IrElementTransformerVoid(), FileLower
private fun substituteSetter(descriptor: PropertyAccessorDescriptor, expression: IrCall): IrSetFieldImpl { private fun substituteSetter(descriptor: PropertyAccessorDescriptor, expression: IrCall): IrSetFieldImpl {
return IrSetFieldImpl( return IrSetFieldImpl(
expression.startOffset, expression.startOffset,
expression.endOffset, expression.endOffset,
descriptor.correspondingProperty, descriptor.correspondingProperty,
expression.dispatchReceiver, expression.dispatchReceiver,
expression.getValueArgument(descriptor.valueParameters.lastIndex)!!, expression.getValueArgument(descriptor.valueParameters.lastIndex)!!,
expression.origin, expression.origin,
expression.superQualifier expression.superQualifier
) )
} }
private fun substituteGetter(descriptor: PropertyGetterDescriptor, expression: IrCall): IrGetFieldImpl { private fun substituteGetter(descriptor: PropertyGetterDescriptor, expression: IrCall): IrGetFieldImpl {
return IrGetFieldImpl( return IrGetFieldImpl(
expression.startOffset, expression.startOffset,
expression.endOffset, expression.endOffset,
descriptor.correspondingProperty, descriptor.correspondingProperty,
expression.dispatchReceiver, expression.dispatchReceiver,
expression.origin, expression.origin,
expression.superQualifier expression.superQualifier
) )
} }
} }
@@ -38,10 +38,14 @@ class StaticDefaultFunctionLowering(val state: GenerationState) : IrElementTrans
override fun visitFunction(declaration: IrFunction): IrStatement { override fun visitFunction(declaration: IrFunction): IrStatement {
if (declaration.origin == DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER && declaration.dispatchReceiverParameter != null) { if (declaration.origin == DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER && declaration.dispatchReceiverParameter != null) {
val newFunction = createStaticFunctionWithReceivers(declaration.descriptor.containingDeclaration as ClassDescriptor, declaration.descriptor.name, declaration.descriptor, declaration.descriptor.dispatchReceiverParameter!!.type) val newFunction = createStaticFunctionWithReceivers(
declaration.descriptor.containingDeclaration as ClassDescriptor,
declaration.descriptor.name,
declaration.descriptor,
declaration.descriptor.dispatchReceiverParameter!!.type
)
return newFunction.createFunctionAndMapVariables(declaration) return newFunction.createFunctionAndMapVariables(declaration)
} } else {
else {
return super.visitFunction(declaration) return super.visitFunction(declaration)
} }
} }
@@ -56,22 +56,22 @@ interface StubContext {
} }
class StubCodegenContext( class StubCodegenContext(
contextDescriptor: ClassDescriptor, contextDescriptor: ClassDescriptor,
parentContext: CodegenContext<*>?, parentContext: CodegenContext<*>?,
override val irClassContext: IrClassContext override val irClassContext: IrClassContext
) :StubContext, CodegenContext<DeclarationDescriptor>( ) : StubContext, CodegenContext<DeclarationDescriptor>(
if (contextDescriptor is FileClassDescriptor) contextDescriptor.containingDeclaration else contextDescriptor, if (contextDescriptor is FileClassDescriptor) contextDescriptor.containingDeclaration else contextDescriptor,
OwnerKind.IMPLEMENTATION, parentContext, null, OwnerKind.IMPLEMENTATION, parentContext, null,
if (contextDescriptor is FileClassDescriptor) null else contextDescriptor, if (contextDescriptor is FileClassDescriptor) null else contextDescriptor,
null null
) )
class ClassStubContext( class ClassStubContext(
contextDescriptor: ClassDescriptor, contextDescriptor: ClassDescriptor,
parentContext: CodegenContext<*>?, parentContext: CodegenContext<*>?,
override val irClassContext: IrClassContext, override val irClassContext: IrClassContext,
typeMapper: KotlinTypeMapper typeMapper: KotlinTypeMapper
) : StubContext, ClassContext( typeMapper, contextDescriptor, OwnerKind.IMPLEMENTATION, parentContext, null) ) : StubContext, ClassContext(typeMapper, contextDescriptor, OwnerKind.IMPLEMENTATION, parentContext, null)
class ContextAnnotator(val state: GenerationState) : ClassLowerWithContext() { class ContextAnnotator(val state: GenerationState) : ClassLowerWithContext() {
@@ -89,8 +89,7 @@ class ContextAnnotator(val state: GenerationState) : ClassLowerWithContext() {
val descriptor = irClass.descriptor val descriptor = irClass.descriptor
val newContext: CodegenContext<*> = if (descriptor is FileClassDescriptor) { val newContext: CodegenContext<*> = if (descriptor is FileClassDescriptor) {
StubCodegenContext(descriptor, data.parent?.codegenContext, data) StubCodegenContext(descriptor, data.parent?.codegenContext, data)
} } else {
else {
ClassStubContext(descriptor, data.parent?.codegenContext, data, state.typeMapper) ClassStubContext(descriptor, data.parent?.codegenContext, data, state.typeMapper)
} }
newContext.apply { newContext.apply {
@@ -137,12 +136,15 @@ class SyntheticAccessorLowering(val context: JvmBackendContext) : FileLoweringPa
val codegenContext = data.codegenContext val codegenContext = data.codegenContext
val accessors = codegenContext.accessors val accessors = codegenContext.accessors
val allAccessors = val allAccessors =
( (
accessors.filterIsInstance<FunctionDescriptor>() + accessors.filterIsInstance<FunctionDescriptor>() +
accessors.filterIsInstance<AccessorForPropertyDescriptor>().flatMap { accessors.filterIsInstance<AccessorForPropertyDescriptor>().flatMap {
listOfNotNull(if (it.isWithSyntheticGetterAccessor) it.getter else null, if (it.isWithSyntheticSetterAccessor) it.setter else null) listOfNotNull(
} if (it.isWithSyntheticGetterAccessor) it.getter else null,
).filterIsInstance<AccessorForCallableDescriptor<*>>() if (it.isWithSyntheticSetterAccessor) it.setter else null
)
}
).filterIsInstance<AccessorForCallableDescriptor<*>>()
val irClassToAddAccessor = data.irClass val irClassToAddAccessor = data.irClass
allAccessors.forEach { accessor -> allAccessors.forEach { accessor ->
@@ -157,30 +159,55 @@ class SyntheticAccessorLowering(val context: JvmBackendContext) : FileLoweringPa
} }
companion object { companion object {
fun createSyntheticAccessorCallForFunction(superResult: IrElement, expression: IrMemberAccessExpression, codegenContext: CodegenContext<*>?, context: JvmBackendContext): IrElement { fun createSyntheticAccessorCallForFunction(
superResult: IrElement,
expression: IrMemberAccessExpression,
codegenContext: CodegenContext<*>?,
context: JvmBackendContext
): IrElement {
val descriptor = expression.descriptor val descriptor = expression.descriptor
if (descriptor is FunctionDescriptor && !expression.usesDefaultArguments()) { if (descriptor is FunctionDescriptor && !expression.usesDefaultArguments()) {
val directAccessor = codegenContext!!.accessibleDescriptor(JvmCodegenUtil.getDirectMember(descriptor), (expression as? IrCall)?.superQualifier) val directAccessor = codegenContext!!.accessibleDescriptor(
JvmCodegenUtil.getDirectMember(descriptor),
(expression as? IrCall)?.superQualifier
)
val accessor = Companion.actualAccessor(descriptor, directAccessor) val accessor = Companion.actualAccessor(descriptor, directAccessor)
if (accessor is AccessorForCallableDescriptor<*> && descriptor !is AccessorForCallableDescriptor<*>) { if (accessor is AccessorForCallableDescriptor<*> && descriptor !is AccessorForCallableDescriptor<*>) {
val isConstructor = descriptor is ConstructorDescriptor val isConstructor = descriptor is ConstructorDescriptor
val accessorOwner = accessor.containingDeclaration as ClassOrPackageFragmentDescriptor val accessorOwner = accessor.containingDeclaration as ClassOrPackageFragmentDescriptor
val accessorForIr = val accessorForIr =
accessorToIrAccessorDescriptor(isConstructor, accessor, context, descriptor, accessorOwner) //TODO change call accessorToIrAccessorDescriptor(isConstructor, accessor, context, descriptor, accessorOwner) //TODO change call
val call = val call =
if (isConstructor && expression is IrDelegatingConstructorCall) if (isConstructor && expression is IrDelegatingConstructorCall)
IrDelegatingConstructorCallImpl(expression.startOffset, expression.endOffset, accessorForIr as ClassConstructorDescriptor) IrDelegatingConstructorCallImpl(
else IrCallImpl(expression.startOffset, expression.endOffset, accessorForIr, emptyMap(), expression.origin/*TODO super*/) expression.startOffset,
expression.endOffset,
accessorForIr as ClassConstructorDescriptor
)
else IrCallImpl(
expression.startOffset,
expression.endOffset,
accessorForIr,
emptyMap(),
expression.origin/*TODO super*/
)
//copyAllArgsToValueParams(call, expression) //copyAllArgsToValueParams(call, expression)
val receiverAndArgs = expression.receiverAndArgs() val receiverAndArgs = expression.receiverAndArgs()
receiverAndArgs.forEachIndexed { i, irExpression -> receiverAndArgs.forEachIndexed { i, irExpression ->
call.putValueArgument(i, irExpression) call.putValueArgument(i, irExpression)
} }
if (isConstructor) { if (isConstructor) {
call.putValueArgument(receiverAndArgs.size, IrConstImpl.constNull(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.ir.symbols.defaultConstructorMarker.descriptor.defaultType)) call.putValueArgument(
receiverAndArgs.size,
IrConstImpl.constNull(
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
context.ir.symbols.defaultConstructorMarker.descriptor.defaultType
)
)
} }
return call return call
} }
@@ -188,12 +215,21 @@ class SyntheticAccessorLowering(val context: JvmBackendContext) : FileLoweringPa
return superResult return superResult
} }
private fun accessorToIrAccessorDescriptor(isConstructor: Boolean, accessor: CallableMemberDescriptor, context: JvmBackendContext, descriptor: FunctionDescriptor, accessorOwner: ClassOrPackageFragmentDescriptor): FunctionDescriptor { private fun accessorToIrAccessorDescriptor(
isConstructor: Boolean,
accessor: CallableMemberDescriptor,
context: JvmBackendContext,
descriptor: FunctionDescriptor,
accessorOwner: ClassOrPackageFragmentDescriptor
): FunctionDescriptor {
return if (isConstructor) return if (isConstructor)
(accessor as AccessorForConstructorDescriptor).constructorDescriptorWithMarker( (accessor as AccessorForConstructorDescriptor).constructorDescriptorWithMarker(
context.ir.symbols.defaultConstructorMarker.descriptor.defaultType context.ir.symbols.defaultConstructorMarker.descriptor.defaultType
) )
else descriptor.toStatic(accessorOwner, Name.identifier(context.state.typeMapper.mapAsmMethod(accessor as FunctionDescriptor).name)) else descriptor.toStatic(
accessorOwner,
Name.identifier(context.state.typeMapper.mapAsmMethod(accessor as FunctionDescriptor).name)
)
} }
fun addAccessorToClass(accessor: AccessorForCallableDescriptor<*>, irClassToAddAccessor: IrClass, context: JvmBackendContext) { fun addAccessorToClass(accessor: AccessorForCallableDescriptor<*>, irClassToAddAccessor: IrClass, context: JvmBackendContext) {
@@ -203,7 +239,8 @@ class SyntheticAccessorLowering(val context: JvmBackendContext) : FileLoweringPa
val accessorForIr = accessorToIrAccessorDescriptor( val accessorForIr = accessorToIrAccessorDescriptor(
isConstructor, accessor, context, isConstructor, accessor, context,
accessor.calleeDescriptor as? FunctionDescriptor ?: return, accessor.calleeDescriptor as? FunctionDescriptor ?: return,
accessorOwner) accessorOwner
)
val syntheticFunction = if (isConstructor) IrConstructorImpl( val syntheticFunction = if (isConstructor) IrConstructorImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR, UNDEFINED_OFFSET, UNDEFINED_OFFSET, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR,
accessorForIr as ClassConstructorDescriptor, body accessorForIr as ClassConstructorDescriptor, body
@@ -255,28 +292,56 @@ class SyntheticAccessorLowering(val context: JvmBackendContext) : FileLoweringPa
var offset = 0 var offset = 0
val delegateTo = call.descriptor val delegateTo = call.descriptor
delegateTo.dispatchReceiverParameter?.let { delegateTo.dispatchReceiverParameter?.let {
call.dispatchReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, syntheticFunction.valueParameters[offset++].symbol) call.dispatchReceiver =
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, syntheticFunction.valueParameters[offset++].symbol)
} }
delegateTo.extensionReceiverParameter?.let { delegateTo.extensionReceiverParameter?.let {
call.extensionReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, syntheticFunction.valueParameters[offset++].symbol) call.extensionReceiver =
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, syntheticFunction.valueParameters[offset++].symbol)
} }
call.descriptor.valueParameters.forEachIndexed { i, _ -> call.descriptor.valueParameters.forEachIndexed { i, _ ->
call.putValueArgument(i, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, syntheticFunction.valueParameters[i + offset].symbol)) call.putValueArgument(
i,
IrGetValueImpl(
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
syntheticFunction.valueParameters[i + offset].symbol
)
)
} }
} }
private fun AccessorForConstructorDescriptor.constructorDescriptorWithMarker(marker: KotlinType) = private fun AccessorForConstructorDescriptor.constructorDescriptorWithMarker(marker: KotlinType) =
ClassConstructorDescriptorImpl.createSynthesized(containingDeclaration, annotations, false, source).also { ClassConstructorDescriptorImpl.createSynthesized(containingDeclaration, annotations, false, source).also {
it.initialize( it.initialize(
DescriptorUtils.getReceiverParameterType(extensionReceiverParameter), DescriptorUtils.getReceiverParameterType(extensionReceiverParameter),
dispatchReceiverParameter, dispatchReceiverParameter,
emptyList()/*TODO*/, emptyList()/*TODO*/,
calleeDescriptor.valueParameters.map { it.copy(this, it.name, it.index) } + ValueParameterDescriptorImpl.createWithDestructuringDeclarations(it, null, calleeDescriptor.valueParameters.size, Annotations.EMPTY, Name.identifier("marker"), marker, false, false, false, null, SourceElement.NO_SOURCE, null), calleeDescriptor.valueParameters.map {
calleeDescriptor.returnType, it.copy(
Modality.FINAL, this,
Visibilities.LOCAL it.name,
it.index
)
} + ValueParameterDescriptorImpl.createWithDestructuringDeclarations(
it,
null,
calleeDescriptor.valueParameters.size,
Annotations.EMPTY,
Name.identifier("marker"),
marker,
false,
false,
false,
null,
SourceElement.NO_SOURCE,
null
),
calleeDescriptor.returnType,
Modality.FINAL,
Visibilities.LOCAL
) )
} }
} }