Update compiler to IR with symbols, part 2 (#581)

The symbols produced by first lowering phases are now bound
This commit is contained in:
SvyatoslavScherbina
2017-05-18 17:54:53 +03:00
committed by GitHub
parent 3000b1ec41
commit c9d7f976a5
29 changed files with 1332 additions and 494 deletions
@@ -20,14 +20,26 @@ import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlock
import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlockImpl import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlockImpl
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.ir.expressions.IrBlock import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.expressions.IrLoop import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrSetVariableImpl
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
import org.jetbrains.kotlin.ir.util.DeepCopyIrTree import org.jetbrains.kotlin.ir.util.DeepCopyIrTree
import org.jetbrains.kotlin.ir.util.DeepCopyIrTreeWithSymbols
import org.jetbrains.kotlin.ir.util.DeepCopySymbolsRemapper
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
/** /**
* Copies IR tree with descriptors of all declarations inside; * Copies IR tree with descriptors of all declarations inside;
* updates the references to these declarations. * updates the references to these declarations.
*/ */
@Deprecated("Creates unbound symbols")
open class DeepCopyIrTreeWithDeclarations : DeepCopyIrTree() { open class DeepCopyIrTreeWithDeclarations : DeepCopyIrTree() {
private fun DeclarationDescriptor.notSupported(): Nothing = TODO("${this}") private fun DeclarationDescriptor.notSupported(): Nothing = TODO("${this}")
@@ -95,4 +107,69 @@ open class DeepCopyIrTreeWithDeclarations : DeepCopyIrTree() {
override fun getNonTransformedLoop(irLoop: IrLoop): IrLoop { override fun getNonTransformedLoop(irLoop: IrLoop): IrLoop {
return irLoop return irLoop
} }
} }
fun IrElement.deepCopyWithVariablesImpl(): IrElement {
// FIXME: support non-transformed loops
val remapper = DeepCopySymbolsRemapper()
acceptVoid(remapper)
val variableDescriptorReplacer = object : IrElementTransformerVoid() {
val copiedVariables = mutableMapOf<IrVariableSymbol, IrVariableSymbol>()
override fun visitVariable(declaration: IrVariable): IrStatement {
declaration.transformChildrenVoid()
val descriptor = declaration.descriptor
val newDescriptor = LocalVariableDescriptor(
/* containingDeclaration = */ descriptor.containingDeclaration,
/* annotations = */ descriptor.annotations,
/* name = */ descriptor.name,
/* type = */ descriptor.type,
/* mutable = */ descriptor.isVar,
/* isDelegated = */ false,
/* source = */ descriptor.source
)
val newSymbol = IrVariableSymbolImpl(newDescriptor)
copiedVariables[declaration.symbol] = newSymbol
return with(declaration) {
IrVariableImpl(startOffset, endOffset, origin, newSymbol).also {
it.initializer = initializer
}
}
}
override fun visitValueAccess(expression: IrValueAccessExpression): IrExpression {
assert(expression.symbol !in copiedVariables)
return super.visitValueAccess(expression)
}
override fun visitGetValue(expression: IrGetValue): IrExpression {
val newSymbol = copiedVariables[expression.symbol] ?: return super.visitGetValue(expression)
expression.transformChildrenVoid()
return with(expression) {
IrGetValueImpl(startOffset, endOffset, newSymbol, origin)
}
}
override fun visitSetVariable(expression: IrSetVariable): IrExpression {
val newSymbol = copiedVariables[expression.symbol] ?: return super.visitSetVariable(expression)
expression.transformChildrenVoid()
return with(expression) {
IrSetVariableImpl(startOffset, endOffset, newSymbol, value, origin)
}
}
}
return this.transform(DeepCopyIrTreeWithSymbols(remapper), null).transform(variableDescriptorReplacer, null)
}
inline fun <reified T : IrElement> T.deepCopyWithVariables(): T =
this.deepCopyWithVariablesImpl() as T
@@ -38,7 +38,7 @@ abstract internal class IrElementTransformerVoidWithContext : IrElementTransform
} }
override final fun visitClass(declaration: IrClass): IrStatement { override final fun visitClass(declaration: IrClass): IrStatement {
scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration)) scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration))
val result = visitClassNew(declaration) val result = visitClassNew(declaration)
scopeStack.pop() scopeStack.pop()
return result return result
@@ -52,14 +52,14 @@ abstract internal class IrElementTransformerVoidWithContext : IrElementTransform
} }
override final fun visitField(declaration: IrField): IrStatement { override final fun visitField(declaration: IrField): IrStatement {
scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration)) scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration))
val result = visitFieldNew(declaration) val result = visitFieldNew(declaration)
scopeStack.pop() scopeStack.pop()
return result return result
} }
override final fun visitFunction(declaration: IrFunction): IrStatement { override final fun visitFunction(declaration: IrFunction): IrStatement {
scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration)) scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration))
val result = visitFunctionNew(declaration) val result = visitFunctionNew(declaration)
scopeStack.pop() scopeStack.pop()
return result return result
@@ -102,13 +102,13 @@ abstract internal class IrElementVisitorVoidWithContext : IrElementVisitorVoid {
private val scopeStack = mutableListOf<ScopeWithIr>() private val scopeStack = mutableListOf<ScopeWithIr>()
override final fun visitFile(declaration: IrFile) { override final fun visitFile(declaration: IrFile) {
scopeStack.push(ScopeWithIr(Scope(declaration.packageFragmentDescriptor), declaration)) scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration))
visitFileNew(declaration) visitFileNew(declaration)
scopeStack.pop() scopeStack.pop()
} }
override final fun visitClass(declaration: IrClass) { override final fun visitClass(declaration: IrClass) {
scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration)) scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration))
visitClassNew(declaration) visitClassNew(declaration)
scopeStack.pop() scopeStack.pop()
} }
@@ -121,7 +121,7 @@ abstract internal class IrElementVisitorVoidWithContext : IrElementVisitorVoid {
override final fun visitField(declaration: IrField) { override final fun visitField(declaration: IrField) {
val isDelegated = declaration.descriptor.isDelegated val isDelegated = declaration.descriptor.isDelegated
if (isDelegated) scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration)) if (isDelegated) scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration))
visitFieldNew(declaration) visitFieldNew(declaration)
if (isDelegated) scopeStack.pop() if (isDelegated) scopeStack.pop()
} }
@@ -203,7 +203,7 @@ private class IrValidator(val context: BackendContext, performHeavyValidations:
private fun recordDeclaration(declaration: IrDeclaration) { private fun recordDeclaration(declaration: IrDeclaration) {
if (foundDeclarations.isAlreadyDeclared(declaration)) { if (foundDeclarations.isAlreadyDeclared(declaration)) {
if (declaration.descriptor !is ReceiverParameterDescriptor && declaration !is IrTypeParameter) { if (declaration !is IrValueParameter && declaration !is IrTypeParameter) {
// TODO: remove the check. // TODO: remove the check.
error(declaration, "redeclaration") error(declaration, "redeclaration")
} }
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrCatch import org.jetbrains.kotlin.ir.expressions.IrCatch
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrValueAccessExpression import org.jetbrains.kotlin.ir.expressions.IrValueAccessExpression
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid
@@ -30,7 +31,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
// TODO: synchronize with JVM BE // TODO: synchronize with JVM BE
// TODO: rename the file. // TODO: rename the file.
class Closure(val capturedValues: List<ValueDescriptor> = emptyList()) class Closure(val capturedValues: List<IrValueSymbol> = emptyList())
class ClosureAnnotator { class ClosureAnnotator {
private val closureBuilders = mutableMapOf<DeclarationDescriptor, ClosureBuilder>() private val closureBuilders = mutableMapOf<DeclarationDescriptor, ClosureBuilder>()
@@ -51,7 +52,7 @@ class ClosureAnnotator {
} }
private class ClosureBuilder(val owner: DeclarationDescriptor) { private class ClosureBuilder(val owner: DeclarationDescriptor) {
val capturedValues = mutableSetOf<ValueDescriptor>() val capturedValues = mutableSetOf<IrValueSymbol>()
private val declaredValues = mutableSetOf<ValueDescriptor>() private val declaredValues = mutableSetOf<ValueDescriptor>()
private val includes = mutableSetOf<ClosureBuilder>() private val includes = mutableSetOf<ClosureBuilder>()
@@ -63,11 +64,11 @@ class ClosureAnnotator {
* variables declared in the node. * variables declared in the node.
*/ */
fun buildClosure(): Closure { fun buildClosure(): Closure {
val result = mutableSetOf<ValueDescriptor>().apply { addAll(capturedValues) } val result = mutableSetOf<IrValueSymbol>().apply { addAll(capturedValues) }
includes.forEach { includes.forEach {
if (!it.processed) { if (!it.processed) {
it.processed = true it.processed = true
it.buildClosure().capturedValues.filterTo(result) { isExternal(it) } it.buildClosure().capturedValues.filterTo(result) { isExternal(it.descriptor) }
} }
} }
// TODO: We can save the closure and reuse it. // TODO: We can save the closure and reuse it.
@@ -84,9 +85,9 @@ class ClosureAnnotator {
declaredValues.add(valueDescriptor) declaredValues.add(valueDescriptor)
} }
fun seeVariable(valueDescriptor: ValueDescriptor) { fun seeVariable(value: IrValueSymbol) {
if (isExternal(valueDescriptor)) if (isExternal(value.descriptor))
capturedValues.add(valueDescriptor) capturedValues.add(value)
} }
fun isExternal(valueDescriptor: ValueDescriptor): Boolean { fun isExternal(valueDescriptor: ValueDescriptor): Boolean {
@@ -159,7 +160,7 @@ class ClosureAnnotator {
} }
override fun visitVariableAccess(expression: IrValueAccessExpression) { override fun visitVariableAccess(expression: IrValueAccessExpression) {
closuresStack.peek()?.seeVariable(expression.descriptor) closuresStack.peek()?.seeVariable(expression.symbol)
super.visitVariableAccess(expression) super.visitVariableAccess(expression)
} }
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.* import org.jetbrains.kotlin.ir.declarations.impl.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.util.createParameterDeclarations import org.jetbrains.kotlin.ir.util.createParameterDeclarations
import org.jetbrains.kotlin.ir.util.transformFlat import org.jetbrains.kotlin.ir.util.transformFlat
import org.jetbrains.kotlin.ir.visitors.* import org.jetbrains.kotlin.ir.visitors.*
@@ -78,13 +79,14 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
get() = declaration.descriptor get() = declaration.descriptor
abstract val transformedDescriptor: FunctionDescriptor abstract val transformedDescriptor: FunctionDescriptor
abstract val transformedDeclaration: IrFunction
val capturedValueToParameter: MutableMap<ValueDescriptor, ValueParameterDescriptor> = HashMap() val capturedValueToParameter: MutableMap<ValueDescriptor, IrValueParameterSymbol> = HashMap()
override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? { override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? {
val newDescriptor = capturedValueToParameter[descriptor] ?: return null val newSymbol = capturedValueToParameter[descriptor] ?: return null
return IrGetValueImpl(startOffset, endOffset, newDescriptor) return IrGetValueImpl(startOffset, endOffset, newSymbol)
} }
} }
@@ -92,6 +94,7 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
lateinit var closure: Closure lateinit var closure: Closure
override lateinit var transformedDescriptor: FunctionDescriptor override lateinit var transformedDescriptor: FunctionDescriptor
override lateinit var transformedDeclaration: IrSimpleFunction
var index: Int = -1 var index: Int = -1
@@ -104,6 +107,7 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
get() = declaration.descriptor get() = declaration.descriptor
override lateinit var transformedDescriptor: ClassConstructorDescriptor override lateinit var transformedDescriptor: ClassConstructorDescriptor
override lateinit var transformedDeclaration: IrConstructor
override fun toString(): String = override fun toString(): String =
"LocalClassConstructorContext for $descriptor" "LocalClassConstructorContext for $descriptor"
@@ -115,13 +119,13 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
lateinit var closure: Closure lateinit var closure: Closure
val capturedValueToField: MutableMap<ValueDescriptor, PropertyDescriptor> = HashMap() val capturedValueToField: MutableMap<ValueDescriptor, IrField> = HashMap()
override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? { override fun irGet(startOffset: Int, endOffset: Int, descriptor: ValueDescriptor): IrExpression? {
val fieldDescriptor = capturedValueToField[descriptor] ?: return null val field = capturedValueToField[descriptor] ?: return null
return IrGetFieldImpl(startOffset, endOffset, fieldDescriptor, return IrGetFieldImpl(startOffset, endOffset, field.symbol,
receiver = IrGetValueImpl(startOffset, endOffset, this.descriptor.thisAsReceiverParameter) receiver = IrGetValueImpl(startOffset, endOffset, declaration.thisReceiver!!.symbol)
) )
} }
@@ -134,14 +138,14 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
val localClasses: MutableMap<ClassDescriptor, LocalClassContext> = LinkedHashMap() val localClasses: MutableMap<ClassDescriptor, LocalClassContext> = LinkedHashMap()
val localClassConstructors: MutableMap<ClassConstructorDescriptor, LocalClassConstructorContext> = LinkedHashMap() val localClassConstructors: MutableMap<ClassConstructorDescriptor, LocalClassConstructorContext> = LinkedHashMap()
val transformedDescriptors = mutableMapOf<DeclarationDescriptor, DeclarationDescriptor>() val transformedDeclarations = mutableMapOf<DeclarationDescriptor, IrSymbol>()
val FunctionDescriptor.transformed: FunctionDescriptor? val FunctionDescriptor.transformed: IrFunctionSymbol?
get() = transformedDescriptors[this] as FunctionDescriptor? get() = transformedDeclarations[this] as IrFunctionSymbol?
val oldParameterToNew: MutableMap<ParameterDescriptor, ParameterDescriptor> = HashMap() val oldParameterToNew: MutableMap<ParameterDescriptor, IrValueParameterSymbol> = HashMap()
val newParameterToOld: MutableMap<ParameterDescriptor, ParameterDescriptor> = HashMap() val newParameterToOld: MutableMap<ParameterDescriptor, ParameterDescriptor> = HashMap()
val newParameterToCaptured: MutableMap<ValueParameterDescriptor, ValueDescriptor> = HashMap() val newParameterToCaptured: MutableMap<ValueParameterDescriptor, IrValueSymbol> = HashMap()
fun lowerLocalDeclarations(): List<IrDeclaration>? { fun lowerLocalDeclarations(): List<IrDeclaration>? {
collectLocalDeclarations() collectLocalDeclarations()
@@ -163,16 +167,12 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
localFunctions.values.mapTo(this) { localFunctions.values.mapTo(this) {
val original = it.declaration val original = it.declaration
IrFunctionImpl( it.transformedDeclaration.apply {
original.startOffset, original.endOffset, original.origin, this.body = original.body
it.transformedDescriptor,
original.body
).apply {
createParameterDeclarations()
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)!!
this.putDefault(oldParameterToNew[argument] as ValueParameterDescriptor, body) oldParameterToNew[argument]!!.owner.defaultValue = body
} }
} }
} }
@@ -205,16 +205,14 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
override fun visitConstructor(declaration: IrConstructor): IrStatement { override fun visitConstructor(declaration: IrConstructor): IrStatement {
// Body is transformed separately. See loop over constructors in rewriteDeclarations(). // Body is transformed separately. See loop over constructors in rewriteDeclarations().
val transformedDescriptor = localClassConstructors[declaration.descriptor]?.transformedDescriptor val constructorContext = localClassConstructors[declaration.descriptor]
if (transformedDescriptor != null) { if (constructorContext != null) {
return IrConstructorImpl(declaration.startOffset, declaration.endOffset, declaration.origin, return constructorContext.transformedDeclaration.apply {
transformedDescriptor, declaration.body!!).apply { this.body = declaration.body!!
createParameterDeclarations()
declaration.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument -> declaration.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument ->
val body = declaration.getDefault(argument)!! val body = declaration.getDefault(argument)!!
this.putDefault(oldParameterToNew[argument] as ValueParameterDescriptor, body) oldParameterToNew[argument]!!.owner.defaultValue = body
} }
} }
} else { } else {
@@ -251,12 +249,13 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
expression.transformChildrenVoid(this) expression.transformChildrenVoid(this)
val oldCallee = expression.descriptor.original val oldCallee = expression.descriptor.original
val newCallee = transformedDescriptors[oldCallee] as ClassConstructorDescriptor? ?: 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,
remapTypeArguments(expression, newCallee) newCallee.descriptor,
remapTypeArguments(expression, newCallee.descriptor)
).fillArguments(expression) ).fillArguments(expression)
return newExpression return newExpression
@@ -271,17 +270,18 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
oldExpression.getValueArgument(oldParameter as ValueParameterDescriptor) oldExpression.getValueArgument(oldParameter as ValueParameterDescriptor)
} else { } else {
// The callee expects captured value as argument. // The callee expects captured value as argument.
val capturedValueDescriptor = val capturedValueSymbol =
newParameterToCaptured[newValueParameterDescriptor] ?: newParameterToCaptured[newValueParameterDescriptor] ?:
throw AssertionError("Non-mapped parameter $newValueParameterDescriptor") throw AssertionError("Non-mapped parameter $newValueParameterDescriptor")
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(oldExpression.startOffset, oldExpression.endOffset,
oldParameterToNew[capturedValueDescriptor] ?: capturedValueDescriptor) oldParameterToNew[capturedValueDescriptor] ?: capturedValueSymbol)
} }
} }
@@ -302,7 +302,8 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
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,
remapTypeArguments(expression, newCallee), newCallee.descriptor,
remapTypeArguments(expression, newCallee.descriptor),
expression.origin expression.origin
).fillArguments(expression) ).fillArguments(expression)
@@ -319,14 +320,14 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
} }
override fun visitDeclarationReference(expression: IrDeclarationReference): IrExpression { override fun visitDeclarationReference(expression: IrDeclarationReference): IrExpression {
if (expression.descriptor in transformedDescriptors) { if (expression.descriptor in transformedDeclarations) {
TODO() TODO()
} }
return super.visitDeclarationReference(expression) return super.visitDeclarationReference(expression)
} }
override fun visitDeclaration(declaration: IrDeclaration): IrStatement { override fun visitDeclaration(declaration: IrDeclaration): IrStatement {
if (declaration.descriptor in transformedDescriptors) { if (declaration.descriptor in transformedDeclarations) {
TODO() TODO()
} }
return super.visitDeclaration(declaration) return super.visitDeclaration(declaration)
@@ -352,24 +353,18 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
.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, fieldDescriptor -> localClassContext.capturedValueToField.forEach { capturedValue, field ->
val startOffset = irClass.startOffset val startOffset = irClass.startOffset
val endOffset = irClass.endOffset val endOffset = irClass.endOffset
irClass.declarations.add( irClass.declarations.add(field)
IrFieldImpl(
startOffset, endOffset,
DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE,
fieldDescriptor
)
)
for (constructorContext in constructorsCallingSuper) { for (constructorContext in constructorsCallingSuper) {
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(0,
IrSetFieldImpl(startOffset, endOffset, fieldDescriptor, IrSetFieldImpl(startOffset, endOffset, field.symbol,
IrGetValueImpl(startOffset, endOffset, classDescriptor.thisAsReceiverParameter), IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol),
capturedValueExpression, STATEMENT_ORIGIN_INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE)) capturedValueExpression, STATEMENT_ORIGIN_INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE))
} }
} }
@@ -391,15 +386,16 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
rewriteFunctionBody(memberDeclaration, null) rewriteFunctionBody(memberDeclaration, null)
} }
private fun createNewCall(oldCall: IrCall, newCallee: FunctionDescriptor) = private fun createNewCall(oldCall: IrCall, newCallee: IrFunctionSymbol) =
if (oldCall is IrCallWithShallowCopy) if (oldCall is IrCallWithShallowCopy)
oldCall.shallowCopy(oldCall.origin, newCallee, oldCall.superQualifier) oldCall.shallowCopy(oldCall.origin, newCallee, oldCall.superQualifierSymbol)
else else
IrCallImpl( IrCallImpl(
oldCall.startOffset, oldCall.endOffset, oldCall.startOffset, oldCall.endOffset,
newCallee, newCallee,
remapTypeArguments(oldCall, newCallee), newCallee.descriptor,
oldCall.origin, oldCall.superQualifier remapTypeArguments(oldCall, newCallee.descriptor),
oldCall.origin, oldCall.superQualifierSymbol
) )
private fun remapTypeArguments(oldExpression: IrMemberAccessExpression, newCallee: CallableDescriptor): Map<TypeParameterDescriptor, KotlinType>? { private fun remapTypeArguments(oldExpression: IrMemberAccessExpression, newCallee: CallableDescriptor): Map<TypeParameterDescriptor, KotlinType>? {
@@ -463,7 +459,6 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
} }
localFunctionContext.transformedDescriptor = newDescriptor localFunctionContext.transformedDescriptor = newDescriptor
transformedDescriptors[oldDescriptor] = newDescriptor
if (oldDescriptor.dispatchReceiverParameter != null) { if (oldDescriptor.dispatchReceiverParameter != null) {
throw AssertionError("local functions must not have dispatch receiver") throw AssertionError("local functions must not have dispatch receiver")
@@ -490,12 +485,20 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
) )
oldDescriptor.extensionReceiverParameter?.let { oldDescriptor.extensionReceiverParameter?.let {
recordRemappedParameter(it, newDescriptor.extensionReceiverParameter!!) newParameterToOld.putAbsentOrSame(newDescriptor.extensionReceiverParameter!!, it)
}
localFunctionContext.transformedDeclaration = with(localFunctionContext.declaration) {
IrFunctionImpl(startOffset, endOffset, origin, newDescriptor)
}.apply {
createParameterDeclarations()
recordTransformedValueParameters(localFunctionContext)
transformedDeclarations[oldDescriptor] = this.symbol
} }
} }
private fun createTransformedValueParameters(localContext: LocalContextWithClosureAsParameters, private fun createTransformedValueParameters(localContext: LocalContextWithClosureAsParameters,
capturedValues: List<ValueDescriptor>) capturedValues: List<IrValueSymbol>)
: List<ValueParameterDescriptor> { : List<ValueParameterDescriptor> {
val oldDescriptor = localContext.descriptor val oldDescriptor = localContext.descriptor
@@ -505,21 +508,39 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
val newValueParametersCount = closureParametersCount + oldDescriptor.valueParameters.size val newValueParametersCount = closureParametersCount + oldDescriptor.valueParameters.size
val newValueParameters = ArrayList<ValueParameterDescriptor>(newValueParametersCount).apply { val newValueParameters = ArrayList<ValueParameterDescriptor>(newValueParametersCount).apply {
capturedValues.mapIndexedTo(this) { i, capturedValueDescriptor -> capturedValues.mapIndexedTo(this) { i, capturedValue ->
createUnsubstitutedCapturedValueParameter(newDescriptor, capturedValueDescriptor, i).apply { createUnsubstitutedCapturedValueParameter(newDescriptor, capturedValue.descriptor, i).apply {
localContext.recordCapturedAsParameter(capturedValueDescriptor, this) newParameterToCaptured[this] = capturedValue
} }
} }
oldDescriptor.valueParameters.mapIndexedTo(this) { i, oldValueParameterDescriptor -> oldDescriptor.valueParameters.mapIndexedTo(this) { i, oldValueParameterDescriptor ->
createUnsubstitutedParameter(newDescriptor, oldValueParameterDescriptor, closureParametersCount + i).apply { createUnsubstitutedParameter(newDescriptor, oldValueParameterDescriptor, closureParametersCount + i).apply {
recordRemappedParameter(oldValueParameterDescriptor, this) newParameterToOld.putAbsentOrSame(this, oldValueParameterDescriptor)
} }
} }
} }
return newValueParameters return newValueParameters
} }
private fun IrFunction.recordTransformedValueParameters(localContext: LocalContextWithClosureAsParameters) {
valueParameters.forEach {
val capturedValue = newParameterToCaptured[it.descriptor]
if (capturedValue != null) {
localContext.capturedValueToParameter[capturedValue.descriptor] = it.symbol
}
}
(listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters).forEach {
val oldParameter = newParameterToOld[it.descriptor]
if (oldParameter != null) {
oldParameterToNew.putAbsentOrSame(oldParameter, it.symbol)
}
}
}
private fun createTransformedConstructorDescriptor(constructorContext: LocalClassConstructorContext) { private fun createTransformedConstructorDescriptor(constructorContext: LocalClassConstructorContext) {
val oldDescriptor = constructorContext.descriptor val oldDescriptor = constructorContext.descriptor
val localClassContext = localClasses[oldDescriptor.containingDeclaration]!! val localClassContext = localClasses[oldDescriptor.containingDeclaration]!!
@@ -528,7 +549,6 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
Annotations.EMPTY, oldDescriptor.isPrimary, oldDescriptor.source) Annotations.EMPTY, oldDescriptor.isPrimary, oldDescriptor.source)
constructorContext.transformedDescriptor = newDescriptor constructorContext.transformedDescriptor = newDescriptor
transformedDescriptors[oldDescriptor] = newDescriptor
// Do not substitute type parameters for now. // Do not substitute type parameters for now.
val newTypeParameters = oldDescriptor.typeParameters val newTypeParameters = oldDescriptor.typeParameters
@@ -545,12 +565,20 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
newDescriptor.returnType = oldDescriptor.returnType newDescriptor.returnType = oldDescriptor.returnType
oldDescriptor.dispatchReceiverParameter?.let { oldDescriptor.dispatchReceiverParameter?.let {
recordRemappedParameter(it, newDescriptor.dispatchReceiverParameter!!) newParameterToOld.putAbsentOrSame(newDescriptor.dispatchReceiverParameter!!, it)
} }
oldDescriptor.extensionReceiverParameter?.let { oldDescriptor.extensionReceiverParameter?.let {
throw AssertionError("constructors can't have extension receiver") throw AssertionError("constructors can't have extension receiver")
} }
constructorContext.transformedDeclaration = with(constructorContext.declaration) {
IrConstructorImpl(startOffset, endOffset, origin, newDescriptor)
}.apply {
createParameterDeclarations()
recordTransformedValueParameters(constructorContext)
transformedDeclarations[oldDescriptor] = this.symbol
}
} }
private fun createFieldsForCapturedValues(localClassContext: LocalClassContext) { private fun createFieldsForCapturedValues(localClassContext: LocalClassContext) {
@@ -563,7 +591,7 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
Modality.FINAL, Modality.FINAL,
Visibilities.PRIVATE, Visibilities.PRIVATE,
/* isVar = */ false, /* isVar = */ false,
suggestNameForCapturedValue(capturedValue), suggestNameForCapturedValue(capturedValue.descriptor),
CallableMemberDescriptor.Kind.SYNTHESIZED, CallableMemberDescriptor.Kind.SYNTHESIZED,
SourceElement.NO_SOURCE, SourceElement.NO_SOURCE,
/* lateInit = */ false, /* lateInit = */ false,
@@ -578,25 +606,19 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
val extensionReceiverParameter: ReceiverParameterDescriptor? = null val extensionReceiverParameter: ReceiverParameterDescriptor? = null
fieldDescriptor.setType( fieldDescriptor.setType(
capturedValue.type, capturedValue.descriptor.type,
emptyList<TypeParameterDescriptor>(), emptyList<TypeParameterDescriptor>(),
classDescriptor.thisAsReceiverParameter, classDescriptor.thisAsReceiverParameter,
extensionReceiverParameter) extensionReceiverParameter)
localClassContext.capturedValueToField[capturedValue] = fieldDescriptor localClassContext.capturedValueToField[capturedValue.descriptor] = IrFieldImpl(
localClassContext.declaration.startOffset, localClassContext.declaration.endOffset,
DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE,
fieldDescriptor
)
} }
} }
private fun LocalContextWithClosureAsParameters.recordCapturedAsParameter(
oldDescriptor: ValueDescriptor,
newDescriptor: ValueParameterDescriptor
) {
capturedValueToParameter[oldDescriptor] = newDescriptor
newParameterToCaptured[newDescriptor] = oldDescriptor
}
private fun <K, V> MutableMap<K, V>.putAbsentOrSame(key: K, value: V) { private fun <K, V> MutableMap<K, V>.putAbsentOrSame(key: K, value: V) {
val current = this.getOrPut(key, { value }) val current = this.getOrPut(key, { value })
@@ -605,11 +627,6 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
} }
} }
private fun recordRemappedParameter(oldDescriptor: ParameterDescriptor, newDescriptor: ParameterDescriptor) {
oldParameterToNew.putAbsentOrSame(oldDescriptor, newDescriptor)
newParameterToOld.putAbsentOrSame(newDescriptor, oldDescriptor)
}
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()
@@ -126,11 +126,10 @@ fun IrBuilderWithScope.irNot(arg: IrExpression) =
fun IrBuilderWithScope.irThrow(arg: IrExpression) = fun IrBuilderWithScope.irThrow(arg: IrExpression) =
IrThrowImpl(startOffset, endOffset, context.builtIns.nothingType, arg) IrThrowImpl(startOffset, endOffset, context.builtIns.nothingType, arg)
fun IrBuilderWithScope.irCatch(parameter: VariableDescriptor, result: IrExpression) = fun IrBuilderWithScope.irCatch(catchParameter: IrVariable) =
IrCatchImpl( IrCatchImpl(
startOffset, endOffset, startOffset, endOffset,
IrVariableImpl(startOffset, endOffset, IrDeclarationOrigin.CATCH_PARAMETER, parameter), catchParameter
result
) )
fun IrBuilderWithScope.irCast(arg: IrExpression, type: KotlinType, typeOperand: KotlinType) = fun IrBuilderWithScope.irCast(arg: IrExpression, type: KotlinType, typeOperand: KotlinType) =
@@ -16,22 +16,16 @@
package org.jetbrains.kotlin.backend.common.lower package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.backend.common.DeepCopyIrTreeWithDeclarations
import org.jetbrains.kotlin.backend.common.FunctionLoweringPass
import org.jetbrains.kotlin.backend.common.collectTailRecursionCalls
import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters
import org.jetbrains.kotlin.backend.common.descriptors.getOriginalParameter
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
import org.jetbrains.kotlin.descriptors.ValueDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.getDefault
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
import org.jetbrains.kotlin.ir.util.getArguments import org.jetbrains.kotlin.ir.util.explicitParameters
import org.jetbrains.kotlin.ir.util.getArgumentsWithSymbols
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -53,11 +47,10 @@ private fun lowerTailRecursionCalls(context: BackendContext, irFunction: IrFunct
return return
} }
val descriptor = irFunction.descriptor
val oldBody = irFunction.body as IrBlockBody val oldBody = irFunction.body as IrBlockBody
val builder = context.createIrBuilder(descriptor).at(oldBody) val builder = context.createIrBuilder(irFunction.symbol).at(oldBody)
val parameters = descriptor.explicitParameters val parameters = irFunction.explicitParameters
irFunction.body = builder.irBlockBody { irFunction.body = builder.irBlockBody {
// Define variables containing current values of parameters: // Define variables containing current values of parameters:
@@ -74,7 +67,7 @@ private fun lowerTailRecursionCalls(context: BackendContext, irFunction: IrFunct
// Read variables containing current values of parameters: // Read variables containing current values of parameters:
val parameterToNew = parameters.associate { val parameterToNew = parameters.associate {
val variable = parameterToVariable[it]!! val variable = parameterToVariable[it]!!
it to defineTemporary(irGet(variable), nameHint = it.suggestVariableName()) it to irTemporary(irGet(variable), nameHint = it.suggestVariableName()).symbol
} }
val transformer = BodyTransformer(builder, irFunction, loop, val transformer = BodyTransformer(builder, irFunction, loop,
@@ -94,16 +87,16 @@ private class BodyTransformer(
val builder: IrBuilderWithScope, val builder: IrBuilderWithScope,
val irFunction: IrFunction, val irFunction: IrFunction,
val loop: IrLoop, val loop: IrLoop,
val parameterToNew: Map<ParameterDescriptor, ValueDescriptor>, val parameterToNew: Map<IrValueParameterSymbol, IrValueSymbol>,
val parameterToVariable: Map<ParameterDescriptor, IrVariableSymbol>, val parameterToVariable: Map<IrValueParameterSymbol, IrVariableSymbol>,
val tailRecursionCalls: Set<IrCall> val tailRecursionCalls: Set<IrCall>
) : IrElementTransformerVoid() { ) : IrElementTransformerVoid() {
val parameters = irFunction.descriptor.explicitParameters val parameters = irFunction.explicitParameters
override fun visitGetValue(expression: IrGetValue): IrExpression { override fun visitGetValue(expression: IrGetValue): IrExpression {
expression.transformChildrenVoid(this) expression.transformChildrenVoid(this)
val value = parameterToNew[expression.descriptor] ?: return expression val value = parameterToNew[expression.symbol] ?: return expression
return builder.at(expression).irGet(value) return builder.at(expression).irGet(value)
} }
@@ -118,8 +111,8 @@ private class BodyTransformer(
private fun IrBuilderWithScope.genTailCall(expression: IrCall) = this.irBlock(expression) { private fun IrBuilderWithScope.genTailCall(expression: IrCall) = this.irBlock(expression) {
// Get all specified arguments: // Get all specified arguments:
val parameterToArgument = expression.getArguments().map { (parameter, argument) -> val parameterToArgument = expression.getArgumentsWithSymbols().map { (parameter, argument) ->
expression.descriptor.getOriginalParameter(parameter) to argument parameter to argument
} }
// For each specified argument set the corresponding variable to it in the correct order: // For each specified argument set the corresponding variable to it in the correct order:
@@ -135,15 +128,24 @@ 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 = irFunction.getDefaultArgumentExpression(parameter) ?: 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.transform(object : DeepCopyIrTreeWithDeclarations() { val defaultValue = originalDefaultValue
override fun mapValueReference(descriptor: ValueDescriptor): ValueDescriptor { .deepCopyWithVariables()
return parameterToVariable[descriptor]?.descriptor ?: super.mapValueReference(descriptor) .transform(object : IrElementTransformerVoid() {
}
}, data = null) override fun visitGetValue(expression: IrGetValue): IrExpression {
expression.transformChildrenVoid(this)
val variableSymbol = parameterToVariable[expression.symbol] ?: return expression
return IrGetValueImpl(
expression.startOffset, expression.endOffset,
variableSymbol, expression.origin
)
}
}, data = null)
+irSetVar(parameterToVariable[parameter]!!, defaultValue) +irSetVar(parameterToVariable[parameter]!!, defaultValue)
} }
@@ -153,23 +155,9 @@ private class BodyTransformer(
} }
} }
private fun IrFunction.getDefaultArgumentExpression(parameter: ParameterDescriptor): IrExpression? { private fun IrValueParameterSymbol.suggestVariableName(): String = if (descriptor.name.isSpecial) {
if (parameter !is ValueParameterDescriptor) { val oldNameStr = descriptor.name.asString()
return null
}
val body = this.getDefault(parameter) ?: return null
if (body !is IrExpressionBody) {
throw Error("unexpected default argument body: $body")
}
return body.expression
}
private fun ParameterDescriptor.suggestVariableName(): String = if (name.isSpecial) {
val oldNameStr = name.asString()
"$" + oldNameStr.substring(1, oldNameStr.length - 1) "$" + oldNameStr.substring(1, oldNameStr.length - 1)
} else { } else {
name.identifier descriptor.name.identifier
} }
@@ -32,15 +32,15 @@ import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.SourceManager import org.jetbrains.kotlin.ir.SourceManager
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScope
@@ -55,22 +55,34 @@ import java.util.*
import kotlin.LazyThreadSafetyMode.PUBLICATION import kotlin.LazyThreadSafetyMode.PUBLICATION
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
internal class SpecialDescriptorsFactory(val context: Context) { internal class SpecialDeclarationsFactory(val context: Context) {
private val enumSpecialDescriptorsFactory by lazy { EnumSpecialDescriptorsFactory(context) } private val enumSpecialDeclarationsFactory by lazy { EnumSpecialDeclarationsFactory(context) }
private val outerThisDescriptors = mutableMapOf<ClassDescriptor, PropertyDescriptor>() private val outerThisFields = mutableMapOf<ClassDescriptor, IrField>()
private val bridgesDescriptors = mutableMapOf<Pair<FunctionDescriptor, BridgeDirections>, FunctionDescriptor>() private val bridgesDescriptors = mutableMapOf<Pair<FunctionDescriptor, BridgeDirections>, FunctionDescriptor>()
private val loweredEnums = mutableMapOf<ClassDescriptor, LoweredEnum>() private val loweredEnums = mutableMapOf<ClassDescriptor, LoweredEnum>()
fun getOuterThisFieldDescriptor(innerClassDescriptor: ClassDescriptor): PropertyDescriptor = object DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS :
IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS")
fun getOuterThisField(innerClassDescriptor: ClassDescriptor): IrField =
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 outerThisFields.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")
val receiver = ReceiverParameterDescriptorImpl(innerClassDescriptor, ImplicitClassReceiver(innerClassDescriptor)) val receiver = ReceiverParameterDescriptorImpl(innerClassDescriptor, ImplicitClassReceiver(innerClassDescriptor))
PropertyDescriptorImpl.create(innerClassDescriptor, Annotations.EMPTY, Modality.FINAL, Visibilities.PRIVATE, val descriptor = PropertyDescriptorImpl.create(
false, "this$0".synthesizedName, CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE, innerClassDescriptor, Annotations.EMPTY, Modality.FINAL,
false, false, false, false, false, false).initialize(outerClassDescriptor.defaultType, dispatchReceiverParameter = receiver) Visibilities.PRIVATE, false, "this$0".synthesizedName, CallableMemberDescriptor.Kind.SYNTHESIZED,
SourceElement.NO_SOURCE, false, false, false, false, false, false
).initialize(outerClassDescriptor.defaultType, dispatchReceiverParameter = receiver)
IrFieldImpl(
innerClassDescriptor.startOffsetOrUndefined,
innerClassDescriptor.endOffsetOrUndefined,
DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS,
descriptor
)
} }
fun getBridgeDescriptor(overriddenFunctionDescriptor: OverriddenFunctionDescriptor): FunctionDescriptor { fun getBridgeDescriptor(overriddenFunctionDescriptor: OverriddenFunctionDescriptor): FunctionDescriptor {
@@ -93,7 +105,7 @@ internal class SpecialDescriptorsFactory(val context: Context) {
fun getLoweredEnum(enumClassDescriptor: ClassDescriptor): LoweredEnum { fun getLoweredEnum(enumClassDescriptor: ClassDescriptor): LoweredEnum {
assert(enumClassDescriptor.kind == ClassKind.ENUM_CLASS, { "Expected enum class but was: $enumClassDescriptor" }) assert(enumClassDescriptor.kind == ClassKind.ENUM_CLASS, { "Expected enum class but was: $enumClassDescriptor" })
return loweredEnums.getOrPut(enumClassDescriptor) { return loweredEnums.getOrPut(enumClassDescriptor) {
enumSpecialDescriptorsFactory.createLoweredEnum(enumClassDescriptor) enumSpecialDeclarationsFactory.createLoweredEnum(enumClassDescriptor)
} }
} }
@@ -219,7 +231,7 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
override val builtIns: KonanBuiltIns by lazy(PUBLICATION) { moduleDescriptor.builtIns as KonanBuiltIns } override val builtIns: KonanBuiltIns by lazy(PUBLICATION) { moduleDescriptor.builtIns as KonanBuiltIns }
val specialDescriptorsFactory = SpecialDescriptorsFactory(this) val specialDeclarationsFactory = SpecialDeclarationsFactory(this)
val reflectionTypes: ReflectionTypes by lazy(PUBLICATION) { ReflectionTypes(moduleDescriptor) } val reflectionTypes: ReflectionTypes by lazy(PUBLICATION) { ReflectionTypes(moduleDescriptor) }
private val vtableBuilders = mutableMapOf<ClassDescriptor, ClassVtablesBuilder>() private val vtableBuilders = mutableMapOf<ClassDescriptor, ClassVtablesBuilder>()
@@ -233,6 +245,9 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
// to dump this information into generated file. // to dump this information into generated file.
var serializedLinkData: LinkData? = null var serializedLinkData: LinkData? = null
@Deprecated("")
lateinit var psi2IrGeneratorContext: GeneratorContext
// TODO: make lateinit? // TODO: make lateinit?
var irModule: IrModuleFragment? = null var irModule: IrModuleFragment? = null
set(module: IrModuleFragment?) { set(module: IrModuleFragment?) {
@@ -244,7 +259,7 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
ir = Ir(this, module) ir = Ir(this, module)
} }
lateinit var ir: Ir override lateinit var ir: Ir
override val irBuiltIns override val irBuiltIns
get() = ir.irModule.irBuiltins get() = ir.irModule.irBuiltins
@@ -22,7 +22,13 @@ import org.jetbrains.kotlin.backend.konan.ir.createSimpleDelegatingConstructorDe
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.* import org.jetbrains.kotlin.descriptors.impl.*
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.*
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
import org.jetbrains.kotlin.ir.util.endOffsetOrUndefined
import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.startOffsetOrUndefined
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.resolve.scopes.MemberScope
@@ -32,19 +38,33 @@ import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.replace import org.jetbrains.kotlin.types.replace
internal data class LoweredEnum(val implObjectDescriptor: ClassDescriptor,
val valuesProperty: PropertyDescriptor, internal object DECLARATION_ORIGIN_ENUM :
val valuesGetter: FunctionDescriptor, IrDeclarationOriginImpl("ENUM")
val itemGetter: FunctionDescriptor,
internal data class LoweredEnum(val implObject: IrClass,
val valuesField: IrField,
val valuesGetter: IrSimpleFunction,
val itemGetterSymbol: IrFunctionSymbol,
val itemGetterDescriptor: FunctionDescriptor,
val entriesMap: Map<Name, Int>) val entriesMap: Map<Name, Int>)
internal class EnumSpecialDescriptorsFactory(val context: Context) { internal class EnumSpecialDeclarationsFactory(val context: Context) {
fun createLoweredEnum(enumClassDescriptor: ClassDescriptor): LoweredEnum { fun createLoweredEnum(enumClassDescriptor: ClassDescriptor): LoweredEnum {
val startOffset = enumClassDescriptor.startOffsetOrUndefined
val endOffset = enumClassDescriptor.endOffsetOrUndefined
val implObjectDescriptor = ClassDescriptorImpl(enumClassDescriptor, "OBJECT".synthesizedName, Modality.FINAL, val implObjectDescriptor = ClassDescriptorImpl(enumClassDescriptor, "OBJECT".synthesizedName, Modality.FINAL,
ClassKind.OBJECT, listOf(context.builtIns.anyType), SourceElement.NO_SOURCE, false) ClassKind.OBJECT, listOf(context.builtIns.anyType), SourceElement.NO_SOURCE, false)
val valuesProperty = createEnumValuesField(enumClassDescriptor, implObjectDescriptor) val valuesProperty = createEnumValuesField(enumClassDescriptor, implObjectDescriptor)
val valuesGetter = createValuesGetterDescriptor(enumClassDescriptor, implObjectDescriptor) val valuesField = IrFieldImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, valuesProperty)
val valuesGetterDescriptor = createValuesGetterDescriptor(enumClassDescriptor, implObjectDescriptor)
val valuesGetter = IrFunctionImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, valuesGetterDescriptor).apply {
createParameterDeclarations()
}
val memberScope = MemberScope.Empty val memberScope = MemberScope.Empty
@@ -53,9 +73,18 @@ internal class EnumSpecialDescriptorsFactory(val context: Context) {
val constructorDescriptor = implObjectDescriptor.createSimpleDelegatingConstructorDescriptor(constructorOfAny, true) val constructorDescriptor = implObjectDescriptor.createSimpleDelegatingConstructorDescriptor(constructorOfAny, true)
implObjectDescriptor.initialize(memberScope, setOf(constructorDescriptor), constructorDescriptor) implObjectDescriptor.initialize(memberScope, setOf(constructorDescriptor), constructorDescriptor)
val implObject = IrClassImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, implObjectDescriptor).apply {
createParameterDeclarations()
}
return LoweredEnum(implObjectDescriptor, valuesProperty, valuesGetter, val (itemGetterSymbol, itemGetterDescriptor) = getEnumItemGetter(enumClassDescriptor)
getEnumItemGetter(enumClassDescriptor), createEnumEntriesMap(enumClassDescriptor))
return LoweredEnum(
implObject,
valuesField,
valuesGetter,
itemGetterSymbol, itemGetterDescriptor,
createEnumEntriesMap(enumClassDescriptor))
} }
private fun createValuesGetterDescriptor(enumClassDescriptor: ClassDescriptor, implObjectDescriptor: ClassDescriptor) private fun createValuesGetterDescriptor(enumClassDescriptor: ClassDescriptor, implObjectDescriptor: ClassDescriptor)
@@ -87,15 +116,15 @@ internal class EnumSpecialDescriptorsFactory(val context: Context) {
} }
private val kotlinPackage = context.irModule!!.descriptor.getPackage(FqName("kotlin")) private val kotlinPackage = context.irModule!!.descriptor.getPackage(FqName("kotlin"))
private val genericArrayType = kotlinPackage.memberScope.getContributedClassifier(Name.identifier("Array"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor private val genericArrayType = context.ir.symbols.array.descriptor
private fun getEnumItemGetter(enumClassDescriptor: ClassDescriptor): FunctionDescriptor { private fun getEnumItemGetter(enumClassDescriptor: ClassDescriptor): Pair<IrFunctionSymbol, FunctionDescriptor> {
val getter = genericArrayType.unsubstitutedMemberScope.getContributedFunctions(Name.identifier("get"), NoLookupLocation.FROM_BACKEND).single() val getter = context.ir.symbols.array.functions.single { it.descriptor.name == Name.identifier("get") }
val typeParameterT = genericArrayType.declaredTypeParameters[0] val typeParameterT = genericArrayType.declaredTypeParameters[0]
val enumClassType = enumClassDescriptor.defaultType val enumClassType = enumClassDescriptor.defaultType
val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(enumClassType))) val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(enumClassType)))
return getter.substitute(typeSubstitutor)!! return getter to getter.descriptor.substitute(typeSubstitutor)!!
} }
private fun createEnumEntriesMap(enumClassDescriptor: ClassDescriptor): Map<Name, Int> { private fun createEnumEntriesMap(enumClassDescriptor: ClassDescriptor): Map<Name, Int> {
@@ -18,13 +18,16 @@ package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.backend.common.BackendContext import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.konan.descriptors.KonanSharedVariablesManager import org.jetbrains.kotlin.backend.konan.descriptors.KonanSharedVariablesManager
import org.jetbrains.kotlin.backend.konan.ir.Ir
abstract internal class KonanBackendContext(val config: KonanConfig) : BackendContext { abstract internal class KonanBackendContext(val config: KonanConfig) : BackendContext {
abstract override val builtIns: KonanBuiltIns abstract override val builtIns: KonanBuiltIns
abstract val ir: Ir
override val sharedVariablesManager by lazy { override val sharedVariablesManager by lazy {
// Creating lazily because builtIns module seems to be incomplete during `link` test; // Creating lazily because builtIns module seems to be incomplete during `link` test;
// TODO: investigate this. // TODO: investigate this.
KonanSharedVariablesManager(builtIns) KonanSharedVariablesManager(this)
} }
} }
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.backend.common.messageCollector
import org.jetbrains.kotlin.backend.common.validateIrModule import org.jetbrains.kotlin.backend.common.validateIrModule
import org.jetbrains.kotlin.backend.konan.ir.DeserializerDriver import org.jetbrains.kotlin.backend.konan.ir.DeserializerDriver
import org.jetbrains.kotlin.backend.konan.ir.ModuleIndex import org.jetbrains.kotlin.backend.konan.ir.ModuleIndex
import org.jetbrains.kotlin.backend.konan.ir.Symbols
import org.jetbrains.kotlin.backend.konan.llvm.emitLLVM import org.jetbrains.kotlin.backend.konan.llvm.emitLLVM
import org.jetbrains.kotlin.backend.konan.serialization.KonanSerializationUtil import org.jetbrains.kotlin.backend.konan.serialization.KonanSerializationUtil
import org.jetbrains.kotlin.backend.konan.serialization.markBackingFields import org.jetbrains.kotlin.backend.konan.serialization.markBackingFields
@@ -81,10 +82,15 @@ public fun runTopLevelPhases(konanConfig: KonanConfig, environment: KotlinCoreEn
phaser.phase(KonanPhase.PSI_TO_IR) { phaser.phase(KonanPhase.PSI_TO_IR) {
// Translate AST to high level IR. // Translate AST to high level IR.
val translator = Psi2IrTranslator(Psi2IrConfiguration(false)) val translator = Psi2IrTranslator(Psi2IrConfiguration(false))
val module = translator.generateModule(context.moduleDescriptor, val generatorContext = translator.createGeneratorContext(context.moduleDescriptor, bindingContext)
environment.getSourceFiles(), bindingContext) context.psi2IrGeneratorContext = generatorContext
val symbols = Symbols(context, generatorContext.symbolTable)
val module = translator.generateModuleFragment(generatorContext, environment.getSourceFiles())
context.irModule = module context.irModule = module
context.ir.symbols = symbols
validateIrModule(context, module) validateIrModule(context, module)
} }
@@ -20,8 +20,12 @@ import org.jetbrains.kotlin.backend.common.runOnFilePostfix
import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.common.lower.*
import org.jetbrains.kotlin.backend.common.validateIrFile import org.jetbrains.kotlin.backend.common.validateIrFile
import org.jetbrains.kotlin.backend.konan.lower.* import org.jetbrains.kotlin.backend.konan.lower.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.util.IrSymbolBindingChecker
import org.jetbrains.kotlin.ir.util.replaceUnboundSymbols
import org.jetbrains.kotlin.ir.visitors.acceptVoid
internal class KonanLower(val context: Context) { internal class KonanLower(val context: Context) {
@@ -45,6 +49,8 @@ internal class KonanLower(val context: Context) {
// Inlining must be run before other phases. // Inlining must be run before other phases.
phaser.phase(KonanPhase.LOWER_INLINE) { phaser.phase(KonanPhase.LOWER_INLINE) {
FunctionInlining(context).inline(irModule) FunctionInlining(context).inline(irModule)
irModule.replaceUnboundSymbols(context)
irModule.checkSymbolsBound()
} }
} }
@@ -53,24 +59,31 @@ internal class KonanLower(val context: Context) {
phaser.phase(KonanPhase.LOWER_STRING_CONCAT) { phaser.phase(KonanPhase.LOWER_STRING_CONCAT) {
StringConcatenationLowering(context).lower(irFile) StringConcatenationLowering(context).lower(irFile)
irFile.checkSymbolsBound()
} }
phaser.phase(KonanPhase.LOWER_ENUMS) { phaser.phase(KonanPhase.LOWER_ENUMS) {
EnumClassLowering(context).run(irFile) EnumClassLowering(context).run(irFile)
irFile.checkSymbolsBound()
} }
phaser.phase(KonanPhase.LOWER_INITIALIZERS) { phaser.phase(KonanPhase.LOWER_INITIALIZERS) {
InitializersLowering(context).runOnFilePostfix(irFile) InitializersLowering(context).runOnFilePostfix(irFile)
irFile.checkSymbolsBound()
} }
phaser.phase(KonanPhase.LOWER_SHARED_VARIABLES) { phaser.phase(KonanPhase.LOWER_SHARED_VARIABLES) {
SharedVariablesLowering(context).runOnFilePostfix(irFile) SharedVariablesLowering(context).runOnFilePostfix(irFile)
irFile.checkSymbolsBound()
} }
phaser.phase(KonanPhase.LOWER_DELEGATION) { phaser.phase(KonanPhase.LOWER_DELEGATION) {
PropertyDelegationLowering(context).lower(irFile) PropertyDelegationLowering(context).lower(irFile)
irFile.checkSymbolsBound()
} }
phaser.phase(KonanPhase.LOWER_LOCAL_FUNCTIONS) { phaser.phase(KonanPhase.LOWER_LOCAL_FUNCTIONS) {
LocalDeclarationsLowering(context).runOnFilePostfix(irFile) LocalDeclarationsLowering(context).runOnFilePostfix(irFile)
irFile.checkSymbolsBound()
} }
phaser.phase(KonanPhase.LOWER_TAILREC) { phaser.phase(KonanPhase.LOWER_TAILREC) {
TailrecLowering(context).runOnFilePostfix(irFile) TailrecLowering(context).runOnFilePostfix(irFile)
irFile.checkSymbolsBound()
} }
phaser.phase(KonanPhase.LOWER_FINALLY) { phaser.phase(KonanPhase.LOWER_FINALLY) {
FinallyBlocksLowering(context).runOnFilePostfix(irFile) FinallyBlocksLowering(context).runOnFilePostfix(irFile)
@@ -112,4 +125,10 @@ internal class KonanLower(val context: Context) {
Autoboxing(context).lower(irFile) Autoboxing(context).lower(irFile)
} }
} }
private fun IrElement.checkSymbolsBound() {
if (context.shouldVerifyIr()) {
this.acceptVoid(IrSymbolBindingChecker())
}
}
} }
@@ -18,12 +18,14 @@ package org.jetbrains.kotlin.backend.konan.descriptors
import org.jetbrains.kotlin.backend.common.descriptors.SharedVariablesManager import org.jetbrains.kotlin.backend.common.descriptors.SharedVariablesManager
import org.jetbrains.kotlin.backend.konan.KonanBuiltIns import org.jetbrains.kotlin.backend.konan.KonanBackendContext
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
@@ -32,24 +34,33 @@ import org.jetbrains.kotlin.ir.expressions.IrSetVariable
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.*
internal class KonanSharedVariablesManager(val builtIns: KonanBuiltIns) : SharedVariablesManager { internal class KonanSharedVariablesManager(val context: KonanBackendContext) : SharedVariablesManager {
private val refClass = builtIns.getKonanInternalClass("Ref") private val refClass = context.ir.symbols.refClass
private val refClassConstructor = refClass.unsubstitutedPrimaryConstructor!! private val refClassConstructor = refClass.constructors.single()
private val elementProperty = refClass.owner.declarations.filterIsInstance<IrProperty>().single()
// TODO: refactor `SharedVariablesManager` interface instead of tracking the mapping:
private val sharedVariableDescriptorToSymbol = mutableMapOf<VariableDescriptor, IrVariableSymbol>()
private fun refConstructor(elementType: KotlinType): ClassConstructorDescriptor { private fun refConstructor(elementType: KotlinType): ClassConstructorDescriptor {
val typeParameter = refClassConstructor.typeParameters[0] val typeParameter = refClassConstructor.descriptor.typeParameters[0]
return refClassConstructor.substitute(TypeSubstitutor.create( return refClassConstructor.descriptor.substitute(TypeSubstitutor.create(
mapOf(typeParameter.typeConstructor to TypeProjectionImpl(Variance.INVARIANT, elementType)) mapOf(typeParameter.typeConstructor to TypeProjectionImpl(Variance.INVARIANT, elementType))
))!! ))!!
} }
private fun refType(elementType: KotlinType): KotlinType { private fun refType(elementType: KotlinType): KotlinType {
return refClass.defaultType.replace(listOf(TypeProjectionImpl(elementType))) return refClass.owner.defaultType.replace(listOf(TypeProjectionImpl(elementType)))
} }
override fun createSharedVariableDescriptor(variableDescriptor: VariableDescriptor): VariableDescriptor { override fun createSharedVariableDescriptor(variableDescriptor: VariableDescriptor): VariableDescriptor {
@@ -57,10 +68,12 @@ internal class KonanSharedVariablesManager(val builtIns: KonanBuiltIns) : Shared
variableDescriptor.containingDeclaration, variableDescriptor.annotations, variableDescriptor.name, variableDescriptor.containingDeclaration, variableDescriptor.annotations, variableDescriptor.name,
refType(variableDescriptor.type), refType(variableDescriptor.type),
false, false, variableDescriptor.source false, false, variableDescriptor.source
) ).also {
sharedVariableDescriptorToSymbol[it] = IrVariableSymbolImpl(it)
}
} }
private fun getElementProperty(sharedVariableDescriptor: VariableDescriptor): PropertyDescriptor { private fun getElementPropertyDescriptor(sharedVariableDescriptor: VariableDescriptor): PropertyDescriptor {
return sharedVariableDescriptor.type.memberScope.getContributedDescriptors() return sharedVariableDescriptor.type.memberScope.getContributedDescriptors()
.filterIsInstance<PropertyDescriptor>() .filterIsInstance<PropertyDescriptor>()
.single { .single {
@@ -71,49 +84,62 @@ internal class KonanSharedVariablesManager(val builtIns: KonanBuiltIns) : Shared
override fun defineSharedValue(sharedVariableDescriptor: VariableDescriptor, override fun defineSharedValue(sharedVariableDescriptor: VariableDescriptor,
originalDeclaration: IrVariable): IrStatement { originalDeclaration: IrVariable): IrStatement {
val sharedVariableSymbol = sharedVariableDescriptorToSymbol[sharedVariableDescriptor]!!
val valueType = originalDeclaration.descriptor.type val valueType = originalDeclaration.descriptor.type
val refConstructorTypeArguments = mapOf(refClassConstructor.typeParameters[0] to valueType) val refConstructorTypeArguments = mapOf(refClassConstructor.descriptor.typeParameters[0] to valueType)
val refConstructorCall = IrCallImpl( val refConstructorCall = IrCallImpl(
originalDeclaration.startOffset, originalDeclaration.endOffset, originalDeclaration.startOffset, originalDeclaration.endOffset,
refConstructor(valueType), refConstructorTypeArguments refClassConstructor, refConstructor(valueType), refConstructorTypeArguments
) )
val sharedVariableDeclaration = IrVariableImpl( val sharedVariableDeclaration = IrVariableImpl(
originalDeclaration.startOffset, originalDeclaration.endOffset, originalDeclaration.origin, originalDeclaration.startOffset, originalDeclaration.endOffset, originalDeclaration.origin,
sharedVariableDescriptor, refConstructorCall sharedVariableSymbol
) ).apply {
initializer = refConstructorCall
}
val initializer = originalDeclaration.initializer ?: val initializer = originalDeclaration.initializer ?:
return sharedVariableDeclaration return sharedVariableDeclaration
val elementProperty = getElementProperty(sharedVariableDescriptor) val elementPropertyDescriptor = getElementPropertyDescriptor(sharedVariableDescriptor)
val sharedVariableInitialization = val sharedVariableInitialization =
IrCallImpl(initializer.startOffset, initializer.endOffset, elementProperty.setter!!) IrCallImpl(initializer.startOffset, initializer.endOffset, elementProperty.setter!!.symbol,
elementPropertyDescriptor.setter!!)
sharedVariableInitialization.dispatchReceiver = sharedVariableInitialization.dispatchReceiver =
IrGetValueImpl(initializer.startOffset, initializer.endOffset, sharedVariableDescriptor) IrGetValueImpl(initializer.startOffset, initializer.endOffset, sharedVariableSymbol)
sharedVariableInitialization.putValueArgument(0, initializer) sharedVariableInitialization.putValueArgument(0, initializer)
return IrCompositeImpl( return IrCompositeImpl(
originalDeclaration.startOffset, originalDeclaration.endOffset, builtIns.unitType, null, originalDeclaration.startOffset, originalDeclaration.endOffset, context.builtIns.unitType, null,
listOf(sharedVariableDeclaration, sharedVariableInitialization) listOf(sharedVariableDeclaration, sharedVariableInitialization)
) )
} }
override fun getSharedValue(sharedVariableDescriptor: VariableDescriptor, originalGet: IrGetValue): IrExpression { override fun getSharedValue(sharedVariableDescriptor: VariableDescriptor, originalGet: IrGetValue): IrExpression {
val elementProperty = getElementProperty(sharedVariableDescriptor) val sharedVariableSymbol = sharedVariableDescriptorToSymbol[sharedVariableDescriptor]!!
return IrCallImpl(originalGet.startOffset, originalGet.endOffset, elementProperty.getter!!).apply {
dispatchReceiver = IrGetValueImpl(originalGet.startOffset, originalGet.endOffset, sharedVariableDescriptor) val elementPropertyDescriptor = getElementPropertyDescriptor(sharedVariableDescriptor)
return IrCallImpl(originalGet.startOffset, originalGet.endOffset, elementProperty.getter!!.symbol,
elementPropertyDescriptor.getter!!).apply {
dispatchReceiver = IrGetValueImpl(originalGet.startOffset, originalGet.endOffset, sharedVariableSymbol)
} }
} }
override fun setSharedValue(sharedVariableDescriptor: VariableDescriptor, originalSet: IrSetVariable): IrExpression { override fun setSharedValue(sharedVariableDescriptor: VariableDescriptor, originalSet: IrSetVariable): IrExpression {
val elementProperty = getElementProperty(sharedVariableDescriptor) val sharedVariableSymbol = sharedVariableDescriptorToSymbol[sharedVariableDescriptor]!!
return IrCallImpl(originalSet.startOffset, originalSet.endOffset, elementProperty.setter!!).apply {
dispatchReceiver = IrGetValueImpl(originalSet.startOffset, originalSet.endOffset, sharedVariableDescriptor) val elementPropertyDescriptor = getElementPropertyDescriptor(sharedVariableDescriptor)
return IrCallImpl(originalSet.startOffset, originalSet.endOffset, elementProperty.setter!!.symbol,
elementPropertyDescriptor.setter!!).apply {
dispatchReceiver = IrGetValueImpl(originalSet.startOffset, originalSet.endOffset, sharedVariableSymbol)
putValueArgument(0, originalSet.value) putValueArgument(0, originalSet.value)
} }
} }
@@ -17,10 +17,18 @@
package org.jetbrains.kotlin.backend.konan.ir package org.jetbrains.kotlin.backend.konan.ir
import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.KonanBuiltIns
import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalClass
import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalFunctions
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi2ir.generators.SymbolTable
// This is what Context collects about IR. // This is what Context collects about IR.
internal class Ir(val context: Context, val irModule: IrModuleFragment) { internal class Ir(val context: Context, val irModule: IrModuleFragment) {
@@ -31,4 +39,63 @@ internal class Ir(val context: Context, val irModule: IrModuleFragment) {
val originalModuleIndex = ModuleIndex(irModule) val originalModuleIndex = ModuleIndex(irModule)
lateinit var moduleIndexForCodegen: ModuleIndex lateinit var moduleIndexForCodegen: ModuleIndex
lateinit var symbols: Symbols
} }
internal class Symbols(val context: Context, val symbolTable: SymbolTable) {
val builtIns: KonanBuiltIns get() = context.builtIns
private fun builtInsPackage(vararg packageNameSegments: String) =
builtIns.builtInsModule.getPackage(FqName.fromSegments(listOf(*packageNameSegments))).memberScope
val refClass = symbolTable.referenceClass(builtIns.getKonanInternalClass("Ref"))
val areEqualByValue = builtIns.getKonanInternalFunctions("areEqualByValue").map {
symbolTable.referenceSimpleFunction(it)
}
val areEqual = symbolTable.referenceSimpleFunction(builtIns.getKonanInternalFunctions("areEqual").single())
val ThrowNullPointerException = symbolTable.referenceSimpleFunction(
builtIns.getKonanInternalFunctions("ThrowNullPointerException").single())
val ThrowNoWhenBranchMatchedException = symbolTable.referenceSimpleFunction(
builtIns.getKonanInternalFunctions("ThrowNoWhenBranchMatchedException").single())
val ThrowTypeCastException = symbolTable.referenceSimpleFunction(
builtIns.getKonanInternalFunctions("ThrowTypeCastException").single())
val stringBuilder = symbolTable.referenceClass(
builtInsPackage("kotlin", "text").getContributedClassifier(
Name.identifier("StringBuilder"), NoLookupLocation.FROM_BACKEND
) as ClassDescriptor
)
val any = symbolTable.referenceClass(builtIns.any)
val arrayOf = symbolTable.referenceSimpleFunction(
builtInsPackage("kotlin").getContributedFunctions(
Name.identifier("arrayOf"), NoLookupLocation.FROM_BACKEND
).single()
)
val array = symbolTable.referenceClass(builtIns.array)
val valuesForEnum = symbolTable.referenceSimpleFunction(
builtIns.getKonanInternalFunctions("valuesForEnum").single())
val valueOfForEnum = symbolTable.referenceSimpleFunction(
builtIns.getKonanInternalFunctions("valueOfForEnum").single())
val kProperty0Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty0Impl)
val kProperty1Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty1Impl)
val kProperty2Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty2Impl)
val kMutableProperty0Impl = symbolTable.referenceClass(context.reflectionTypes.kMutableProperty0Impl)
val kMutableProperty1Impl = symbolTable.referenceClass(context.reflectionTypes.kMutableProperty1Impl)
val kMutableProperty2Impl = symbolTable.referenceClass(context.reflectionTypes.kMutableProperty2Impl)
val kLocalDelegatedPropertyImpl = symbolTable.referenceClass(context.reflectionTypes.kLocalDelegatedPropertyImpl)
val kLocalDelegatedMutablePropertyImpl = symbolTable.referenceClass(context.reflectionTypes.kLocalDelegatedMutablePropertyImpl)
}
@@ -20,17 +20,16 @@ import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
import org.jetbrains.kotlin.ir.util.createParameterDeclarations import org.jetbrains.kotlin.ir.util.createParameterDeclarations
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeProjectionImpl import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.types.TypeSubstitutor
@@ -91,30 +90,38 @@ internal fun ClassDescriptor.createSimpleDelegatingConstructorDescriptor(superCo
return constructorDescriptor return constructorDescriptor
} }
internal fun ClassDescriptor.createSimpleDelegatingConstructor(superConstructorDescriptor: ClassConstructorDescriptor, internal fun IrClass.addSimpleDelegatingConstructor(superConstructorSymbol: IrConstructorSymbol,
constructorDescriptor: ClassConstructorDescriptor, constructorDescriptor: ClassConstructorDescriptor,
startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin) origin: IrDeclarationOrigin)
: IrConstructor { : IrConstructor {
val body = IrBlockBodyImpl(startOffset, endOffset,
listOf( return IrConstructorImpl(startOffset, endOffset, origin, constructorDescriptor).also { constructor ->
IrDelegatingConstructorCallImpl(startOffset, endOffset, superConstructorDescriptor).apply { constructor.createParameterDeclarations()
constructorDescriptor.valueParameters.forEachIndexed { idx, parameter ->
putValueArgument(idx, IrGetValueImpl(startOffset, endOffset, parameter)) constructor.body = IrBlockBodyImpl(startOffset, endOffset,
} listOf(
}, IrDelegatingConstructorCallImpl(
IrInstanceInitializerCallImpl(startOffset, endOffset, this) startOffset, endOffset,
) superConstructorSymbol, superConstructorSymbol.descriptor
) ).apply {
return IrConstructorImpl(startOffset, endOffset, origin, constructorDescriptor, body).apply { constructor.valueParameters.forEachIndexed { idx, parameter ->
createParameterDeclarations() putValueArgument(idx, IrGetValueImpl(startOffset, endOffset, parameter.symbol))
}
},
IrInstanceInitializerCallImpl(startOffset, endOffset, this.symbol)
)
)
this.declarations.add(constructor)
} }
} }
internal fun Context.createArrayOfExpression(arrayElementType: KotlinType, internal fun Context.createArrayOfExpression(arrayElementType: KotlinType,
arrayElements: List<IrExpression>, arrayElements: List<IrExpression>,
startOffset: Int, endOffset: Int): IrExpression { startOffset: Int, endOffset: Int): IrExpression {
val kotlinPackage = irModule!!.descriptor.getPackage(FqName("kotlin"))
val genericArrayOfFun = kotlinPackage.memberScope.getContributedFunctions(Name.identifier("arrayOf"), NoLookupLocation.FROM_BACKEND).first() val genericArrayOfFunSymbol = ir.symbols.arrayOf
val genericArrayOfFun = genericArrayOfFunSymbol.descriptor
val typeParameter0 = genericArrayOfFun.typeParameters[0] val typeParameter0 = genericArrayOfFun.typeParameters[0]
val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameter0.typeConstructor to TypeProjectionImpl(arrayElementType))) val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameter0.typeConstructor to TypeProjectionImpl(arrayElementType)))
val substitutedArrayOfFun = genericArrayOfFun.substitute(typeSubstitutor)!! val substitutedArrayOfFun = genericArrayOfFun.substitute(typeSubstitutor)!!
@@ -126,7 +133,7 @@ internal fun Context.createArrayOfExpression(arrayElementType: KotlinType,
val arg0VarargElementType = valueParameter0.varargElementType!! val arg0VarargElementType = valueParameter0.varargElementType!!
val arg0 = IrVarargImpl(startOffset, endOffset, arg0VarargType, arg0VarargElementType, arrayElements) val arg0 = IrVarargImpl(startOffset, endOffset, arg0VarargType, arg0VarargElementType, arrayElements)
return IrCallImpl(startOffset, endOffset, substitutedArrayOfFun, typeArguments).apply { return IrCallImpl(startOffset, endOffset, genericArrayOfFunSymbol, substitutedArrayOfFun, typeArguments).apply {
putValueArgument(0, arg0) putValueArgument(0, arg0)
} }
} }
@@ -16,33 +16,55 @@
package org.jetbrains.kotlin.backend.konan.ir package org.jetbrains.kotlin.backend.konan.ir
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner
import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.IrBlock import org.jetbrains.kotlin.ir.expressions.IrBlock
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.IrContainerExpressionBase import org.jetbrains.kotlin.ir.expressions.impl.IrContainerExpressionBase
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBase import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBase
import org.jetbrains.kotlin.ir.symbols.IrBindableSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrBindableSymbolBase
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
//-----------------------------------------------------------------------------// //-----------------------------------------------------------------------------//
interface IrReturnableBlock: IrBlock { interface IrReturnableBlockSymbol : IrFunctionSymbol, IrBindableSymbol<FunctionDescriptor, IrReturnableBlock>
val descriptor: CallableDescriptor
interface IrReturnableBlock: IrBlock, IrSymbolOwner {
override val symbol: IrReturnableBlockSymbol
val descriptor: FunctionDescriptor
} }
class IrReturnableBlockSymbolImpl(descriptor: FunctionDescriptor) :
IrBindableSymbolBase<FunctionDescriptor, IrReturnableBlock>(descriptor),
IrReturnableBlockSymbol
class IrReturnableBlockImpl(startOffset: Int, endOffset: Int, type: KotlinType, class IrReturnableBlockImpl(startOffset: Int, endOffset: Int, type: KotlinType,
override val descriptor: CallableDescriptor, origin: IrStatementOrigin? = null) override val symbol: IrReturnableBlockSymbol, origin: IrStatementOrigin? = null)
: IrContainerExpressionBase(startOffset, endOffset, type, origin), IrReturnableBlock { : IrContainerExpressionBase(startOffset, endOffset, type, origin), IrReturnableBlock {
override val descriptor = symbol.descriptor
constructor(startOffset: Int, endOffset: Int, type: KotlinType, constructor(startOffset: Int, endOffset: Int, type: KotlinType,
descriptor: CallableDescriptor, origin: IrStatementOrigin?, statements: List<IrStatement>) : descriptor: FunctionDescriptor, origin: IrStatementOrigin? = null) :
this(startOffset, endOffset, type, IrReturnableBlockSymbolImpl(descriptor), origin)
constructor(startOffset: Int, endOffset: Int, type: KotlinType,
descriptor: FunctionDescriptor, origin: IrStatementOrigin?, statements: List<IrStatement>) :
this(startOffset, endOffset, type, descriptor, origin) { this(startOffset, endOffset, type, descriptor, origin) {
this.statements.addAll(statements) this.statements.addAll(statements)
} }
init {
symbol.bind(this)
}
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R = override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
visitor.visitBlock(this, data) visitor.visitBlock(this, data)
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.backend.konan.descriptors.*
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.OverridingUtil
import org.jetbrains.kotlin.resolve.constants.StringValue import org.jetbrains.kotlin.resolve.constants.StringValue
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
@@ -191,6 +190,6 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
} else { } else {
descriptor descriptor
} }
return context.specialDescriptorsFactory.getBridgeDescriptor(OverriddenFunctionDescriptor(bridgeOwner, overriddenDescriptor)) return context.specialDeclarationsFactory.getBridgeDescriptor(OverriddenFunctionDescriptor(bridgeOwner, overriddenDescriptor))
} }
} }
@@ -112,7 +112,7 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
IrDeclarationOriginImpl("BRIDGE_METHOD") IrDeclarationOriginImpl("BRIDGE_METHOD")
private fun buildBridge(descriptor: OverriddenFunctionDescriptor, irClass: IrClass) { private fun buildBridge(descriptor: OverriddenFunctionDescriptor, irClass: IrClass) {
val bridgeDescriptor = context.specialDescriptorsFactory.getBridgeDescriptor(descriptor) val bridgeDescriptor = context.specialDeclarationsFactory.getBridgeDescriptor(descriptor)
val target = descriptor.descriptor.target val target = descriptor.descriptor.target
val delegatingCall = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, target, val delegatingCall = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, target,
@@ -19,17 +19,15 @@ package org.jetbrains.kotlin.backend.konan.lower
import org.jetbrains.kotlin.backend.common.BodyLoweringPass import org.jetbrains.kotlin.backend.common.BodyLoweringPass
import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.KonanConfigKeys.Companion.ENABLE_ASSERTIONS import org.jetbrains.kotlin.backend.konan.KonanConfigKeys.Companion.ENABLE_ASSERTIONS
import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalFunctions
import org.jetbrains.kotlin.backend.konan.isValueType import org.jetbrains.kotlin.backend.konan.isValueType
import org.jetbrains.kotlin.backend.konan.util.atMostOne import org.jetbrains.kotlin.backend.konan.util.atMostOne
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.ir.descriptors.IrBuiltinOperatorDescriptor import org.jetbrains.kotlin.ir.descriptors.IrBuiltinOperatorDescriptor
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrBinaryPrimitiveImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrTryImpl import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.util.isNullConst import org.jetbrains.kotlin.ir.util.isNullConst
import org.jetbrains.kotlin.ir.util.type
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
@@ -89,17 +87,17 @@ private class BuiltinOperatorTransformer(val context: Context) : IrElementTransf
return when (descriptor) { return when (descriptor) {
irBuiltins.eqeq -> { irBuiltins.eqeq -> {
val binary = expression as IrBinaryPrimitiveImpl lowerEqeq(expression.getValueArgument(0)!!, expression.getValueArgument(1)!!,
lowerEqeq(binary.argument0, binary.argument1, expression.startOffset, expression.endOffset) expression.startOffset, expression.endOffset)
} }
irBuiltins.eqeqeq -> lowerEqeqeq(expression) irBuiltins.eqeqeq -> lowerEqeqeq(expression)
irBuiltins.throwNpe -> IrCallImpl(expression.startOffset, expression.endOffset, irBuiltins.throwNpe -> IrCallImpl(expression.startOffset, expression.endOffset,
builtIns.getKonanInternalFunctions("ThrowNullPointerException").single()) context.ir.symbols.ThrowNullPointerException)
irBuiltins.noWhenBranchMatchedException -> IrCallImpl(expression.startOffset, expression.endOffset, irBuiltins.noWhenBranchMatchedException -> IrCallImpl(expression.startOffset, expression.endOffset,
builtIns.getKonanInternalFunctions("ThrowNoWhenBranchMatchedException").single()) context.ir.symbols.ThrowNoWhenBranchMatchedException)
else -> expression else -> expression
} }
@@ -129,29 +127,30 @@ private class BuiltinOperatorTransformer(val context: Context) : IrElementTransf
} }
} }
private fun selectEqualsFunction(lhs: IrExpression, rhs: IrExpression): FunctionDescriptor { private fun selectEqualsFunction(lhs: IrExpression, rhs: IrExpression): IrSimpleFunctionSymbol {
val nullableNothingType = builtIns.nullableNothingType val nullableNothingType = builtIns.nullableNothingType
if (lhs.type.isSubtypeOf(nullableNothingType) && rhs.type.isSubtypeOf(nullableNothingType)) { if (lhs.type.isSubtypeOf(nullableNothingType) && rhs.type.isSubtypeOf(nullableNothingType)) {
// Compare by reference if each part is either `Nothing` or `Nothing?`: // Compare by reference if each part is either `Nothing` or `Nothing?`:
return irBuiltins.eqeqeq return irBuiltins.eqeqeqSymbol
} }
// TODO: areEqualByValue intrinsics are specially treated by code generator // TODO: areEqualByValue intrinsics are specially treated by code generator
// and thus can be declared synthetically in the compiler instead of explicitly in the runtime. // and thus can be declared synthetically in the compiler instead of explicitly in the runtime.
// Find a type-compatible `konan.internal.areEqualByValue` intrinsic: // Find a type-compatible `konan.internal.areEqualByValue` intrinsic:
builtIns.getKonanInternalFunctions("areEqualByValue").atMostOne { context.ir.symbols.areEqualByValue.atMostOne {
lhs.type.isSubtypeOf(it.valueParameters[0].type) && rhs.type.isSubtypeOf(it.valueParameters[1].type) lhs.type.isSubtypeOf(it.owner.valueParameters[0].type) &&
rhs.type.isSubtypeOf(it.owner.valueParameters[1].type)
}?.let { }?.let {
return it return it
} }
return if (lhs.isNullConst() || rhs.isNullConst()) { return if (lhs.isNullConst() || rhs.isNullConst()) {
// or compare by reference if left or right part is `null`: // or compare by reference if left or right part is `null`:
irBuiltins.eqeqeq irBuiltins.eqeqeqSymbol
} else { } else {
// or use the general implementation: // or use the general implementation:
builtIns.getKonanInternalFunctions("areEqual").single() context.ir.symbols.areEqual
} }
} }
} }
@@ -33,10 +33,12 @@ import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrLocalDelegatedProperty import org.jetbrains.kotlin.ir.declarations.IrLocalDelegatedProperty
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
import org.jetbrains.kotlin.ir.expressions.IrCallableReference import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.IrConstKind
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -48,39 +50,48 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
private val kotlinPackage = context.irModule!!.descriptor.getPackage(FqName("kotlin")) private val kotlinPackage = context.irModule!!.descriptor.getPackage(FqName("kotlin"))
private val genericArrayType = kotlinPackage.memberScope.getContributedClassifier(Name.identifier("Array"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor private val genericArrayType = kotlinPackage.memberScope.getContributedClassifier(Name.identifier("Array"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor
private fun getKPropertyImplConstructorDescriptor(receiverTypes: List<KotlinType>, private fun getKPropertyImplConstructor(receiverTypes: List<KotlinType>,
returnType: KotlinType, returnType: KotlinType,
isLocal: Boolean, isLocal: Boolean,
isMutable: Boolean) : ClassConstructorDescriptor { isMutable: Boolean) : Pair<IrConstructorSymbol, ClassConstructorDescriptor> {
val classDescriptor =
val symbols = context.ir.symbols
val classSymbol =
if (isLocal) { if (isLocal) {
assert(receiverTypes.isEmpty(), { "Local delegated property cannot have explicit receiver" }) assert(receiverTypes.isEmpty(), { "Local delegated property cannot have explicit receiver" })
when { when {
isMutable -> reflectionTypes.kLocalDelegatedMutablePropertyImpl isMutable -> symbols.kLocalDelegatedMutablePropertyImpl
else -> reflectionTypes.kLocalDelegatedPropertyImpl else -> symbols.kLocalDelegatedPropertyImpl
} }
} else { } else {
when (receiverTypes.size) { when (receiverTypes.size) {
0 -> when { 0 -> when {
isMutable -> reflectionTypes.kMutableProperty0Impl isMutable -> symbols.kMutableProperty0Impl
else -> reflectionTypes.kProperty0Impl else -> symbols.kProperty0Impl
} }
1 -> when { 1 -> when {
isMutable -> reflectionTypes.kMutableProperty1Impl isMutable -> symbols.kMutableProperty1Impl
else -> reflectionTypes.kProperty1Impl else -> symbols.kProperty1Impl
} }
2 -> when { 2 -> when {
isMutable -> reflectionTypes.kMutableProperty2Impl isMutable -> symbols.kMutableProperty2Impl
else -> reflectionTypes.kProperty2Impl else -> symbols.kProperty2Impl
} }
else -> throw AssertionError("More than 2 receivers is not allowed") else -> throw AssertionError("More than 2 receivers is not allowed")
} }
} }
val classDescriptor = classSymbol.descriptor
val typeParameters = classDescriptor.declaredTypeParameters val typeParameters = classDescriptor.declaredTypeParameters
val arguments = (receiverTypes + listOf(returnType)) val arguments = (receiverTypes + listOf(returnType))
.mapIndexed { index, type -> typeParameters[index].typeConstructor to TypeProjectionImpl(type) } .mapIndexed { index, type -> typeParameters[index].typeConstructor to TypeProjectionImpl(type) }
.toMap() .toMap()
return classDescriptor.unsubstitutedPrimaryConstructor!!.substitute(TypeSubstitutor.create(arguments))!!
val constructorSymbol = classSymbol.constructors.single()
return constructorSymbol to constructorSymbol.descriptor.substitute(TypeSubstitutor.create(arguments))!!
} }
private fun ClassDescriptor.replace(vararg type: KotlinType): SimpleType { private fun ClassDescriptor.replace(vararg type: KotlinType): SimpleType {
@@ -90,14 +101,21 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
override fun lower(irFile: IrFile) { override fun lower(irFile: IrFile) {
val kProperties = mutableMapOf<VariableDescriptorWithAccessors, Pair<IrExpression, Int>>() val kProperties = mutableMapOf<VariableDescriptorWithAccessors, Pair<IrExpression, Int>>()
val arrayItemGetter = genericArrayType.unsubstitutedMemberScope.getContributedFunctions(Name.identifier("get"), val arrayClass = context.ir.symbols.array
NoLookupLocation.FROM_BACKEND).single()
val arrayItemGetter = arrayClass.functions.single { it.descriptor.name == Name.identifier("get") }
val typeParameterT = genericArrayType.declaredTypeParameters[0] val typeParameterT = genericArrayType.declaredTypeParameters[0]
val kPropertyImplType = reflectionTypes.kProperty1Impl.replace(context.builtIns.anyType, context.builtIns.anyType) val kPropertyImplType = reflectionTypes.kProperty1Impl.replace(context.builtIns.anyType, context.builtIns.anyType)
val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(kPropertyImplType))) val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(kPropertyImplType)))
val substitutedArrayItemGetter = arrayItemGetter.substitute(typeSubstitutor)!! val substitutedArrayItemGetter = arrayItemGetter.descriptor.substitute(typeSubstitutor)!!
val kPropertiesField = createKPropertiesFieldDescriptor(irFile.packageFragmentDescriptor, genericArrayType.replace(kPropertyImplType)) val kPropertiesField = IrFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION,
createKPropertiesFieldDescriptor(irFile.packageFragmentDescriptor,
genericArrayType.replace(kPropertyImplType)
)
)
irFile.transformChildrenVoid(object : IrElementTransformerVoid() { irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitFunction(declaration: IrFunction): IrStatement { override fun visitFunction(declaration: IrFunction): IrStatement {
@@ -120,22 +138,52 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
} }
override fun visitCallableReference(expression: IrCallableReference): IrExpression { override fun visitPropertyReference(expression: IrPropertyReference): IrExpression {
expression.transformChildrenVoid(this) expression.transformChildrenVoid(this)
val propertyDescriptor = expression.descriptor as? VariableDescriptorWithAccessors
if (propertyDescriptor == null) return expression
val receiversCount = listOf(expression.dispatchReceiver, expression.extensionReceiver).count { it != null } val receiversCount = listOf(expression.dispatchReceiver, expression.extensionReceiver).count { it != null }
if (receiversCount == 1 && propertyDescriptor is PropertyDescriptor) // Has receiver and is not local delegated. if (receiversCount == 1) // Has receiver.
return createKProperty(expression, propertyDescriptor) return createKProperty(expression)
else if (receiversCount == 2) else if (receiversCount == 2)
throw AssertionError("Callable reference to properties with two receivers is not allowed: $propertyDescriptor") throw AssertionError("Callable reference to properties with two receivers is not allowed: ${expression.descriptor}")
else { // Cache KProperties with no arguments. else { // Cache KProperties with no arguments.
val field = kProperties.getOrPut(propertyDescriptor) { val field = kProperties.getOrPut(expression.descriptor) {
createKProperty(expression, propertyDescriptor) to kProperties.size createKProperty(expression) to kProperties.size
} }
return IrCallImpl(expression.startOffset, expression.endOffset, substitutedArrayItemGetter).apply { return IrCallImpl(
dispatchReceiver = IrGetFieldImpl(expression.startOffset, expression.endOffset, kPropertiesField) expression.startOffset, expression.endOffset,
arrayItemGetter, substitutedArrayItemGetter
).apply {
dispatchReceiver =
IrGetFieldImpl(expression.startOffset, expression.endOffset, kPropertiesField.symbol)
putValueArgument(0, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, field.second))
}
}
}
override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference): IrExpression {
expression.transformChildrenVoid(this)
val propertyDescriptor = expression.descriptor
val receiversCount = listOf(expression.dispatchReceiver, expression.extensionReceiver).count { it != null }
if (receiversCount == 2)
throw AssertionError("Callable reference to properties with two receivers is not allowed: $propertyDescriptor")
else { // Cache KProperties with no arguments.
// TODO: what about `receiversCount == 1` case?
val field = kProperties.getOrPut(propertyDescriptor) {
createLocalKProperty(expression, propertyDescriptor) to kProperties.size
}
return IrCallImpl(
expression.startOffset, expression.endOffset,
arrayItemGetter, substitutedArrayItemGetter
).apply {
dispatchReceiver =
IrGetFieldImpl(expression.startOffset, expression.endOffset, kPropertiesField.symbol)
putValueArgument(0, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, field.second)) putValueArgument(0, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, field.second))
} }
} }
@@ -146,66 +194,68 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
if (kProperties.isNotEmpty()) { if (kProperties.isNotEmpty()) {
val initializers = kProperties.values.sortedBy { it.second }.map { it.first } val initializers = kProperties.values.sortedBy { it.second }.map { it.first }
// TODO: move to object for lazy initialization. // TODO: move to object for lazy initialization.
irFile.declarations.add(0, IrFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irFile.declarations.add(0, kPropertiesField.apply {
DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION, initializer = IrExpressionBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
kPropertiesField, context.createArrayOfExpression(kPropertyImplType, initializers, UNDEFINED_OFFSET, UNDEFINED_OFFSET))
IrExpressionBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, })
context.createArrayOfExpression(kPropertyImplType, initializers, UNDEFINED_OFFSET, UNDEFINED_OFFSET))))
} }
} }
private fun createKProperty(expression: IrCallableReference, propertyDescriptor: VariableDescriptorWithAccessors): IrCallImpl { private fun createKProperty(expression: IrPropertyReference): IrCallImpl {
val startOffset = expression.startOffset val startOffset = expression.startOffset
val endOffset = expression.endOffset val endOffset = expression.endOffset
val receiverTypes = mutableListOf<KotlinType>() val receiverTypes = mutableListOf<KotlinType>()
val isLocal = propertyDescriptor !is PropertyDescriptor
val propertyDescriptor = expression.descriptor
val returnType = propertyDescriptor.type val returnType = propertyDescriptor.type
val getterCallableReference = propertyDescriptor.getter.let { val getterCallableReference = propertyDescriptor.getter?.let { getter ->
if (it == null || isLocal) null getter.extensionReceiverParameter.let {
else { if (it != null && expression.extensionReceiver == null)
val getter = propertyDescriptor.getter!! receiverTypes.add(it.type)
getter.extensionReceiverParameter.let { }
if (it != null && expression.extensionReceiver == null) getter.dispatchReceiverParameter.let {
receiverTypes.add(it.type) if (it != null && expression.dispatchReceiver == null)
} receiverTypes.add(it.type)
getter.dispatchReceiverParameter.let { }
if (it != null && expression.dispatchReceiver == null) val getterKFunctionType = context.reflectionTypes.getKFunctionType(
receiverTypes.add(it.type) annotations = Annotations.EMPTY,
} receiverType = receiverTypes.firstOrNull(),
val getterKFunctionType = context.reflectionTypes.getKFunctionType( parameterTypes = if (receiverTypes.size < 2) listOf() else listOf(receiverTypes[1]),
annotations = Annotations.EMPTY, returnType = returnType)
receiverType = receiverTypes.firstOrNull(), IrFunctionReferenceImpl(
parameterTypes = if (receiverTypes.size < 2) listOf() else listOf(receiverTypes[1]), startOffset, endOffset,
returnType = returnType) getterKFunctionType, expression.getter!!, getter, null
IrFunctionReferenceImpl(startOffset, endOffset, getterKFunctionType, getter, null).apply { ).apply {
dispatchReceiver = expression.dispatchReceiver dispatchReceiver = expression.dispatchReceiver
extensionReceiver = expression.extensionReceiver extensionReceiver = expression.extensionReceiver
}
} }
} }
val setterCallableReference = propertyDescriptor.setter.let { val setterCallableReference = propertyDescriptor.setter?.let {
if (it == null || isLocal || !isKMutablePropertyType(expression.type)) null if (!isKMutablePropertyType(expression.type)) null
else { else {
val setterKFunctionType = context.reflectionTypes.getKFunctionType( val setterKFunctionType = context.reflectionTypes.getKFunctionType(
annotations = Annotations.EMPTY, annotations = Annotations.EMPTY,
receiverType = receiverTypes.firstOrNull(), receiverType = receiverTypes.firstOrNull(),
parameterTypes = if (receiverTypes.size < 2) listOf(returnType) else listOf(receiverTypes[1], returnType), parameterTypes = if (receiverTypes.size < 2) listOf(returnType) else listOf(receiverTypes[1], returnType),
returnType = context.builtIns.unitType) returnType = context.builtIns.unitType)
IrFunctionReferenceImpl(startOffset, endOffset, setterKFunctionType, it, null).apply { IrFunctionReferenceImpl(
startOffset, endOffset,
setterKFunctionType, expression.setter!!, it, null
).apply {
dispatchReceiver = expression.dispatchReceiver dispatchReceiver = expression.dispatchReceiver
extensionReceiver = expression.extensionReceiver extensionReceiver = expression.extensionReceiver
} }
} }
} }
val descriptor = getKPropertyImplConstructorDescriptor( val (symbol, descriptor) = getKPropertyImplConstructor(
receiverTypes = receiverTypes, receiverTypes = receiverTypes,
returnType = returnType, returnType = returnType,
isLocal = isLocal, isLocal = false,
isMutable = setterCallableReference != null) isMutable = setterCallableReference != null)
val initializer = IrCallImpl(startOffset, endOffset, descriptor).apply { val initializer = IrCallImpl(startOffset, endOffset, symbol, descriptor).apply {
putValueArgument(0, IrConstImpl<String>(startOffset, endOffset, putValueArgument(0, IrConstImpl<String>(startOffset, endOffset,
context.builtIns.stringType, IrConstKind.String, propertyDescriptor.name.asString())) context.builtIns.stringType, IrConstKind.String, propertyDescriptor.name.asString()))
if (getterCallableReference != null) if (getterCallableReference != null)
@@ -216,6 +266,25 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
return initializer return initializer
} }
private fun createLocalKProperty(expression: IrLocalDelegatedPropertyReference, propertyDescriptor: VariableDescriptorWithAccessors): IrCallImpl {
val startOffset = expression.startOffset
val endOffset = expression.endOffset
val returnType = propertyDescriptor.type
val (symbol, descriptor) = getKPropertyImplConstructor(
receiverTypes = emptyList(),
returnType = returnType,
isLocal = true,
isMutable = false)
val initializer = IrCallImpl(startOffset, endOffset, symbol, descriptor).apply {
putValueArgument(0, IrConstImpl<String>(startOffset, endOffset,
context.builtIns.stringType, IrConstKind.String, propertyDescriptor.name.asString()))
}
return initializer
}
private fun isKMutablePropertyType(type: KotlinType): Boolean { private fun isKMutablePropertyType(type: KotlinType): Boolean {
val arguments = type.arguments val arguments = type.arguments
val expectedClassDescriptor = when (arguments.size) { val expectedClassDescriptor = when (arguments.size) {
@@ -22,26 +22,23 @@ import org.jetbrains.kotlin.backend.common.lower.SimpleMemberScope
import org.jetbrains.kotlin.backend.common.runOnFilePostfix import org.jetbrains.kotlin.backend.common.runOnFilePostfix
import org.jetbrains.kotlin.backend.jvm.descriptors.createValueParameter import org.jetbrains.kotlin.backend.jvm.descriptors.createValueParameter
import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalFunctions import org.jetbrains.kotlin.backend.konan.DECLARATION_ORIGIN_ENUM
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
import org.jetbrains.kotlin.backend.konan.ir.createArrayOfExpression import org.jetbrains.kotlin.backend.konan.ir.createArrayOfExpression
import org.jetbrains.kotlin.backend.konan.ir.createFakeOverrideDescriptor import org.jetbrains.kotlin.backend.konan.ir.createFakeOverrideDescriptor
import org.jetbrains.kotlin.backend.konan.ir.createSimpleDelegatingConstructor import org.jetbrains.kotlin.backend.konan.ir.addSimpleDelegatingConstructor
import org.jetbrains.kotlin.backend.konan.ir.createSimpleDelegatingConstructorDescriptor import org.jetbrains.kotlin.backend.konan.ir.createSimpleDelegatingConstructorDescriptor
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.* import org.jetbrains.kotlin.ir.declarations.impl.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.util.createParameterDeclarations import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.util.dump import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.util.transform
import org.jetbrains.kotlin.ir.util.transformFlat
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -53,43 +50,47 @@ import org.jetbrains.kotlin.types.TypeSubstitutor
internal class EnumSyntheticFunctionsBuilder(val context: Context) { internal class EnumSyntheticFunctionsBuilder(val context: Context) {
fun buildValuesExpression(startOffset: Int, endOffset: Int, fun buildValuesExpression(startOffset: Int, endOffset: Int,
enumClassDescriptor: ClassDescriptor): IrExpression { enumClassDescriptor: ClassDescriptor): IrExpression {
val loweredEnum = context.specialDescriptorsFactory.getLoweredEnum(enumClassDescriptor) val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClassDescriptor)
val typeParameterT = genericValuesDescriptor.typeParameters[0] val typeParameterT = genericValuesDescriptor.typeParameters[0]
val enumClassType = enumClassDescriptor.defaultType val enumClassType = enumClassDescriptor.defaultType
val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(enumClassType))) val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(enumClassType)))
val substitutedValueOf = genericValuesDescriptor.substitute(typeSubstitutor)!! val substitutedValueOf = genericValuesDescriptor.substitute(typeSubstitutor)!!
return IrCallImpl(startOffset, endOffset, substitutedValueOf, mapOf(typeParameterT to enumClassType)) return IrCallImpl(startOffset, endOffset,
genericValuesSymbol, substitutedValueOf, mapOf(typeParameterT to enumClassType))
.apply { .apply {
val receiver = IrGetObjectValueImpl(startOffset, endOffset, val receiver = IrGetObjectValueImpl(startOffset, endOffset,
loweredEnum.implObjectDescriptor.defaultType, loweredEnum.implObjectDescriptor) loweredEnum.implObject.defaultType, loweredEnum.implObject.symbol)
putValueArgument(0, IrGetFieldImpl(startOffset, endOffset, loweredEnum.valuesProperty, receiver)) putValueArgument(0, IrGetFieldImpl(startOffset, endOffset, loweredEnum.valuesField.symbol, receiver))
} }
} }
fun buildValueOfExpression(startOffset: Int, endOffset: Int, fun buildValueOfExpression(startOffset: Int, endOffset: Int,
enumClassDescriptor: ClassDescriptor, enumClassDescriptor: ClassDescriptor,
value: IrExpression): IrExpression { value: IrExpression): IrExpression {
val loweredEnum = context.specialDescriptorsFactory.getLoweredEnum(enumClassDescriptor) val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClassDescriptor)
val typeParameterT = genericValueOfDescriptor.typeParameters[0] val typeParameterT = genericValueOfDescriptor.typeParameters[0]
val enumClassType = enumClassDescriptor.defaultType val enumClassType = enumClassDescriptor.defaultType
val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(enumClassType))) val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(enumClassType)))
val substitutedValueOf = genericValueOfDescriptor.substitute(typeSubstitutor)!! val substitutedValueOf = genericValueOfDescriptor.substitute(typeSubstitutor)!!
return IrCallImpl(startOffset, endOffset, substitutedValueOf, mapOf(typeParameterT to enumClassType)) return IrCallImpl(startOffset, endOffset,
genericValueOfSymbol, substitutedValueOf, mapOf(typeParameterT to enumClassType))
.apply { .apply {
putValueArgument(0, value) putValueArgument(0, value)
val receiver = IrGetObjectValueImpl(startOffset, endOffset, val receiver = IrGetObjectValueImpl(startOffset, endOffset,
loweredEnum.implObjectDescriptor.defaultType, loweredEnum.implObjectDescriptor) loweredEnum.implObject.defaultType, loweredEnum.implObject.symbol)
putValueArgument(1, IrGetFieldImpl(startOffset, endOffset, loweredEnum.valuesProperty, receiver)) putValueArgument(1, IrGetFieldImpl(startOffset, endOffset, loweredEnum.valuesField.symbol, receiver))
} }
} }
private val genericValueOfDescriptor = context.builtIns.getKonanInternalFunctions("valueOfForEnum").single() private val genericValueOfSymbol = context.ir.symbols.valueOfForEnum
private val genericValueOfDescriptor = genericValueOfSymbol.descriptor
private val genericValuesDescriptor = context.builtIns.getKonanInternalFunctions("valuesForEnum").single() private val genericValuesSymbol = context.ir.symbols.valuesForEnum
private val genericValuesDescriptor = genericValuesSymbol.descriptor
} }
internal class EnumUsageLowering(val context: Context) internal class EnumUsageLowering(val context: Context)
@@ -142,10 +143,10 @@ internal class EnumUsageLowering(val context: Context)
Name.identifier("enumValues"), NoLookupLocation.FROM_BACKEND).single() Name.identifier("enumValues"), NoLookupLocation.FROM_BACKEND).single()
private fun loadEnumEntry(startOffset: Int, endOffset: Int, enumClassDescriptor: ClassDescriptor, name: Name): IrExpression { private fun loadEnumEntry(startOffset: Int, endOffset: Int, enumClassDescriptor: ClassDescriptor, name: Name): IrExpression {
val loweredEnum = context.specialDescriptorsFactory.getLoweredEnum(enumClassDescriptor) val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClassDescriptor)
val ordinal = loweredEnum.entriesMap[name]!! val ordinal = loweredEnum.entriesMap[name]!!
return IrCallImpl(startOffset, endOffset, loweredEnum.itemGetter).apply { return IrCallImpl(startOffset, endOffset, loweredEnum.itemGetterSymbol, loweredEnum.itemGetterDescriptor).apply {
dispatchReceiver = IrCallImpl(startOffset, endOffset, loweredEnum.valuesGetter) dispatchReceiver = IrCallImpl(startOffset, endOffset, loweredEnum.valuesGetter.symbol)
putValueArgument(0, IrConstImpl.int(startOffset, endOffset, enumClassDescriptor.module.builtIns.intType, ordinal)) putValueArgument(0, IrConstImpl.int(startOffset, endOffset, enumClassDescriptor.module.builtIns.intType, ordinal))
} }
} }
@@ -169,11 +170,11 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
} }
private inner class EnumClassTransformer(val irClass: IrClass) { private inner class EnumClassTransformer(val irClass: IrClass) {
private val loweredEnum = context.specialDescriptorsFactory.getLoweredEnum(irClass.descriptor) private val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(irClass.descriptor)
private val enumEntryOrdinals = mutableMapOf<ClassDescriptor, Int>() private val enumEntryOrdinals = mutableMapOf<ClassDescriptor, Int>()
private val loweredEnumConstructors = mutableMapOf<ClassConstructorDescriptor, ClassConstructorDescriptor>() private val loweredEnumConstructors = mutableMapOf<ClassConstructorDescriptor, IrConstructor>()
private val descriptorToIrConstructorWithDefaultArguments = mutableMapOf<ClassConstructorDescriptor, IrConstructor>() private val descriptorToIrConstructorWithDefaultArguments = mutableMapOf<ClassConstructorDescriptor, IrConstructor>()
private val defaultEnumEntryConstructors = mutableMapOf<ClassConstructorDescriptor, ClassConstructorDescriptor>() private val defaultEnumEntryConstructors = mutableMapOf<ClassConstructorDescriptor, IrConstructor>()
private val loweredEnumConstructorParameters = mutableMapOf<ValueParameterDescriptor, ValueParameterDescriptor>() private val loweredEnumConstructorParameters = mutableMapOf<ValueParameterDescriptor, ValueParameterDescriptor>()
private val enumSyntheticFunctionsBuilder = EnumSyntheticFunctionsBuilder(context) private val enumSyntheticFunctionsBuilder = EnumSyntheticFunctionsBuilder(context)
@@ -205,7 +206,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
blockBody.statements.transformFlat { blockBody.statements.transformFlat {
if (it is IrEnumConstructorCall) if (it is IrEnumConstructorCall)
listOf(it, IrInstanceInitializerCallImpl(declaration.startOffset, declaration.startOffset, listOf(it, IrInstanceInitializerCallImpl(declaration.startOffset, declaration.startOffset,
irClass.descriptor)) irClass.symbol))
else null else null
} }
} }
@@ -254,21 +255,21 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
val constructors = mutableSetOf<ClassConstructorDescriptor>() val constructors = mutableSetOf<ClassConstructorDescriptor>()
descriptor.constructors.forEach { descriptor.constructors.forEach {
val loweredEnumConstructor = loweredEnumConstructors[it]!! val loweredEnumConstructorSymbol = loweredEnumConstructors[it]!!.symbol
val loweredEnumConstructor = loweredEnumConstructorSymbol.descriptor
val constructorDescriptor = defaultClassDescriptor.createSimpleDelegatingConstructorDescriptor(loweredEnumConstructor) val constructorDescriptor = defaultClassDescriptor.createSimpleDelegatingConstructorDescriptor(loweredEnumConstructor)
val constructor = defaultClassDescriptor.createSimpleDelegatingConstructor( val constructor = defaultClass.addSimpleDelegatingConstructor(
loweredEnumConstructor, constructorDescriptor, loweredEnumConstructorSymbol, constructorDescriptor,
startOffset, endOffset, DECLARATION_ORIGIN_ENUM) DECLARATION_ORIGIN_ENUM)
constructors.add(constructorDescriptor) constructors.add(constructorDescriptor)
defaultClass.declarations.add(constructor) defaultEnumEntryConstructors.put(loweredEnumConstructor, constructor)
defaultEnumEntryConstructors.put(loweredEnumConstructor, constructorDescriptor)
val irConstructor = descriptorToIrConstructorWithDefaultArguments[loweredEnumConstructor] val irConstructor = descriptorToIrConstructorWithDefaultArguments[loweredEnumConstructor]
if (irConstructor != null) { if (irConstructor != null) {
it.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument -> it.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument ->
val loweredArgument = loweredEnumConstructor.valueParameters[argument.loweredIndex()] val loweredArgument = loweredEnumConstructor.valueParameters[argument.loweredIndex()]
val body = irConstructor.getDefault(loweredArgument)!! val body = irConstructor.getDefault(loweredArgument)!!
body.transformChildrenVoid(ParameterMapper(constructorDescriptor)) body.transformChildrenVoid(ParameterMapper(constructor))
constructor.putDefault(constructorDescriptor.valueParameters[loweredArgument.index], body) constructor.putDefault(constructorDescriptor.valueParameters[loweredArgument.index], body)
} }
} }
@@ -285,12 +286,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
} }
private fun createImplObject() { private fun createImplObject() {
val startOffset = irClass.startOffset val implObject = loweredEnum.implObject
val endOffset = irClass.endOffset
val implObjectDescriptor = loweredEnum.implObjectDescriptor
val implObject = IrClassImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, implObjectDescriptor)
implObject.createParameterDeclarations()
val enumEntries = mutableListOf<IrEnumEntry>() val enumEntries = mutableListOf<IrEnumEntry>()
var i = 0 var i = 0
@@ -307,9 +303,9 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
if (body is IrSyntheticBody) { if (body is IrSyntheticBody) {
when (body.kind) { when (body.kind) {
IrSyntheticBodyKind.ENUM_VALUEOF -> IrSyntheticBodyKind.ENUM_VALUEOF ->
declaration.body = createSyntheticValueOfMethodBody(declaration.descriptor) declaration.body = createSyntheticValueOfMethodBody(declaration)
IrSyntheticBodyKind.ENUM_VALUES -> IrSyntheticBodyKind.ENUM_VALUES ->
declaration.body = createSyntheticValuesMethodBody(declaration.descriptor) declaration.body = createSyntheticValuesMethodBody(declaration)
} }
} }
} }
@@ -320,12 +316,12 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
++i ++i
} }
val constructorOfAny = irClass.descriptor.module.builtIns.any.constructors.first() val constructorOfAny = context.ir.symbols.any.constructors.single()
val constructor = implObjectDescriptor.createSimpleDelegatingConstructor(
constructorOfAny, implObjectDescriptor.constructors.single(), implObject.addSimpleDelegatingConstructor(
startOffset, endOffset, DECLARATION_ORIGIN_ENUM) constructorOfAny, implObject.descriptor.constructors.single(),
DECLARATION_ORIGIN_ENUM)
implObject.declarations.add(constructor)
implObject.declarations.add(createSyntheticValuesPropertyDeclaration(enumEntries)) implObject.declarations.add(createSyntheticValuesPropertyDeclaration(enumEntries))
irClass.declarations.add(implObject) irClass.declarations.add(implObject)
@@ -337,47 +333,42 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
val irValuesInitializer = context.createArrayOfExpression(irClass.descriptor.defaultType, val irValuesInitializer = context.createArrayOfExpression(irClass.descriptor.defaultType,
enumEntries.sortedBy { it.descriptor.name }.map { it.initializerExpression!! }, startOffset, endOffset) enumEntries.sortedBy { it.descriptor.name }.map { it.initializerExpression!! }, startOffset, endOffset)
val irField = IrFieldImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, val irField = loweredEnum.valuesField.apply {
loweredEnum.valuesProperty, initializer = IrExpressionBodyImpl(startOffset, endOffset, irValuesInitializer)
IrExpressionBodyImpl(startOffset, endOffset, irValuesInitializer)) }
val getter = IrFunctionImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, loweredEnum.valuesGetter) val getter = loweredEnum.valuesGetter
getter.createParameterDeclarations()
val receiver = IrGetObjectValueImpl(startOffset, endOffset, val receiver = IrGetObjectValueImpl(startOffset, endOffset,
loweredEnum.implObjectDescriptor.defaultType, loweredEnum.implObjectDescriptor) loweredEnum.implObject.defaultType, loweredEnum.implObject.symbol)
val value = IrGetFieldImpl(startOffset, endOffset, loweredEnum.valuesProperty, receiver) val value = IrGetFieldImpl(startOffset, endOffset, loweredEnum.valuesField.symbol, receiver)
val returnStatement = IrReturnImpl(startOffset, endOffset, loweredEnum.valuesGetter, value) val returnStatement = IrReturnImpl(startOffset, endOffset, loweredEnum.valuesGetter.symbol, value)
getter.body = IrBlockBodyImpl(startOffset, endOffset, listOf(returnStatement)) getter.body = IrBlockBodyImpl(startOffset, endOffset, listOf(returnStatement))
val irProperty = IrPropertyImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, val irProperty = IrPropertyImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM,
false, loweredEnum.valuesProperty, irField, getter, null) false, loweredEnum.valuesField.descriptor, irField, getter, null)
return irProperty return irProperty
} }
private object DECLARATION_ORIGIN_ENUM : private fun createSyntheticValuesMethodBody(declaration: IrFunction): IrBody {
IrDeclarationOriginImpl("ENUM")
private fun createSyntheticValuesMethodBody(descriptor: FunctionDescriptor): IrBody {
val startOffset = irClass.startOffset val startOffset = irClass.startOffset
val endOffset = irClass.endOffset val endOffset = irClass.endOffset
val valuesExpression = enumSyntheticFunctionsBuilder.buildValuesExpression(startOffset, endOffset, irClass.descriptor) val valuesExpression = enumSyntheticFunctionsBuilder.buildValuesExpression(startOffset, endOffset, irClass.descriptor)
return IrBlockBodyImpl(startOffset, endOffset, return IrBlockBodyImpl(startOffset, endOffset,
listOf(IrReturnImpl(startOffset, endOffset, descriptor, valuesExpression)) listOf(IrReturnImpl(startOffset, endOffset, declaration.symbol, valuesExpression))
) )
} }
private fun createSyntheticValueOfMethodBody(descriptor: FunctionDescriptor): IrBody { private fun createSyntheticValueOfMethodBody(declaration: IrFunction): IrBody {
val startOffset = irClass.startOffset val startOffset = irClass.startOffset
val endOffset = irClass.endOffset val endOffset = irClass.endOffset
val value = IrGetValueImpl(startOffset, endOffset, descriptor.valueParameters[0]) val value = IrGetValueImpl(startOffset, endOffset, declaration.valueParameters[0].symbol)
val valueOfExpression = enumSyntheticFunctionsBuilder.buildValueOfExpression(startOffset, endOffset, irClass.descriptor, value) val valueOfExpression = enumSyntheticFunctionsBuilder.buildValueOfExpression(startOffset, endOffset, irClass.descriptor, value)
return IrBlockBodyImpl( return IrBlockBodyImpl(
startOffset, endOffset, startOffset, endOffset,
listOf(IrReturnImpl(startOffset, endOffset, descriptor, valueOfExpression)) listOf(IrReturnImpl(startOffset, endOffset, declaration.symbol, valueOfExpression))
) )
} }
@@ -397,11 +388,13 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
enumConstructor.body!! // will be transformed later enumConstructor.body!! // will be transformed later
) )
loweredEnumConstructors[constructorDescriptor] = loweredEnumConstructor
loweredEnumConstructor.createParameterDeclarations() loweredEnumConstructor.createParameterDeclarations()
enumConstructor.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { enumConstructor.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach {
val body = enumConstructor.getDefault(it)!! val body = enumConstructor.getDefault(it)!!
body.transformChildrenVoid(ParameterMapper(constructorDescriptor)) body.transformChildrenVoid(ParameterMapper(enumConstructor))
loweredEnumConstructor.putDefault(loweredConstructorDescriptor.valueParameters[it.loweredIndex()], body) loweredEnumConstructor.putDefault(loweredConstructorDescriptor.valueParameters[it.loweredIndex()], body)
descriptorToIrConstructorWithDefaultArguments[loweredConstructorDescriptor] = loweredEnumConstructor descriptorToIrConstructorWithDefaultArguments[loweredConstructorDescriptor] = loweredEnumConstructor
} }
@@ -428,8 +421,6 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
loweredConstructorDescriptor.returnType = constructorDescriptor.returnType loweredConstructorDescriptor.returnType = constructorDescriptor.returnType
loweredEnumConstructors[constructorDescriptor] = loweredConstructorDescriptor
return loweredConstructorDescriptor return loweredConstructorDescriptor
} }
@@ -450,14 +441,15 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
irClass.transformChildrenVoid(EnumClassBodyTransformer()) irClass.transformChildrenVoid(EnumClassBodyTransformer())
} }
private inner class InEnumClassConstructor(val enumClassConstructor: ClassConstructorDescriptor) : private inner class InEnumClassConstructor(val enumClassConstructor: IrConstructor) :
EnumConstructorCallTransformer { EnumConstructorCallTransformer {
override fun transform(enumConstructorCall: IrEnumConstructorCall): IrExpression { override fun transform(enumConstructorCall: IrEnumConstructorCall): IrExpression {
val startOffset = enumConstructorCall.startOffset val startOffset = enumConstructorCall.startOffset
val endOffset = enumConstructorCall.endOffset val endOffset = enumConstructorCall.endOffset
val origin = enumConstructorCall.origin val origin = enumConstructorCall.origin
val result = IrDelegatingConstructorCallImpl(startOffset, endOffset, enumConstructorCall.descriptor) val result = IrDelegatingConstructorCallImpl(startOffset, endOffset,
enumConstructorCall.symbol, enumConstructorCall.descriptor)
assert(result.descriptor.valueParameters.size == 2) { assert(result.descriptor.valueParameters.size == 2) {
"Enum(String, Int) constructor call expected:\n${result.dump()}" "Enum(String, Int) constructor call expected:\n${result.dump()}"
@@ -471,8 +463,8 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
throw AssertionError("No 'ordinal' parameter in enum constructor: $enumClassConstructor") throw AssertionError("No 'ordinal' parameter in enum constructor: $enumClassConstructor")
} }
result.putValueArgument(0, IrGetValueImpl(startOffset, endOffset, nameParameter, origin)) result.putValueArgument(0, IrGetValueImpl(startOffset, endOffset, nameParameter.symbol, origin))
result.putValueArgument(1, IrGetValueImpl(startOffset, endOffset, ordinalParameter, origin)) result.putValueArgument(1, IrGetValueImpl(startOffset, endOffset, ordinalParameter.symbol, origin))
return result return result
} }
@@ -486,10 +478,13 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
throw AssertionError("Constructor called in enum entry initializer should've been lowered: $descriptor") throw AssertionError("Constructor called in enum entry initializer should've been lowered: $descriptor")
} }
val result = IrDelegatingConstructorCallImpl(startOffset, endOffset, loweredDelegatedConstructor) val result = IrDelegatingConstructorCallImpl(startOffset, endOffset,
loweredDelegatedConstructor.symbol, loweredDelegatedConstructor.descriptor)
result.putValueArgument(0, IrGetValueImpl(startOffset, endOffset, enumClassConstructor.valueParameters[0])) result.putValueArgument(0,
result.putValueArgument(1, IrGetValueImpl(startOffset, endOffset, enumClassConstructor.valueParameters[1])) IrGetValueImpl(startOffset, endOffset, enumClassConstructor.valueParameters[0].symbol))
result.putValueArgument(1,
IrGetValueImpl(startOffset, endOffset, enumClassConstructor.valueParameters[1].symbol))
descriptor.valueParameters.forEach { valueParameter -> descriptor.valueParameters.forEach { valueParameter ->
result.putValueArgument(valueParameter.loweredIndex(), delegatingConstructorCall.getValueArgument(valueParameter)) result.putValueArgument(valueParameter.loweredIndex(), delegatingConstructorCall.getValueArgument(valueParameter))
@@ -512,7 +507,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
throw AssertionError("Constructor called in enum entry initializer should've been lowered: $descriptor") throw AssertionError("Constructor called in enum entry initializer should've been lowered: $descriptor")
} }
val result = createConstructorCall(startOffset, endOffset, loweredConstructor) val result = createConstructorCall(startOffset, endOffset, loweredConstructor.symbol)
result.putValueArgument(0, IrConstImpl.string(startOffset, endOffset, context.builtIns.stringType, name)) result.putValueArgument(0, IrConstImpl.string(startOffset, endOffset, context.builtIns.stringType, name))
result.putValueArgument(1, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, ordinal)) result.putValueArgument(1, IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, ordinal))
@@ -529,17 +524,19 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
throw AssertionError("Unexpected delegating constructor call within enum entry: $enumEntry") throw AssertionError("Unexpected delegating constructor call within enum entry: $enumEntry")
} }
abstract fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: ClassConstructorDescriptor): IrMemberAccessExpression abstract fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol): IrMemberAccessExpression
} }
private inner class InEnumEntryClassConstructor(enumEntry: ClassDescriptor) : InEnumEntry(enumEntry) { private inner class InEnumEntryClassConstructor(enumEntry: ClassDescriptor) : InEnumEntry(enumEntry) {
override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: ClassConstructorDescriptor) override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol)
= IrDelegatingConstructorCallImpl(startOffset, endOffset, loweredConstructor) = IrDelegatingConstructorCallImpl(startOffset, endOffset, loweredConstructor, loweredConstructor.descriptor)
} }
private inner class InEnumEntryInitializer(enumEntry: ClassDescriptor) : InEnumEntry(enumEntry) { private inner class InEnumEntryInitializer(enumEntry: ClassDescriptor) : InEnumEntry(enumEntry) {
override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: ClassConstructorDescriptor) override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol): IrCall {
= IrCallImpl(startOffset, endOffset, defaultEnumEntryConstructors[loweredConstructor] ?: loweredConstructor) return IrCallImpl(startOffset, endOffset,
defaultEnumEntryConstructors[loweredConstructor.descriptor]?.symbol ?: loweredConstructor)
}
} }
private inner class EnumClassBodyTransformer : IrElementTransformerVoid() { private inner class EnumClassBodyTransformer : IrElementTransformerVoid() {
@@ -571,7 +568,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
enumConstructorCallTransformer = InEnumEntryClassConstructor(containingClass) enumConstructorCallTransformer = InEnumEntryClassConstructor(containingClass)
} else if (containingClass.kind == ClassKind.ENUM_CLASS) { } else if (containingClass.kind == ClassKind.ENUM_CLASS) {
assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}" } assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}" }
enumConstructorCallTransformer = InEnumClassConstructor(constructorDescriptor) enumConstructorCallTransformer = InEnumClassConstructor(declaration)
} }
val result = super.visitConstructor(declaration) val result = super.visitConstructor(declaration)
@@ -605,10 +602,15 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
override fun visitGetValue(expression: IrGetValue): IrExpression { override fun visitGetValue(expression: IrGetValue): IrExpression {
val loweredParameter = loweredEnumConstructorParameters[expression.descriptor] val loweredParameter = loweredEnumConstructorParameters[expression.descriptor]
if (loweredParameter != null) if (loweredParameter != null) {
return IrGetValueImpl(expression.startOffset, expression.endOffset, loweredParameter, expression.origin) val loweredEnumConstructor = loweredEnumConstructors[expression.descriptor.containingDeclaration]!!
else val loweredIrParameter = loweredEnumConstructor.valueParameters[loweredParameter.index]
assert(loweredIrParameter.descriptor == loweredParameter)
return IrGetValueImpl(expression.startOffset, expression.endOffset,
loweredIrParameter.symbol, expression.origin)
} else {
return expression return expression
}
} }
} }
} }
@@ -616,14 +618,14 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
private fun ValueParameterDescriptor.loweredIndex(): Int = index + 2 private fun ValueParameterDescriptor.loweredIndex(): Int = index + 2
private class ParameterMapper(val originalDescriptor: FunctionDescriptor) : IrElementTransformerVoid() { private class ParameterMapper(val originalConstructor: IrConstructor) : IrElementTransformerVoid() {
override fun visitGetValue(expression: IrGetValue): IrExpression { override fun visitGetValue(expression: IrGetValue): IrExpression {
val descriptor = expression.descriptor val descriptor = expression.descriptor
when (descriptor) { when (descriptor) {
is ValueParameterDescriptor -> { is ValueParameterDescriptor -> {
return IrGetValueImpl(expression.startOffset, return IrGetValueImpl(expression.startOffset,
expression.endOffset, expression.endOffset,
originalDescriptor.valueParameters[descriptor.index]) originalConstructor.valueParameters[descriptor.index].symbol)
} }
} }
return expression return expression
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
@@ -204,17 +205,21 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass
name = Name.identifier("t"), name = Name.identifier("t"),
outType = context.builtIns.throwable.defaultType outType = context.builtIns.throwable.defaultType
) )
val catchParameter = IrVariableImpl(
startOffset, endOffset, IrDeclarationOrigin.CATCH_PARAMETER, parameter)
val syntheticTry = IrTryImpl( val syntheticTry = IrTryImpl(
startOffset = startOffset, startOffset = startOffset,
endOffset = endOffset, endOffset = endOffset,
type = context.builtIns.nothingType, type = context.builtIns.nothingType,
tryResult = transformedTry, tryResult = transformedTry,
catches = listOf( catches = listOf(
irCatch(parameter, irCatch(catchParameter).apply {
irBlock { result = irBlock {
+finallyExpression.copy() +finallyExpression.copy()
+irThrow(irGet(parameter)) +irThrow(irGet(catchParameter.symbol))
})), }
}),
finallyExpression = null finallyExpression = null
) )
using(TryScope(syntheticTry, transformedFinallyExpression, this)) { using(TryScope(syntheticTry, transformedFinallyExpression, this)) {
@@ -243,22 +248,15 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass
+finallyExpression.copy() +finallyExpression.copy()
} }
else -> irBlock(value, null, returnType) { else -> irBlock(value, null, returnType) {
val tmp = IrTemporaryVariableDescriptorImpl( val tmp = irTemporary(irReturnableBlock(descriptor) {
functionDescriptor,
"tmp${tempIndex++}".synthesizedName,
returnType
)
+irVar(tmp, irReturnableBlock(descriptor) {
+irReturn(descriptor, value) +irReturn(descriptor, value)
}) })
+finallyExpression.copy() +finallyExpression.copy()
+irGet(tmp) +irGet(tmp.symbol)
} }
} }
} }
private var tempIndex = 0
private fun getFakeFunctionDescriptor(name: String, returnType: KotlinType): FunctionDescriptor { private fun getFakeFunctionDescriptor(name: String, returnType: KotlinType): FunctionDescriptor {
return SimpleFunctionDescriptorImpl.create( return SimpleFunctionDescriptorImpl.create(
functionDescriptor, functionDescriptor,
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.ir.expressions.IrDelegatingConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrInstanceInitializerCall import org.jetbrains.kotlin.ir.expressions.IrInstanceInitializerCall
import org.jetbrains.kotlin.ir.expressions.IrStatementOriginImpl import org.jetbrains.kotlin.ir.expressions.IrStatementOriginImpl
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.util.createParameterDeclarations import org.jetbrains.kotlin.ir.util.createParameterDeclarations
import org.jetbrains.kotlin.ir.util.transformFlat import org.jetbrains.kotlin.ir.util.transformFlat
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
@@ -46,8 +47,8 @@ internal class InitializersLowering(val context: Context) : ClassLoweringPass {
fun lowerInitializers() { fun lowerInitializers() {
collectAndRemoveInitializers() collectAndRemoveInitializers()
val initializerMethodDescriptor = createInitializerMethod() val initializerMethodSymbol = createInitializerMethod()
lowerConstructors(initializerMethodDescriptor) lowerConstructors(initializerMethodSymbol)
} }
object STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER : object STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER :
@@ -72,13 +73,12 @@ internal class InitializersLowering(val context: Context) : ClassLoweringPass {
override fun visitField(declaration: IrField): IrStatement { override fun visitField(declaration: IrField): IrStatement {
val initializer = declaration.initializer ?: return declaration val initializer = declaration.initializer ?: return declaration
val propertyDescriptor = declaration.descriptor
val startOffset = initializer.startOffset val startOffset = initializer.startOffset
val endOffset = initializer.endOffset val endOffset = initializer.endOffset
initializers.add(IrBlockImpl(startOffset, endOffset, context.builtIns.unitType, STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER, initializers.add(IrBlockImpl(startOffset, endOffset, context.builtIns.unitType, STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER,
listOf( listOf(
IrSetFieldImpl(startOffset, endOffset, propertyDescriptor, IrSetFieldImpl(startOffset, endOffset, declaration.symbol,
IrGetValueImpl(startOffset, endOffset, irClass.descriptor.thisAsReceiverParameter), IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol),
initializer.expression, STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER)))) initializer.expression, STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER))))
declaration.initializer = null declaration.initializer = null
return declaration return declaration
@@ -92,7 +92,7 @@ internal class InitializersLowering(val context: Context) : ClassLoweringPass {
} }
} }
private fun createInitializerMethod(): FunctionDescriptor? { private fun createInitializerMethod(): IrSimpleFunctionSymbol? {
if (irClass.descriptor.hasPrimaryConstructor()) if (irClass.descriptor.hasPrimaryConstructor())
return null // Place initializers in the primary constructor. return null // Place initializers in the primary constructor.
val initializerMethodDescriptor = SimpleFunctionDescriptorImpl.create( val initializerMethodDescriptor = SimpleFunctionDescriptorImpl.create(
@@ -118,10 +118,10 @@ internal class InitializersLowering(val context: Context) : ClassLoweringPass {
irClass.declarations.add(initializer) irClass.declarations.add(initializer)
return initializerMethodDescriptor return initializer.symbol
} }
private fun lowerConstructors(initializerMethodDescriptor: FunctionDescriptor?) { private fun lowerConstructors(initializerMethodSymbol: IrSimpleFunctionSymbol?) {
irClass.transformChildrenVoid(object : IrElementTransformerVoid() { irClass.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitClass(declaration: IrClass): IrStatement { override fun visitClass(declaration: IrClass): IrStatement {
@@ -135,14 +135,14 @@ internal class InitializersLowering(val context: Context) : ClassLoweringPass {
blockBody.statements.transformFlat { blockBody.statements.transformFlat {
when { when {
it is IrInstanceInitializerCall -> { it is IrInstanceInitializerCall -> {
if (initializerMethodDescriptor == null) { if (initializerMethodSymbol == null) {
assert(declaration.descriptor.isPrimary) assert(declaration.descriptor.isPrimary)
initializers initializers
} else { } else {
val startOffset = it.startOffset val startOffset = it.startOffset
val endOffset = it.endOffset val endOffset = it.endOffset
listOf(IrCallImpl(startOffset, endOffset, initializerMethodDescriptor).apply { listOf(IrCallImpl(startOffset, endOffset, initializerMethodSymbol).apply {
dispatchReceiver = IrGetValueImpl(startOffset, endOffset, irClass.descriptor.thisAsReceiverParameter) dispatchReceiver = IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol)
}) })
} }
} }
@@ -23,14 +23,14 @@ import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
import org.jetbrains.kotlin.ir.expressions.IrBlockBody import org.jetbrains.kotlin.ir.expressions.IrBlockBody
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrGetValue import org.jetbrains.kotlin.ir.expressions.IrGetValue
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.util.transformFlat import org.jetbrains.kotlin.ir.util.transformFlat
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
@@ -44,7 +44,7 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
private inner class InnerClassTransformer(val irClass: IrClass) { private inner class InnerClassTransformer(val irClass: IrClass) {
val classDescriptor = irClass.descriptor val classDescriptor = irClass.descriptor
lateinit var outerThisFieldDescriptor: PropertyDescriptor lateinit var outerThisFieldSymbol: IrFieldSymbol
fun lowerInnerClass() { fun lowerInnerClass() {
if (!irClass.descriptor.isInner) return if (!irClass.descriptor.isInner) return
@@ -54,17 +54,10 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
lowerConstructors() lowerConstructors()
} }
object DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS :
IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS")
private fun createOuterThisField() { private fun createOuterThisField() {
outerThisFieldDescriptor = context.specialDescriptorsFactory.getOuterThisFieldDescriptor(classDescriptor) val field = context.specialDeclarationsFactory.getOuterThisField(classDescriptor)
outerThisFieldSymbol = field.symbol
irClass.declarations.add(IrFieldImpl( irClass.declarations.add(field)
irClass.startOffset, irClass.endOffset,
DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS,
outerThisFieldDescriptor
))
} }
private fun lowerConstructors() { private fun lowerConstructors() {
@@ -86,9 +79,9 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
blockBody.statements.add( blockBody.statements.add(
0, 0,
IrSetFieldImpl( IrSetFieldImpl(
startOffset, endOffset, outerThisFieldDescriptor, startOffset, endOffset, outerThisFieldSymbol,
IrGetValueImpl(startOffset, endOffset, classDescriptor.thisAsReceiverParameter), IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol),
IrGetValueImpl(startOffset, endOffset, irConstructor.descriptor.dispatchReceiverParameter!!) IrGetValueImpl(startOffset, endOffset, irConstructor.dispatchReceiverParameter!!.symbol)
) )
) )
} }
@@ -106,7 +99,7 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
if (implicitThisClass == classDescriptor) return expression if (implicitThisClass == classDescriptor) return expression
val constructorDescriptor = currentFunction!!.scope.scopeOwner as? ConstructorDescriptor val constructorSymbol = currentFunction!!.scope.scopeOwnerSymbol as? IrConstructorSymbol
val startOffset = expression.startOffset val startOffset = expression.startOffset
val endOffset = expression.endOffset val endOffset = expression.endOffset
@@ -114,14 +107,15 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
var irThis: IrExpression var irThis: IrExpression
var innerClass: ClassDescriptor var innerClass: ClassDescriptor
if (constructorDescriptor == null || constructorDescriptor.constructedClass != classDescriptor) { if (constructorSymbol == null || constructorSymbol.descriptor.constructedClass != classDescriptor) {
innerClass = classDescriptor innerClass = classDescriptor
irThis = IrGetValueImpl(startOffset, endOffset, classDescriptor.thisAsReceiverParameter, origin) irThis = IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol, origin)
} else { } else {
// For constructor we have outer class as dispatchReceiverParameter. // For constructor we have outer class as dispatchReceiverParameter.
innerClass = DescriptorUtils.getContainingClass(classDescriptor) ?: innerClass = DescriptorUtils.getContainingClass(classDescriptor) ?:
throw AssertionError("No containing class for inner class $classDescriptor") throw AssertionError("No containing class for inner class $classDescriptor")
irThis = IrGetValueImpl(startOffset, endOffset, constructorDescriptor.dispatchReceiverParameter!!, origin) irThis = IrGetValueImpl(startOffset, endOffset,
constructorSymbol.owner.dispatchReceiverParameter!!.symbol, origin)
} }
while (innerClass != implicitThisClass) { while (innerClass != implicitThisClass) {
@@ -131,8 +125,8 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
return expression return expression
} }
val outerThisField = context.specialDescriptorsFactory.getOuterThisFieldDescriptor(innerClass) val outerThisField = context.specialDeclarationsFactory.getOuterThisField(innerClass)
irThis = IrGetFieldImpl(startOffset, endOffset, outerThisField, irThis, origin) irThis = IrGetFieldImpl(startOffset, endOffset, outerThisField.symbol, irThis, origin)
val outer = innerClass.containingDeclaration val outer = innerClass.containingDeclaration
innerClass = outer as? ClassDescriptor ?: innerClass = outer as? ClassDescriptor ?:
@@ -18,23 +18,21 @@ package org.jetbrains.kotlin.backend.konan.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irBlock
import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.descriptors.signature2Descriptor import org.jetbrains.kotlin.backend.konan.util.atMostOne
import org.jetbrains.kotlin.ir.builders.irLetSequence
import org.jetbrains.kotlin.builtins.PrimitiveType import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrSymbolDeclaration
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStringConcatenation import org.jetbrains.kotlin.ir.expressions.IrStringConcatenation
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.type
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
@@ -57,30 +55,36 @@ private class StringConcatenationTransformer(val lower: StringConcatenationLower
private val typesWithSpecialAppendFunction = private val typesWithSpecialAppendFunction =
PrimitiveType.values().map { builtIns.getPrimitiveKotlinType(it) } + builtIns.stringType PrimitiveType.values().map { builtIns.getPrimitiveKotlinType(it) } + builtIns.stringType
private val kotlinTextFqName = FqName.fromSegments(listOf("kotlin", "text"))
private val nameToString = Name.identifier("toString") private val nameToString = Name.identifier("toString")
private val nameStringBuilder = Name.identifier("StringBuilder")
private val nameAppend = Name.identifier("append") private val nameAppend = Name.identifier("append")
private val classStringBuilder = builtIns.builtInsModule.getPackage(kotlinTextFqName). private val stringBuilder = context.ir.symbols.stringBuilder
memberScope.getContributedClassifier(nameStringBuilder,
NoLookupLocation.FROM_BACKEND) as ClassDescriptor
//TODO: calculate and pass string length to the constructor. //TODO: calculate and pass string length to the constructor.
private val constructor = classStringBuilder.constructors.firstOrNull { private val constructor = stringBuilder.constructors.single {
it.valueParameters.size == 0 it.owner.valueParameters.size == 0
}!! }
private val toStringFunction = classStringBuilder.signature2Descriptor(nameToString)!! private val toStringFunction = stringBuilder.functions.single {
private val defaultAppendFunction = it.owner.valueParameters.size == 0 && it.descriptor.name == nameToString
classStringBuilder.signature2Descriptor(nameAppend, arrayOf(builtIns.nullableAnyType))!! }
private val defaultAppendFunction = stringBuilder.functions.single {
it.descriptor.name == nameAppend &&
it.owner.valueParameters.size == 1 &&
it.owner.valueParameters.single().type == builtIns.nullableAnyType
}
private val appendFunctions: Map<KotlinType, FunctionDescriptor?> =
typesWithSpecialAppendFunction.map { private val appendFunctions: Map<KotlinType, IrFunctionSymbol?> =
it to classStringBuilder.signature2Descriptor(nameAppend, arrayOf(it)) typesWithSpecialAppendFunction.map { type ->
type to stringBuilder.functions.toList().atMostOne {
it.descriptor.name == nameAppend &&
it.owner.valueParameters.size == 1 &&
it.owner.valueParameters.single().type == type
}
}.toMap() }.toMap()
private fun typeToAppendFunction(type : KotlinType) : FunctionDescriptor { private fun typeToAppendFunction(type : KotlinType) : IrFunctionSymbol {
return appendFunctions[type]?:defaultAppendFunction return appendFunctions[type]?:defaultAppendFunction
} }
@@ -89,11 +93,8 @@ private class StringConcatenationTransformer(val lower: StringConcatenationLower
expression.transformChildrenVoid(this) expression.transformChildrenVoid(this)
val blockBuilder = buildersStack.last() val blockBuilder = buildersStack.last()
return blockBuilder.irLetSequence( return blockBuilder.irBlock(expression) {
value = blockBuilder.irCall(constructor), val stringBuilderImpl = irTemporary(irCall(constructor)).symbol
startOffset = expression.startOffset,
endOffset = expression.endOffset,
resultType = expression.type) { stringBuilderImpl ->
expression.arguments.forEach { arg -> expression.arguments.forEach { arg ->
val appendFunction = typeToAppendFunction(arg.type) val appendFunction = typeToAppendFunction(arg.type)
+irCall(appendFunction).apply { +irCall(appendFunction).apply {
@@ -19,9 +19,7 @@ package org.jetbrains.kotlin.backend.konan.lower
import org.jetbrains.kotlin.backend.common.FunctionLoweringPass import org.jetbrains.kotlin.backend.common.FunctionLoweringPass
import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.common.lower.*
import org.jetbrains.kotlin.backend.konan.Context import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalFunctions
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.*
@@ -29,6 +27,7 @@ import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
@@ -42,19 +41,17 @@ import org.jetbrains.kotlin.types.typeUtil.makeNullable
*/ */
internal class TypeOperatorLowering(val context: Context) : FunctionLoweringPass { internal class TypeOperatorLowering(val context: Context) : FunctionLoweringPass {
override fun lower(irFunction: IrFunction) { override fun lower(irFunction: IrFunction) {
val transformer = TypeOperatorTransformer(context, irFunction.descriptor) val transformer = TypeOperatorTransformer(context, irFunction.symbol)
irFunction.transformChildrenVoid(transformer) irFunction.transformChildrenVoid(transformer)
} }
} }
private class TypeOperatorTransformer(val context: Context, val function: FunctionDescriptor) : IrElementTransformerVoid() { private class TypeOperatorTransformer(val context: Context, val function: IrFunctionSymbol) : IrElementTransformerVoid() {
private val builder = context.createIrBuilder(function) private val builder = context.createIrBuilder(function)
val throwTypeCastException by lazy { val throwTypeCastException = context.ir.symbols.ThrowTypeCastException
context.builtIns.getKonanInternalFunctions("ThrowTypeCastException").single()
}
override fun visitFunction(declaration: IrFunction): IrStatement { override fun visitFunction(declaration: IrFunction): IrStatement {
// ignore inner functions during this pass // ignore inner functions during this pass
@@ -93,7 +90,7 @@ private class TypeOperatorTransformer(val context: Context, val function: Functi
expression.argument.type.isNullable() -> { expression.argument.type.isNullable() -> {
with (builder) { with (builder) {
irLet(expression.argument) { argument -> irLetS(expression.argument) { argument ->
irIfThenElse( irIfThenElse(
type = expression.type, type = expression.type,
condition = irEqeqeq(irGet(argument), irNull()), condition = irEqeqeq(irGet(argument), irNull()),
@@ -123,7 +120,7 @@ private class TypeOperatorTransformer(val context: Context, val function: Functi
val typeOperand = expression.typeOperand.erasure() val typeOperand = expression.typeOperand.erasure()
return builder.irBlock(expression) { return builder.irBlock(expression) {
+irLet(expression.argument) { variable -> +irLetS(expression.argument) { variable ->
irIfThenElse(expression.type, irIfThenElse(expression.type,
condition = irIs(irGet(variable), typeOperand), condition = irIs(irGet(variable), typeOperand),
thenPart = irImplicitCast(irGet(variable), typeOperand), thenPart = irImplicitCast(irGet(variable), typeOperand),
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -138,31 +139,31 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar
descriptor = arrayHandle.setMethodDescriptor, descriptor = arrayHandle.setMethodDescriptor,
typeArguments = null typeArguments = null
) )
setArrayElementCall.dispatchReceiver = irGet(arrayTmpVariable.descriptor) setArrayElementCall.dispatchReceiver = irGet(arrayTmpVariable.symbol)
setArrayElementCall.putValueArgument(0, if (hasSpreadElement) irGet(indexTmpVariable.descriptor) else irConstInt(i)) setArrayElementCall.putValueArgument(0, if (hasSpreadElement) irGet(indexTmpVariable.symbol) else irConstInt(i))
setArrayElementCall.putValueArgument(1, irGet(dst.descriptor)) setArrayElementCall.putValueArgument(1, irGet(dst.symbol))
block.statements.add(setArrayElementCall) block.statements.add(setArrayElementCall)
if (hasSpreadElement) { if (hasSpreadElement) {
block.statements.add(incrementVariable(indexTmpVariable.descriptor, kIntOne)) block.statements.add(incrementVariable(indexTmpVariable.symbol, kIntOne))
} }
} else { } else {
val arraySizeVariable = scope.createTemporaryVariable(irArraySize(arrayHandle, irGet(dst.descriptor)), "length".synthesizedString) val arraySizeVariable = scope.createTemporaryVariable(irArraySize(arrayHandle, irGet(dst.symbol)), "length".synthesizedString)
block.statements.add(arraySizeVariable) block.statements.add(arraySizeVariable)
val copyCall = irCall(arrayHandle.copyRangeToDescriptor, null).apply { val copyCall = irCall(arrayHandle.copyRangeToDescriptor, null).apply {
extensionReceiver = irGet(dst.descriptor) extensionReceiver = irGet(dst.symbol)
putValueArgument(0, irGet(arrayTmpVariable.descriptor)) /* destination */ putValueArgument(0, irGet(arrayTmpVariable.symbol)) /* destination */
putValueArgument(1, kIntZero) /* fromIndex */ putValueArgument(1, kIntZero) /* fromIndex */
putValueArgument(2, irGet(arraySizeVariable.descriptor)) /* toIndex */ putValueArgument(2, irGet(arraySizeVariable.symbol)) /* toIndex */
putValueArgument(3, irGet(indexTmpVariable.descriptor)) /* destinationIndex */ putValueArgument(3, irGet(indexTmpVariable.symbol)) /* destinationIndex */
} }
block.statements.add(copyCall) block.statements.add(copyCall)
block.statements.add(incrementVariable(indexTmpVariable.descriptor, block.statements.add(incrementVariable(indexTmpVariable.symbol,
irGet(arraySizeVariable.descriptor))) irGet(arraySizeVariable.symbol)))
log("element:$i:spread element> ${ir2string(element.expression)}") log("element:$i:spread element> ${ir2string(element.expression)}")
} }
} }
} }
block.statements.add(irGet(arrayTmpVariable.descriptor)) block.statements.add(irGet(arrayTmpVariable.symbol))
return block return block
} }
} }
@@ -203,9 +204,9 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar
} }
} }
private fun IrBuilderWithScope.incrementVariable(descriptor: VariableDescriptor, value: IrExpression): IrExpression { private fun IrBuilderWithScope.incrementVariable(symbol: IrVariableSymbol, value: IrExpression): IrExpression {
return irSetVar(descriptor, intPlus().apply { return irSetVar(symbol, intPlus().apply {
dispatchReceiver = irGet(descriptor) dispatchReceiver = irGet(symbol)
putValueArgument(0, value) putValueArgument(0, value)
}) })
} }
@@ -216,7 +217,7 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar
val notSpreadElementCount = expression.elements.filter { it !is IrSpreadElement}.size val notSpreadElementCount = expression.elements.filter { it !is IrSpreadElement}.size
val initialValue = irConstInt(notSpreadElementCount) as IrExpression val initialValue = irConstInt(notSpreadElementCount) as IrExpression
return vars.filter{it.key is IrSpreadElement}.toList().fold( initial = initialValue) { result, it -> return vars.filter{it.key is IrSpreadElement}.toList().fold( initial = initialValue) { result, it ->
val arraySize = irArraySize(arrayHandle, irGet(it.second.descriptor)) val arraySize = irArraySize(arrayHandle, irGet(it.second.symbol))
increment(result, arraySize) increment(result, arraySize)
} }
} }
@@ -0,0 +1,386 @@
package org.jetbrains.kotlin.ir.util
import org.jetbrains.kotlin.backend.common.pop
import org.jetbrains.kotlin.backend.common.push
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlock
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrAnonymousInitializer
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrBindableSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.psi2ir.generators.ModuleDependenciesGenerator
import org.jetbrains.kotlin.psi2ir.generators.SymbolTable
@Deprecated("")
internal fun IrModuleFragment.replaceUnboundSymbols(context: Context) {
val collector = DeclarationSymbolCollector()
with(collector) {
with(irBuiltins) {
for (op in arrayOf(eqeqeqFun, eqeqFun, lt0Fun, lteq0Fun, gt0Fun, gteq0Fun, throwNpeFun, booleanNotFun,
noWhenBranchMatchedExceptionFun)) {
register(op.symbol)
}
}
}
this.acceptVoid(collector)
val symbolTable = context.ir.symbols.symbolTable
this.transformChildrenVoid(IrUnboundSymbolReplacer(symbolTable, collector.descriptorToSymbol))
// Generate missing external stubs:
ModuleDependenciesGenerator(context.psi2IrGeneratorContext).generateUnboundSymbolsAsDependencies(this)
// Merge duplicated module and package declarations:
this.acceptVoid(object : IrElementVisitorVoid {
override fun visitElement(element: IrElement) {}
override fun visitModuleFragment(declaration: IrModuleFragment) {
declaration.dependencyModules.forEach { it.acceptVoid(this) }
val dependencyModules = declaration.dependencyModules.groupBy { it.descriptor }.map { (_, fragments) ->
fragments.reduce { firstModule, nextModule ->
firstModule.apply {
mergeFrom(nextModule)
}
}
}
declaration.dependencyModules.clear()
declaration.dependencyModules.addAll(dependencyModules)
}
})
}
private fun IrModuleFragment.mergeFrom(other: IrModuleFragment): Unit {
assert(this.files.isEmpty())
assert(other.files.isEmpty())
val thisPackages = this.externalPackageFragments.groupBy { it.packageFragmentDescriptor }
other.externalPackageFragments.forEach {
val thisPackage = thisPackages[it.packageFragmentDescriptor]?.single()
if (thisPackage == null) {
this.externalPackageFragments.add(it)
} else {
thisPackage.declarations.addAll(it.declarations)
}
}
}
private class DeclarationSymbolCollector : IrElementVisitorVoid {
val descriptorToSymbol = mutableMapOf<DeclarationDescriptor, IrSymbol>()
fun register(symbol: IrSymbol) {
descriptorToSymbol[symbol.descriptor] = symbol
}
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
if (element is IrSymbolOwner && element !is IrAnonymousInitializer) {
register(element.symbol)
}
}
}
private class IrUnboundSymbolReplacer(
val symbolTable: SymbolTable,
val descriptorToSymbol: Map<DeclarationDescriptor, IrSymbol>
) : IrElementTransformerVoid() {
private inline fun <D : DeclarationDescriptor, reified S : IrBindableSymbol<D, *>> S.replace(
referenceSymbol: (SymbolTable, D) -> S): S? {
if (this.isBound) {
return null
}
descriptorToSymbol[this.descriptor]?.let {
return it as S
}
return referenceSymbol(symbolTable, this.descriptor)
}
private inline fun <D : DeclarationDescriptor, reified S : IrBindableSymbol<D, *>> S.replaceOrSame(
referenceSymbol: (SymbolTable, D) -> S): S = this.replace(referenceSymbol) ?: this
private fun IrFunctionSymbol.replace(
referenceSymbol: (SymbolTable, FunctionDescriptor) -> IrFunctionSymbol): IrFunctionSymbol? {
if (this.isBound) {
return null
}
descriptorToSymbol[this.descriptor]?.let {
return it as IrFunctionSymbol
}
return referenceSymbol(symbolTable, this.descriptor)
}
private inline fun <reified S : IrSymbol> S.replaceLocal(): S? {
return if (this.isBound) {
null
} else {
descriptorToSymbol[this.descriptor] as S
}
}
override fun visitGetValue(expression: IrGetValue): IrExpression {
val symbol = expression.symbol.replaceLocal() ?: return super.visitGetValue(expression)
expression.transformChildrenVoid(this)
return with(expression) {
IrGetValueImpl(startOffset, endOffset, symbol, origin)
}
}
override fun visitSetVariable(expression: IrSetVariable): IrExpression {
val symbol = expression.symbol.replaceLocal() ?: return super.visitSetVariable(expression)
expression.transformChildrenVoid(this)
return with(expression) {
IrSetVariableImpl(startOffset, endOffset, symbol, value, origin)
}
}
override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression {
val symbol = expression.symbol.replace(SymbolTable::referenceClass) ?:
return super.visitGetObjectValue(expression)
expression.transformChildrenVoid(this)
return with(expression) {
IrGetObjectValueImpl(startOffset, endOffset, type, symbol)
}
}
override fun visitGetEnumValue(expression: IrGetEnumValue): IrExpression {
val symbol = expression.symbol.replace(SymbolTable::referenceEnumEntry) ?:
return super.visitGetEnumValue(expression)
expression.transformChildrenVoid(this)
return with(expression) {
IrGetEnumValueImpl(startOffset, endOffset, type, symbol)
}
}
override fun visitClassReference(expression: IrClassReference): IrExpression {
val symbol = expression.symbol.let {
if (it.isBound) {
return super.visitClassReference(expression)
}
descriptorToSymbol[it.descriptor]?.let {
it as IrClassifierSymbol
}
symbolTable.referenceClassifier(it.descriptor)
}
expression.transformChildrenVoid(this)
return with(expression) {
IrClassReferenceImpl(startOffset, endOffset, type, symbol)
}
}
override fun visitGetField(expression: IrGetField): IrExpression {
val symbol = expression.symbol.replaceOrSame(SymbolTable::referenceField)
val superQualifierSymbol = expression.superQualifierSymbol?.replaceOrSame(SymbolTable::referenceClass)
if (symbol == expression.symbol && superQualifierSymbol == expression.superQualifierSymbol) {
return super.visitGetField(expression)
}
expression.transformChildrenVoid(this)
return with(expression) {
IrGetFieldImpl(startOffset, endOffset, symbol, receiver, origin, superQualifierSymbol)
}
}
override fun visitSetField(expression: IrSetField): IrExpression {
val symbol = expression.symbol.replaceOrSame(SymbolTable::referenceField)
val superQualifierSymbol = expression.superQualifierSymbol?.replaceOrSame(SymbolTable::referenceClass)
if (symbol == expression.symbol && superQualifierSymbol == expression.superQualifierSymbol) {
return super.visitSetField(expression)
}
expression.transformChildrenVoid(this)
return with(expression) {
IrSetFieldImpl(startOffset, endOffset, symbol, receiver, value, origin, superQualifierSymbol)
}
}
override fun visitCall(expression: IrCall): IrExpression {
val symbol = expression.symbol.replace(SymbolTable::referenceFunction) ?: expression.symbol
val superQualifierSymbol = expression.superQualifierSymbol?.replaceOrSame(SymbolTable::referenceClass)
if (symbol == expression.symbol && superQualifierSymbol == expression.superQualifierSymbol) {
return super.visitCall(expression)
}
expression.transformChildrenVoid()
return with(expression) {
IrCallImpl(startOffset, endOffset, symbol, descriptor,
getTypeArgumentsMap(),
origin, superQualifierSymbol).also {
it.copyArgumentsFrom(this)
}
}
}
private fun IrMemberAccessExpression.getTypeArgumentsMap() =
descriptor.original.typeParameters.associate { it to getTypeArgumentOrDefault(it) }
private fun IrMemberAccessExpressionBase.copyArgumentsFrom(original: IrMemberAccessExpression) {
dispatchReceiver = original.dispatchReceiver
extensionReceiver = original.extensionReceiver
original.descriptor.valueParameters.forEachIndexed { index, _ ->
putValueArgument(index, original.getValueArgument(index))
}
}
override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrExpression {
val symbol = expression.symbol.replace(SymbolTable::referenceConstructor) ?:
return super.visitEnumConstructorCall(expression)
return with(expression) {
IrEnumConstructorCallImpl(startOffset, endOffset, symbol).also {
it.copyArgumentsFrom(this)
}
}
}
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
val symbol = expression.symbol.replace(SymbolTable::referenceConstructor) ?:
return super.visitDelegatingConstructorCall(expression)
expression.transformChildrenVoid()
return with(expression) {
IrDelegatingConstructorCallImpl(startOffset, endOffset, symbol, descriptor, getTypeArgumentsMap()).also {
it.copyArgumentsFrom(this)
}
}
}
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
val symbol = expression.symbol.replace(SymbolTable::referenceFunction) ?:
return super.visitFunctionReference(expression)
expression.transformChildrenVoid(this)
return with(expression) {
IrFunctionReferenceImpl(startOffset, endOffset, type, symbol, descriptor, getTypeArgumentsMap()).also {
it.copyArgumentsFrom(this)
}
}
}
override fun visitPropertyReference(expression: IrPropertyReference): IrExpression {
val field = expression.field?.replaceOrSame(SymbolTable::referenceField)
val getter = expression.getter?.replace(SymbolTable::referenceFunction) ?: expression.getter
val setter = expression.setter?.replace(SymbolTable::referenceFunction) ?: expression.setter
if (field == expression.field && getter == expression.getter && setter == expression.setter) {
return super.visitPropertyReference(expression)
}
expression.transformChildrenVoid(this)
return with(expression) {
IrPropertyReferenceImpl(startOffset, endOffset, type, descriptor,
field,
getter,
setter,
getTypeArgumentsMap(), origin).also {
it.copyArgumentsFrom(this)
}
}
}
override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference): IrExpression {
val delegate = expression.delegate.replaceOrSame(SymbolTable::referenceVariable)
val getter = expression.getter.replace(SymbolTable::referenceFunction) ?: expression.getter
val setter = expression.setter?.replace(SymbolTable::referenceFunction) ?: expression.setter
if (delegate == expression.delegate && getter == expression.getter && setter == expression.setter) {
return super.visitLocalDelegatedPropertyReference(expression)
}
expression.transformChildrenVoid(this)
return with(expression) {
IrLocalDelegatedPropertyReferenceImpl(startOffset, endOffset, type, descriptor,
delegate, getter, setter, origin).also {
it.copyArgumentsFrom(this)
}
}
}
private val returnTargetStack = mutableListOf<IrFunctionSymbol>()
override fun visitFunction(declaration: IrFunction): IrStatement {
returnTargetStack.push(declaration.symbol)
try {
return super.visitFunction(declaration)
} finally {
returnTargetStack.pop()
}
}
override fun visitBlock(expression: IrBlock): IrExpression {
if (expression is IrReturnableBlock) {
returnTargetStack.push(expression.symbol)
try {
return super.visitBlock(expression)
} finally {
returnTargetStack.pop()
}
} else {
return super.visitBlock(expression)
}
}
override fun visitReturn(expression: IrReturn): IrExpression {
if (expression.returnTargetSymbol.isBound) {
return super.visitReturn(expression)
}
val returnTargetSymbol = returnTargetStack.last { it.descriptor == expression.returnTarget }
expression.transformChildrenVoid(this)
return with(expression) {
IrReturnImpl(startOffset, endOffset, type, returnTargetSymbol, value)
}
}
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall): IrExpression {
val classSymbol = expression.classSymbol.replace(SymbolTable::referenceClass) ?:
return super.visitInstanceInitializerCall(expression)
expression.transformChildrenVoid(this)
return with(expression) {
IrInstanceInitializerCallImpl(startOffset, endOffset, classSymbol)
}
}
}
@@ -19,17 +19,21 @@ package org.jetbrains.kotlin.ir.util
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
import org.jetbrains.kotlin.descriptors.ParameterDescriptor import org.jetbrains.kotlin.descriptors.ParameterDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.resolve.source.PsiSourceElement import org.jetbrains.kotlin.resolve.source.PsiSourceElement
import org.jetbrains.kotlin.types.KotlinType
/** /**
* Binds the arguments explicitly represented in the IR to the parameters of the accessed function. * Binds the arguments explicitly represented in the IR to the parameters of the accessed function.
@@ -59,6 +63,32 @@ internal fun IrMemberAccessExpression.getArguments(): List<Pair<ParameterDescrip
return res return res
} }
/**
* Binds the arguments explicitly represented in the IR to the parameters of the accessed function.
* The arguments are to be evaluated in the same order as they appear in the resulting list.
*/
internal fun IrFunctionAccessExpression.getArgumentsWithSymbols(): List<Pair<IrValueParameterSymbol, IrExpression>> {
val res = mutableListOf<Pair<IrValueParameterSymbol, IrExpression>>()
val irFunction = symbol.owner as IrFunction
dispatchReceiver?.let {
res += (irFunction.dispatchReceiverParameter!!.symbol to it)
}
extensionReceiver?.let {
res += (irFunction.extensionReceiverParameter!!.symbol to it)
}
irFunction.valueParameters.forEach {
val arg = getValueArgument(it.descriptor as ValueParameterDescriptor)
if (arg != null) {
res += (it.symbol to arg)
}
}
return res
}
/** /**
* Sets arguments that are specified by given mapping of parameters. * Sets arguments that are specified by given mapping of parameters.
*/ */
@@ -146,7 +176,93 @@ fun IrClass.createParameterDeclarations() {
} }
private fun IrElement.innerStartOffset(descriptor: DeclarationDescriptorWithSource): Int = private fun IrElement.innerStartOffset(descriptor: DeclarationDescriptorWithSource): Int =
(descriptor.source as? PsiSourceElement)?.psi?.startOffset ?: this.startOffset descriptor.startOffset ?: this.startOffset
private fun IrElement.innerEndOffset(descriptor: DeclarationDescriptorWithSource): Int = private fun IrElement.innerEndOffset(descriptor: DeclarationDescriptorWithSource): Int =
(descriptor.source as? PsiSourceElement)?.psi?.endOffset ?: this.endOffset descriptor.endOffset ?: this.endOffset
val DeclarationDescriptorWithSource.startOffset: Int? get() = (this.source as? PsiSourceElement)?.psi?.startOffset
val DeclarationDescriptorWithSource.endOffset: Int? get() = (this.source as? PsiSourceElement)?.psi?.endOffset
val DeclarationDescriptorWithSource.startOffsetOrUndefined: Int get() = startOffset ?: UNDEFINED_OFFSET
val DeclarationDescriptorWithSource.endOffsetOrUndefined: Int get() = endOffset ?: UNDEFINED_OFFSET
val IrClassSymbol.functions: Sequence<IrSimpleFunctionSymbol>
get() = this.owner.declarations.asSequence().filterIsInstance<IrSimpleFunction>().map { it.symbol }
val IrClassSymbol.constructors: Sequence<IrConstructorSymbol>
get() = this.owner.declarations.asSequence().filterIsInstance<IrConstructor>().map { it.symbol }
val IrFunction.explicitParameters: List<IrValueParameterSymbol>
get() = (listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters).map { it.symbol }
val IrValueParameter.type: KotlinType
get() = this.descriptor.type
val IrClass.defaultType: KotlinType
get() = this.descriptor.defaultType
class IrSymbolBindingChecker : IrElementVisitorVoid {
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
override fun visitDeclarationReference(expression: IrDeclarationReference) {
super.visitDeclarationReference(expression)
expression.symbol.ensureBound(expression)
}
override fun visitFunctionAccess(expression: IrFunctionAccessExpression) {
super.visitFunctionAccess(expression)
expression.symbol.ensureBound(expression)
}
override fun visitFunctionReference(expression: IrFunctionReference) {
super.visitFunctionReference(expression)
expression.symbol.ensureBound(expression)
}
override fun visitCall(expression: IrCall) {
super.visitCall(expression)
expression.superQualifierSymbol?.ensureBound(expression)
}
override fun visitPropertyReference(expression: IrPropertyReference) {
super.visitPropertyReference(expression)
expression.field?.ensureBound(expression)
expression.getter?.ensureBound(expression)
expression.setter?.ensureBound(expression)
}
override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference) {
super.visitLocalDelegatedPropertyReference(expression)
expression.delegate.ensureBound(expression)
expression.getter.ensureBound(expression)
expression.setter?.ensureBound(expression)
}
override fun visitReturn(expression: IrReturn) {
super.visitReturn(expression)
expression.returnTargetSymbol.ensureBound(expression)
}
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall) {
super.visitInstanceInitializerCall(expression)
expression.classSymbol.ensureBound(expression)
}
private fun IrSymbol.ensureBound(expression: IrExpression) {
if (!this.isBound) {
throw Error("Unbound symbol ${this} found in ${expression.render()}")
}
}
}