Update compiler to IR with symbols, part 2 (#581)
The symbols produced by first lowering phases are now bound
This commit is contained in:
committed by
GitHub
parent
3000b1ec41
commit
c9d7f976a5
+80
-3
@@ -20,14 +20,26 @@ import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlock
|
||||
import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlockImpl
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBlock
|
||||
import org.jetbrains.kotlin.ir.expressions.IrLoop
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
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.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;
|
||||
* updates the references to these declarations.
|
||||
*/
|
||||
@Deprecated("Creates unbound symbols")
|
||||
open class DeepCopyIrTreeWithDeclarations : DeepCopyIrTree() {
|
||||
|
||||
private fun DeclarationDescriptor.notSupported(): Nothing = TODO("${this}")
|
||||
@@ -95,4 +107,69 @@ open class DeepCopyIrTreeWithDeclarations : DeepCopyIrTree() {
|
||||
override fun getNonTransformedLoop(irLoop: IrLoop): 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
|
||||
+6
-6
@@ -38,7 +38,7 @@ abstract internal class IrElementTransformerVoidWithContext : IrElementTransform
|
||||
}
|
||||
|
||||
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)
|
||||
scopeStack.pop()
|
||||
return result
|
||||
@@ -52,14 +52,14 @@ abstract internal class IrElementTransformerVoidWithContext : IrElementTransform
|
||||
}
|
||||
|
||||
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)
|
||||
scopeStack.pop()
|
||||
return result
|
||||
}
|
||||
|
||||
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)
|
||||
scopeStack.pop()
|
||||
return result
|
||||
@@ -102,13 +102,13 @@ abstract internal class IrElementVisitorVoidWithContext : IrElementVisitorVoid {
|
||||
private val scopeStack = mutableListOf<ScopeWithIr>()
|
||||
|
||||
override final fun visitFile(declaration: IrFile) {
|
||||
scopeStack.push(ScopeWithIr(Scope(declaration.packageFragmentDescriptor), declaration))
|
||||
scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration))
|
||||
visitFileNew(declaration)
|
||||
scopeStack.pop()
|
||||
}
|
||||
|
||||
override final fun visitClass(declaration: IrClass) {
|
||||
scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration))
|
||||
scopeStack.push(ScopeWithIr(Scope(declaration.symbol), declaration))
|
||||
visitClassNew(declaration)
|
||||
scopeStack.pop()
|
||||
}
|
||||
@@ -121,7 +121,7 @@ abstract internal class IrElementVisitorVoidWithContext : IrElementVisitorVoid {
|
||||
|
||||
override final fun visitField(declaration: IrField) {
|
||||
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)
|
||||
if (isDelegated) scopeStack.pop()
|
||||
}
|
||||
|
||||
+1
-1
@@ -203,7 +203,7 @@ private class IrValidator(val context: BackendContext, performHeavyValidations:
|
||||
|
||||
private fun recordDeclaration(declaration: IrDeclaration) {
|
||||
if (foundDeclarations.isAlreadyDeclared(declaration)) {
|
||||
if (declaration.descriptor !is ReceiverParameterDescriptor && declaration !is IrTypeParameter) {
|
||||
if (declaration !is IrValueParameter && declaration !is IrTypeParameter) {
|
||||
// TODO: remove the check.
|
||||
error(declaration, "redeclaration")
|
||||
}
|
||||
|
||||
+9
-8
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCatch
|
||||
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
|
||||
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.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
@@ -30,7 +31,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
|
||||
// TODO: synchronize with JVM BE
|
||||
// TODO: rename the file.
|
||||
class Closure(val capturedValues: List<ValueDescriptor> = emptyList())
|
||||
class Closure(val capturedValues: List<IrValueSymbol> = emptyList())
|
||||
|
||||
class ClosureAnnotator {
|
||||
private val closureBuilders = mutableMapOf<DeclarationDescriptor, ClosureBuilder>()
|
||||
@@ -51,7 +52,7 @@ class ClosureAnnotator {
|
||||
}
|
||||
|
||||
private class ClosureBuilder(val owner: DeclarationDescriptor) {
|
||||
val capturedValues = mutableSetOf<ValueDescriptor>()
|
||||
val capturedValues = mutableSetOf<IrValueSymbol>()
|
||||
private val declaredValues = mutableSetOf<ValueDescriptor>()
|
||||
private val includes = mutableSetOf<ClosureBuilder>()
|
||||
|
||||
@@ -63,11 +64,11 @@ class ClosureAnnotator {
|
||||
* variables declared in the node.
|
||||
*/
|
||||
fun buildClosure(): Closure {
|
||||
val result = mutableSetOf<ValueDescriptor>().apply { addAll(capturedValues) }
|
||||
val result = mutableSetOf<IrValueSymbol>().apply { addAll(capturedValues) }
|
||||
includes.forEach {
|
||||
if (!it.processed) {
|
||||
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.
|
||||
@@ -84,9 +85,9 @@ class ClosureAnnotator {
|
||||
declaredValues.add(valueDescriptor)
|
||||
}
|
||||
|
||||
fun seeVariable(valueDescriptor: ValueDescriptor) {
|
||||
if (isExternal(valueDescriptor))
|
||||
capturedValues.add(valueDescriptor)
|
||||
fun seeVariable(value: IrValueSymbol) {
|
||||
if (isExternal(value.descriptor))
|
||||
capturedValues.add(value)
|
||||
}
|
||||
|
||||
fun isExternal(valueDescriptor: ValueDescriptor): Boolean {
|
||||
@@ -159,7 +160,7 @@ class ClosureAnnotator {
|
||||
}
|
||||
|
||||
override fun visitVariableAccess(expression: IrValueAccessExpression) {
|
||||
closuresStack.peek()?.seeVariable(expression.descriptor)
|
||||
closuresStack.peek()?.seeVariable(expression.symbol)
|
||||
super.visitVariableAccess(expression)
|
||||
}
|
||||
|
||||
|
||||
+91
-74
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
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.transformFlat
|
||||
import org.jetbrains.kotlin.ir.visitors.*
|
||||
@@ -78,13 +79,14 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
|
||||
get() = declaration.descriptor
|
||||
|
||||
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? {
|
||||
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
|
||||
|
||||
override lateinit var transformedDescriptor: FunctionDescriptor
|
||||
override lateinit var transformedDeclaration: IrSimpleFunction
|
||||
|
||||
var index: Int = -1
|
||||
|
||||
@@ -104,6 +107,7 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
|
||||
get() = declaration.descriptor
|
||||
|
||||
override lateinit var transformedDescriptor: ClassConstructorDescriptor
|
||||
override lateinit var transformedDeclaration: IrConstructor
|
||||
|
||||
override fun toString(): String =
|
||||
"LocalClassConstructorContext for $descriptor"
|
||||
@@ -115,13 +119,13 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
|
||||
|
||||
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? {
|
||||
val fieldDescriptor = capturedValueToField[descriptor] ?: return null
|
||||
val field = capturedValueToField[descriptor] ?: return null
|
||||
|
||||
return IrGetFieldImpl(startOffset, endOffset, fieldDescriptor,
|
||||
receiver = IrGetValueImpl(startOffset, endOffset, this.descriptor.thisAsReceiverParameter)
|
||||
return IrGetFieldImpl(startOffset, endOffset, field.symbol,
|
||||
receiver = IrGetValueImpl(startOffset, endOffset, declaration.thisReceiver!!.symbol)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -134,14 +138,14 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
|
||||
val localClasses: MutableMap<ClassDescriptor, LocalClassContext> = LinkedHashMap()
|
||||
val localClassConstructors: MutableMap<ClassConstructorDescriptor, LocalClassConstructorContext> = LinkedHashMap()
|
||||
|
||||
val transformedDescriptors = mutableMapOf<DeclarationDescriptor, DeclarationDescriptor>()
|
||||
val transformedDeclarations = mutableMapOf<DeclarationDescriptor, IrSymbol>()
|
||||
|
||||
val FunctionDescriptor.transformed: FunctionDescriptor?
|
||||
get() = transformedDescriptors[this] as FunctionDescriptor?
|
||||
val FunctionDescriptor.transformed: IrFunctionSymbol?
|
||||
get() = transformedDeclarations[this] as IrFunctionSymbol?
|
||||
|
||||
val oldParameterToNew: MutableMap<ParameterDescriptor, ParameterDescriptor> = HashMap()
|
||||
val oldParameterToNew: MutableMap<ParameterDescriptor, IrValueParameterSymbol> = HashMap()
|
||||
val newParameterToOld: MutableMap<ParameterDescriptor, ParameterDescriptor> = HashMap()
|
||||
val newParameterToCaptured: MutableMap<ValueParameterDescriptor, ValueDescriptor> = HashMap()
|
||||
val newParameterToCaptured: MutableMap<ValueParameterDescriptor, IrValueSymbol> = HashMap()
|
||||
|
||||
fun lowerLocalDeclarations(): List<IrDeclaration>? {
|
||||
collectLocalDeclarations()
|
||||
@@ -163,16 +167,12 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
|
||||
|
||||
localFunctions.values.mapTo(this) {
|
||||
val original = it.declaration
|
||||
IrFunctionImpl(
|
||||
original.startOffset, original.endOffset, original.origin,
|
||||
it.transformedDescriptor,
|
||||
original.body
|
||||
).apply {
|
||||
createParameterDeclarations()
|
||||
it.transformedDeclaration.apply {
|
||||
this.body = original.body
|
||||
|
||||
original.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { 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 {
|
||||
// Body is transformed separately. See loop over constructors in rewriteDeclarations().
|
||||
|
||||
val transformedDescriptor = localClassConstructors[declaration.descriptor]?.transformedDescriptor
|
||||
if (transformedDescriptor != null) {
|
||||
return IrConstructorImpl(declaration.startOffset, declaration.endOffset, declaration.origin,
|
||||
transformedDescriptor, declaration.body!!).apply {
|
||||
|
||||
createParameterDeclarations()
|
||||
val constructorContext = localClassConstructors[declaration.descriptor]
|
||||
if (constructorContext != null) {
|
||||
return constructorContext.transformedDeclaration.apply {
|
||||
this.body = declaration.body!!
|
||||
|
||||
declaration.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument ->
|
||||
val body = declaration.getDefault(argument)!!
|
||||
this.putDefault(oldParameterToNew[argument] as ValueParameterDescriptor, body)
|
||||
oldParameterToNew[argument]!!.owner.defaultValue = body
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -251,12 +249,13 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
val oldCallee = expression.descriptor.original
|
||||
val newCallee = transformedDescriptors[oldCallee] as ClassConstructorDescriptor? ?: return expression
|
||||
val newCallee = transformedDeclarations[oldCallee] as IrConstructorSymbol? ?: return expression
|
||||
|
||||
val newExpression = IrDelegatingConstructorCallImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
newCallee,
|
||||
remapTypeArguments(expression, newCallee)
|
||||
newCallee.descriptor,
|
||||
remapTypeArguments(expression, newCallee.descriptor)
|
||||
).fillArguments(expression)
|
||||
|
||||
return newExpression
|
||||
@@ -271,17 +270,18 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
|
||||
oldExpression.getValueArgument(oldParameter as ValueParameterDescriptor)
|
||||
} else {
|
||||
// The callee expects captured value as argument.
|
||||
val capturedValueDescriptor =
|
||||
val capturedValueSymbol =
|
||||
newParameterToCaptured[newValueParameterDescriptor] ?:
|
||||
throw AssertionError("Non-mapped parameter $newValueParameterDescriptor")
|
||||
|
||||
val capturedValueDescriptor = capturedValueSymbol.descriptor
|
||||
localContext?.irGet(
|
||||
oldExpression.startOffset, oldExpression.endOffset,
|
||||
capturedValueDescriptor
|
||||
) ?:
|
||||
// Captured value is directly available for the caller.
|
||||
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.type, // TODO functional type for transformed descriptor
|
||||
newCallee,
|
||||
remapTypeArguments(expression, newCallee),
|
||||
newCallee.descriptor,
|
||||
remapTypeArguments(expression, newCallee.descriptor),
|
||||
expression.origin
|
||||
).fillArguments(expression)
|
||||
|
||||
@@ -319,14 +320,14 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
|
||||
}
|
||||
|
||||
override fun visitDeclarationReference(expression: IrDeclarationReference): IrExpression {
|
||||
if (expression.descriptor in transformedDescriptors) {
|
||||
if (expression.descriptor in transformedDeclarations) {
|
||||
TODO()
|
||||
}
|
||||
return super.visitDeclarationReference(expression)
|
||||
}
|
||||
|
||||
override fun visitDeclaration(declaration: IrDeclaration): IrStatement {
|
||||
if (declaration.descriptor in transformedDescriptors) {
|
||||
if (declaration.descriptor in transformedDeclarations) {
|
||||
TODO()
|
||||
}
|
||||
return super.visitDeclaration(declaration)
|
||||
@@ -352,24 +353,18 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
|
||||
.filter { it.declaration.callsSuper() }
|
||||
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 endOffset = irClass.endOffset
|
||||
irClass.declarations.add(
|
||||
IrFieldImpl(
|
||||
startOffset, endOffset,
|
||||
DECLARATION_ORIGIN_FIELD_FOR_CAPTURED_VALUE,
|
||||
fieldDescriptor
|
||||
)
|
||||
)
|
||||
irClass.declarations.add(field)
|
||||
|
||||
for (constructorContext in constructorsCallingSuper) {
|
||||
val blockBody = constructorContext.declaration.body as? IrBlockBody
|
||||
?: throw AssertionError("Unexpected constructor body: ${constructorContext.declaration.body}")
|
||||
val capturedValueExpression = constructorContext.irGet(startOffset, endOffset, capturedValue)!!
|
||||
blockBody.statements.add(0,
|
||||
IrSetFieldImpl(startOffset, endOffset, fieldDescriptor,
|
||||
IrGetValueImpl(startOffset, endOffset, classDescriptor.thisAsReceiverParameter),
|
||||
IrSetFieldImpl(startOffset, endOffset, field.symbol,
|
||||
IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol),
|
||||
capturedValueExpression, STATEMENT_ORIGIN_INITIALIZER_OF_FIELD_FOR_CAPTURED_VALUE))
|
||||
}
|
||||
}
|
||||
@@ -391,15 +386,16 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
|
||||
rewriteFunctionBody(memberDeclaration, null)
|
||||
}
|
||||
|
||||
private fun createNewCall(oldCall: IrCall, newCallee: FunctionDescriptor) =
|
||||
private fun createNewCall(oldCall: IrCall, newCallee: IrFunctionSymbol) =
|
||||
if (oldCall is IrCallWithShallowCopy)
|
||||
oldCall.shallowCopy(oldCall.origin, newCallee, oldCall.superQualifier)
|
||||
oldCall.shallowCopy(oldCall.origin, newCallee, oldCall.superQualifierSymbol)
|
||||
else
|
||||
IrCallImpl(
|
||||
oldCall.startOffset, oldCall.endOffset,
|
||||
newCallee,
|
||||
remapTypeArguments(oldCall, newCallee),
|
||||
oldCall.origin, oldCall.superQualifier
|
||||
newCallee.descriptor,
|
||||
remapTypeArguments(oldCall, newCallee.descriptor),
|
||||
oldCall.origin, oldCall.superQualifierSymbol
|
||||
)
|
||||
|
||||
private fun remapTypeArguments(oldExpression: IrMemberAccessExpression, newCallee: CallableDescriptor): Map<TypeParameterDescriptor, KotlinType>? {
|
||||
@@ -463,7 +459,6 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
|
||||
}
|
||||
|
||||
localFunctionContext.transformedDescriptor = newDescriptor
|
||||
transformedDescriptors[oldDescriptor] = newDescriptor
|
||||
|
||||
if (oldDescriptor.dispatchReceiverParameter != null) {
|
||||
throw AssertionError("local functions must not have dispatch receiver")
|
||||
@@ -490,12 +485,20 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
|
||||
)
|
||||
|
||||
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,
|
||||
capturedValues: List<ValueDescriptor>)
|
||||
capturedValues: List<IrValueSymbol>)
|
||||
: List<ValueParameterDescriptor> {
|
||||
|
||||
val oldDescriptor = localContext.descriptor
|
||||
@@ -505,21 +508,39 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
|
||||
val newValueParametersCount = closureParametersCount + oldDescriptor.valueParameters.size
|
||||
|
||||
val newValueParameters = ArrayList<ValueParameterDescriptor>(newValueParametersCount).apply {
|
||||
capturedValues.mapIndexedTo(this) { i, capturedValueDescriptor ->
|
||||
createUnsubstitutedCapturedValueParameter(newDescriptor, capturedValueDescriptor, i).apply {
|
||||
localContext.recordCapturedAsParameter(capturedValueDescriptor, this)
|
||||
capturedValues.mapIndexedTo(this) { i, capturedValue ->
|
||||
createUnsubstitutedCapturedValueParameter(newDescriptor, capturedValue.descriptor, i).apply {
|
||||
newParameterToCaptured[this] = capturedValue
|
||||
}
|
||||
}
|
||||
|
||||
oldDescriptor.valueParameters.mapIndexedTo(this) { i, oldValueParameterDescriptor ->
|
||||
createUnsubstitutedParameter(newDescriptor, oldValueParameterDescriptor, closureParametersCount + i).apply {
|
||||
recordRemappedParameter(oldValueParameterDescriptor, this)
|
||||
newParameterToOld.putAbsentOrSame(this, oldValueParameterDescriptor)
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
val oldDescriptor = constructorContext.descriptor
|
||||
val localClassContext = localClasses[oldDescriptor.containingDeclaration]!!
|
||||
@@ -528,7 +549,6 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
|
||||
Annotations.EMPTY, oldDescriptor.isPrimary, oldDescriptor.source)
|
||||
|
||||
constructorContext.transformedDescriptor = newDescriptor
|
||||
transformedDescriptors[oldDescriptor] = newDescriptor
|
||||
|
||||
// Do not substitute type parameters for now.
|
||||
val newTypeParameters = oldDescriptor.typeParameters
|
||||
@@ -545,12 +565,20 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
|
||||
newDescriptor.returnType = oldDescriptor.returnType
|
||||
|
||||
oldDescriptor.dispatchReceiverParameter?.let {
|
||||
recordRemappedParameter(it, newDescriptor.dispatchReceiverParameter!!)
|
||||
newParameterToOld.putAbsentOrSame(newDescriptor.dispatchReceiverParameter!!, it)
|
||||
}
|
||||
|
||||
oldDescriptor.extensionReceiverParameter?.let {
|
||||
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) {
|
||||
@@ -563,7 +591,7 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
|
||||
Modality.FINAL,
|
||||
Visibilities.PRIVATE,
|
||||
/* isVar = */ false,
|
||||
suggestNameForCapturedValue(capturedValue),
|
||||
suggestNameForCapturedValue(capturedValue.descriptor),
|
||||
CallableMemberDescriptor.Kind.SYNTHESIZED,
|
||||
SourceElement.NO_SOURCE,
|
||||
/* lateInit = */ false,
|
||||
@@ -578,25 +606,19 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
|
||||
val extensionReceiverParameter: ReceiverParameterDescriptor? = null
|
||||
|
||||
fieldDescriptor.setType(
|
||||
capturedValue.type,
|
||||
capturedValue.descriptor.type,
|
||||
emptyList<TypeParameterDescriptor>(),
|
||||
classDescriptor.thisAsReceiverParameter,
|
||||
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) {
|
||||
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 =
|
||||
if (valueDescriptor.name.isSpecial) {
|
||||
val oldNameStr = valueDescriptor.name.asString()
|
||||
|
||||
+2
-3
@@ -126,11 +126,10 @@ fun IrBuilderWithScope.irNot(arg: IrExpression) =
|
||||
fun IrBuilderWithScope.irThrow(arg: IrExpression) =
|
||||
IrThrowImpl(startOffset, endOffset, context.builtIns.nothingType, arg)
|
||||
|
||||
fun IrBuilderWithScope.irCatch(parameter: VariableDescriptor, result: IrExpression) =
|
||||
fun IrBuilderWithScope.irCatch(catchParameter: IrVariable) =
|
||||
IrCatchImpl(
|
||||
startOffset, endOffset,
|
||||
IrVariableImpl(startOffset, endOffset, IrDeclarationOrigin.CATCH_PARAMETER, parameter),
|
||||
result
|
||||
catchParameter
|
||||
)
|
||||
|
||||
fun IrBuilderWithScope.irCast(arg: IrExpression, type: KotlinType, typeOperand: KotlinType) =
|
||||
|
||||
+33
-45
@@ -16,22 +16,16 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.common.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.BackendContext
|
||||
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.backend.common.*
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
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.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.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.transformChildrenVoid
|
||||
|
||||
@@ -53,11 +47,10 @@ private fun lowerTailRecursionCalls(context: BackendContext, irFunction: IrFunct
|
||||
return
|
||||
}
|
||||
|
||||
val descriptor = irFunction.descriptor
|
||||
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 {
|
||||
// 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:
|
||||
val parameterToNew = parameters.associate {
|
||||
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,
|
||||
@@ -94,16 +87,16 @@ private class BodyTransformer(
|
||||
val builder: IrBuilderWithScope,
|
||||
val irFunction: IrFunction,
|
||||
val loop: IrLoop,
|
||||
val parameterToNew: Map<ParameterDescriptor, ValueDescriptor>,
|
||||
val parameterToVariable: Map<ParameterDescriptor, IrVariableSymbol>,
|
||||
val parameterToNew: Map<IrValueParameterSymbol, IrValueSymbol>,
|
||||
val parameterToVariable: Map<IrValueParameterSymbol, IrVariableSymbol>,
|
||||
val tailRecursionCalls: Set<IrCall>
|
||||
) : IrElementTransformerVoid() {
|
||||
|
||||
val parameters = irFunction.descriptor.explicitParameters
|
||||
val parameters = irFunction.explicitParameters
|
||||
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
val value = parameterToNew[expression.descriptor] ?: return expression
|
||||
val value = parameterToNew[expression.symbol] ?: return expression
|
||||
return builder.at(expression).irGet(value)
|
||||
}
|
||||
|
||||
@@ -118,8 +111,8 @@ private class BodyTransformer(
|
||||
|
||||
private fun IrBuilderWithScope.genTailCall(expression: IrCall) = this.irBlock(expression) {
|
||||
// Get all specified arguments:
|
||||
val parameterToArgument = expression.getArguments().map { (parameter, argument) ->
|
||||
expression.descriptor.getOriginalParameter(parameter) to argument
|
||||
val parameterToArgument = expression.getArgumentsWithSymbols().map { (parameter, argument) ->
|
||||
parameter to argument
|
||||
}
|
||||
|
||||
// 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:
|
||||
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")
|
||||
|
||||
// Copy default value, mapping parameters to variables containing freshly computed arguments:
|
||||
val defaultValue = originalDefaultValue.transform(object : DeepCopyIrTreeWithDeclarations() {
|
||||
override fun mapValueReference(descriptor: ValueDescriptor): ValueDescriptor {
|
||||
return parameterToVariable[descriptor]?.descriptor ?: super.mapValueReference(descriptor)
|
||||
}
|
||||
}, data = null)
|
||||
val defaultValue = originalDefaultValue
|
||||
.deepCopyWithVariables()
|
||||
.transform(object : IrElementTransformerVoid() {
|
||||
|
||||
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)
|
||||
}
|
||||
@@ -153,23 +155,9 @@ private class BodyTransformer(
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrFunction.getDefaultArgumentExpression(parameter: ParameterDescriptor): IrExpression? {
|
||||
if (parameter !is ValueParameterDescriptor) {
|
||||
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()
|
||||
private fun IrValueParameterSymbol.suggestVariableName(): String = if (descriptor.name.isSpecial) {
|
||||
val oldNameStr = descriptor.name.asString()
|
||||
"$" + oldNameStr.substring(1, oldNameStr.length - 1)
|
||||
} else {
|
||||
name.identifier
|
||||
descriptor.name.identifier
|
||||
}
|
||||
+30
-15
@@ -32,15 +32,15 @@ import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.SourceManager
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.util.DumpIrTreeVisitor
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
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.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
@@ -55,22 +55,34 @@ import java.util.*
|
||||
import kotlin.LazyThreadSafetyMode.PUBLICATION
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
internal class SpecialDescriptorsFactory(val context: Context) {
|
||||
private val enumSpecialDescriptorsFactory by lazy { EnumSpecialDescriptorsFactory(context) }
|
||||
private val outerThisDescriptors = mutableMapOf<ClassDescriptor, PropertyDescriptor>()
|
||||
internal class SpecialDeclarationsFactory(val context: Context) {
|
||||
private val enumSpecialDeclarationsFactory by lazy { EnumSpecialDeclarationsFactory(context) }
|
||||
private val outerThisFields = mutableMapOf<ClassDescriptor, IrField>()
|
||||
private val bridgesDescriptors = mutableMapOf<Pair<FunctionDescriptor, BridgeDirections>, FunctionDescriptor>()
|
||||
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")
|
||||
else outerThisDescriptors.getOrPut(innerClassDescriptor) {
|
||||
else outerThisFields.getOrPut(innerClassDescriptor) {
|
||||
val outerClassDescriptor = DescriptorUtils.getContainingClass(innerClassDescriptor) ?:
|
||||
throw AssertionError("No containing class for inner class $innerClassDescriptor")
|
||||
|
||||
val receiver = ReceiverParameterDescriptorImpl(innerClassDescriptor, ImplicitClassReceiver(innerClassDescriptor))
|
||||
PropertyDescriptorImpl.create(innerClassDescriptor, Annotations.EMPTY, Modality.FINAL, Visibilities.PRIVATE,
|
||||
false, "this$0".synthesizedName, CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE,
|
||||
false, false, false, false, false, false).initialize(outerClassDescriptor.defaultType, dispatchReceiverParameter = receiver)
|
||||
val descriptor = PropertyDescriptorImpl.create(
|
||||
innerClassDescriptor, Annotations.EMPTY, Modality.FINAL,
|
||||
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 {
|
||||
@@ -93,7 +105,7 @@ internal class SpecialDescriptorsFactory(val context: Context) {
|
||||
fun getLoweredEnum(enumClassDescriptor: ClassDescriptor): LoweredEnum {
|
||||
assert(enumClassDescriptor.kind == ClassKind.ENUM_CLASS, { "Expected enum class but was: $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 }
|
||||
|
||||
val specialDescriptorsFactory = SpecialDescriptorsFactory(this)
|
||||
val specialDeclarationsFactory = SpecialDeclarationsFactory(this)
|
||||
val reflectionTypes: ReflectionTypes by lazy(PUBLICATION) { ReflectionTypes(moduleDescriptor) }
|
||||
private val vtableBuilders = mutableMapOf<ClassDescriptor, ClassVtablesBuilder>()
|
||||
|
||||
@@ -233,6 +245,9 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
||||
// to dump this information into generated file.
|
||||
var serializedLinkData: LinkData? = null
|
||||
|
||||
@Deprecated("")
|
||||
lateinit var psi2IrGeneratorContext: GeneratorContext
|
||||
|
||||
// TODO: make lateinit?
|
||||
var irModule: IrModuleFragment? = null
|
||||
set(module: IrModuleFragment?) {
|
||||
@@ -244,7 +259,7 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
||||
ir = Ir(this, module)
|
||||
}
|
||||
|
||||
lateinit var ir: Ir
|
||||
override lateinit var ir: Ir
|
||||
|
||||
override val irBuiltIns
|
||||
get() = ir.irModule.irBuiltins
|
||||
|
||||
+42
-13
@@ -22,7 +22,13 @@ import org.jetbrains.kotlin.backend.konan.ir.createSimpleDelegatingConstructorDe
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
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.Name
|
||||
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.replace
|
||||
|
||||
internal data class LoweredEnum(val implObjectDescriptor: ClassDescriptor,
|
||||
val valuesProperty: PropertyDescriptor,
|
||||
val valuesGetter: FunctionDescriptor,
|
||||
val itemGetter: FunctionDescriptor,
|
||||
|
||||
internal object DECLARATION_ORIGIN_ENUM :
|
||||
IrDeclarationOriginImpl("ENUM")
|
||||
|
||||
internal data class LoweredEnum(val implObject: IrClass,
|
||||
val valuesField: IrField,
|
||||
val valuesGetter: IrSimpleFunction,
|
||||
val itemGetterSymbol: IrFunctionSymbol,
|
||||
val itemGetterDescriptor: FunctionDescriptor,
|
||||
val entriesMap: Map<Name, Int>)
|
||||
|
||||
internal class EnumSpecialDescriptorsFactory(val context: Context) {
|
||||
internal class EnumSpecialDeclarationsFactory(val context: Context) {
|
||||
fun createLoweredEnum(enumClassDescriptor: ClassDescriptor): LoweredEnum {
|
||||
|
||||
val startOffset = enumClassDescriptor.startOffsetOrUndefined
|
||||
val endOffset = enumClassDescriptor.endOffsetOrUndefined
|
||||
|
||||
val implObjectDescriptor = ClassDescriptorImpl(enumClassDescriptor, "OBJECT".synthesizedName, Modality.FINAL,
|
||||
ClassKind.OBJECT, listOf(context.builtIns.anyType), SourceElement.NO_SOURCE, false)
|
||||
|
||||
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
|
||||
|
||||
@@ -53,9 +73,18 @@ internal class EnumSpecialDescriptorsFactory(val context: Context) {
|
||||
val constructorDescriptor = implObjectDescriptor.createSimpleDelegatingConstructorDescriptor(constructorOfAny, true)
|
||||
|
||||
implObjectDescriptor.initialize(memberScope, setOf(constructorDescriptor), constructorDescriptor)
|
||||
val implObject = IrClassImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, implObjectDescriptor).apply {
|
||||
createParameterDeclarations()
|
||||
}
|
||||
|
||||
return LoweredEnum(implObjectDescriptor, valuesProperty, valuesGetter,
|
||||
getEnumItemGetter(enumClassDescriptor), createEnumEntriesMap(enumClassDescriptor))
|
||||
val (itemGetterSymbol, itemGetterDescriptor) = getEnumItemGetter(enumClassDescriptor)
|
||||
|
||||
return LoweredEnum(
|
||||
implObject,
|
||||
valuesField,
|
||||
valuesGetter,
|
||||
itemGetterSymbol, itemGetterDescriptor,
|
||||
createEnumEntriesMap(enumClassDescriptor))
|
||||
}
|
||||
|
||||
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 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 {
|
||||
val getter = genericArrayType.unsubstitutedMemberScope.getContributedFunctions(Name.identifier("get"), NoLookupLocation.FROM_BACKEND).single()
|
||||
private fun getEnumItemGetter(enumClassDescriptor: ClassDescriptor): Pair<IrFunctionSymbol, FunctionDescriptor> {
|
||||
val getter = context.ir.symbols.array.functions.single { it.descriptor.name == Name.identifier("get") }
|
||||
|
||||
val typeParameterT = genericArrayType.declaredTypeParameters[0]
|
||||
val enumClassType = enumClassDescriptor.defaultType
|
||||
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> {
|
||||
|
||||
+4
-1
@@ -18,13 +18,16 @@ package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.BackendContext
|
||||
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 override val builtIns: KonanBuiltIns
|
||||
|
||||
abstract val ir: Ir
|
||||
|
||||
override val sharedVariablesManager by lazy {
|
||||
// Creating lazily because builtIns module seems to be incomplete during `link` test;
|
||||
// TODO: investigate this.
|
||||
KonanSharedVariablesManager(builtIns)
|
||||
KonanSharedVariablesManager(this)
|
||||
}
|
||||
}
|
||||
|
||||
+8
-2
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.backend.common.messageCollector
|
||||
import org.jetbrains.kotlin.backend.common.validateIrModule
|
||||
import org.jetbrains.kotlin.backend.konan.ir.DeserializerDriver
|
||||
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.serialization.KonanSerializationUtil
|
||||
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) {
|
||||
// Translate AST to high level IR.
|
||||
val translator = Psi2IrTranslator(Psi2IrConfiguration(false))
|
||||
val module = translator.generateModule(context.moduleDescriptor,
|
||||
environment.getSourceFiles(), bindingContext)
|
||||
val generatorContext = translator.createGeneratorContext(context.moduleDescriptor, bindingContext)
|
||||
context.psi2IrGeneratorContext = generatorContext
|
||||
|
||||
val symbols = Symbols(context, generatorContext.symbolTable)
|
||||
|
||||
val module = translator.generateModuleFragment(generatorContext, environment.getSourceFiles())
|
||||
|
||||
context.irModule = module
|
||||
context.ir.symbols = symbols
|
||||
|
||||
validateIrModule(context, module)
|
||||
}
|
||||
|
||||
+19
@@ -20,8 +20,12 @@ import org.jetbrains.kotlin.backend.common.runOnFilePostfix
|
||||
import org.jetbrains.kotlin.backend.common.lower.*
|
||||
import org.jetbrains.kotlin.backend.common.validateIrFile
|
||||
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.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) {
|
||||
|
||||
@@ -45,6 +49,8 @@ internal class KonanLower(val context: Context) {
|
||||
// Inlining must be run before other phases.
|
||||
phaser.phase(KonanPhase.LOWER_INLINE) {
|
||||
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) {
|
||||
StringConcatenationLowering(context).lower(irFile)
|
||||
irFile.checkSymbolsBound()
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_ENUMS) {
|
||||
EnumClassLowering(context).run(irFile)
|
||||
irFile.checkSymbolsBound()
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_INITIALIZERS) {
|
||||
InitializersLowering(context).runOnFilePostfix(irFile)
|
||||
irFile.checkSymbolsBound()
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_SHARED_VARIABLES) {
|
||||
SharedVariablesLowering(context).runOnFilePostfix(irFile)
|
||||
irFile.checkSymbolsBound()
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_DELEGATION) {
|
||||
PropertyDelegationLowering(context).lower(irFile)
|
||||
irFile.checkSymbolsBound()
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_LOCAL_FUNCTIONS) {
|
||||
LocalDeclarationsLowering(context).runOnFilePostfix(irFile)
|
||||
irFile.checkSymbolsBound()
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_TAILREC) {
|
||||
TailrecLowering(context).runOnFilePostfix(irFile)
|
||||
irFile.checkSymbolsBound()
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_FINALLY) {
|
||||
FinallyBlocksLowering(context).runOnFilePostfix(irFile)
|
||||
@@ -112,4 +125,10 @@ internal class KonanLower(val context: Context) {
|
||||
Autoboxing(context).lower(irFile)
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrElement.checkSymbolsBound() {
|
||||
if (context.shouldVerifyIr()) {
|
||||
this.acceptVoid(IrSymbolBindingChecker())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+49
-23
@@ -18,12 +18,14 @@ package org.jetbrains.kotlin.backend.konan.descriptors
|
||||
|
||||
|
||||
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.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||
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.impl.IrVariableImpl
|
||||
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.IrCompositeImpl
|
||||
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.*
|
||||
|
||||
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 {
|
||||
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))
|
||||
))!!
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -57,10 +68,12 @@ internal class KonanSharedVariablesManager(val builtIns: KonanBuiltIns) : Shared
|
||||
variableDescriptor.containingDeclaration, variableDescriptor.annotations, variableDescriptor.name,
|
||||
refType(variableDescriptor.type),
|
||||
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()
|
||||
.filterIsInstance<PropertyDescriptor>()
|
||||
.single {
|
||||
@@ -71,49 +84,62 @@ internal class KonanSharedVariablesManager(val builtIns: KonanBuiltIns) : Shared
|
||||
override fun defineSharedValue(sharedVariableDescriptor: VariableDescriptor,
|
||||
originalDeclaration: IrVariable): IrStatement {
|
||||
|
||||
val sharedVariableSymbol = sharedVariableDescriptorToSymbol[sharedVariableDescriptor]!!
|
||||
|
||||
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(
|
||||
originalDeclaration.startOffset, originalDeclaration.endOffset,
|
||||
refConstructor(valueType), refConstructorTypeArguments
|
||||
refClassConstructor, refConstructor(valueType), refConstructorTypeArguments
|
||||
)
|
||||
val sharedVariableDeclaration = IrVariableImpl(
|
||||
originalDeclaration.startOffset, originalDeclaration.endOffset, originalDeclaration.origin,
|
||||
sharedVariableDescriptor, refConstructorCall
|
||||
)
|
||||
sharedVariableSymbol
|
||||
).apply {
|
||||
initializer = refConstructorCall
|
||||
}
|
||||
|
||||
val initializer = originalDeclaration.initializer ?:
|
||||
return sharedVariableDeclaration
|
||||
|
||||
val elementProperty = getElementProperty(sharedVariableDescriptor)
|
||||
val elementPropertyDescriptor = getElementPropertyDescriptor(sharedVariableDescriptor)
|
||||
|
||||
val sharedVariableInitialization =
|
||||
IrCallImpl(initializer.startOffset, initializer.endOffset, elementProperty.setter!!)
|
||||
IrCallImpl(initializer.startOffset, initializer.endOffset, elementProperty.setter!!.symbol,
|
||||
elementPropertyDescriptor.setter!!)
|
||||
|
||||
sharedVariableInitialization.dispatchReceiver =
|
||||
IrGetValueImpl(initializer.startOffset, initializer.endOffset, sharedVariableDescriptor)
|
||||
IrGetValueImpl(initializer.startOffset, initializer.endOffset, sharedVariableSymbol)
|
||||
|
||||
sharedVariableInitialization.putValueArgument(0, initializer)
|
||||
|
||||
return IrCompositeImpl(
|
||||
originalDeclaration.startOffset, originalDeclaration.endOffset, builtIns.unitType, null,
|
||||
originalDeclaration.startOffset, originalDeclaration.endOffset, context.builtIns.unitType, null,
|
||||
listOf(sharedVariableDeclaration, sharedVariableInitialization)
|
||||
)
|
||||
}
|
||||
|
||||
override fun getSharedValue(sharedVariableDescriptor: VariableDescriptor, originalGet: IrGetValue): IrExpression {
|
||||
val elementProperty = getElementProperty(sharedVariableDescriptor)
|
||||
return IrCallImpl(originalGet.startOffset, originalGet.endOffset, elementProperty.getter!!).apply {
|
||||
dispatchReceiver = IrGetValueImpl(originalGet.startOffset, originalGet.endOffset, sharedVariableDescriptor)
|
||||
val sharedVariableSymbol = sharedVariableDescriptorToSymbol[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 {
|
||||
val elementProperty = getElementProperty(sharedVariableDescriptor)
|
||||
return IrCallImpl(originalSet.startOffset, originalSet.endOffset, elementProperty.setter!!).apply {
|
||||
dispatchReceiver = IrGetValueImpl(originalSet.startOffset, originalSet.endOffset, sharedVariableDescriptor)
|
||||
val sharedVariableSymbol = sharedVariableDescriptorToSymbol[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)
|
||||
}
|
||||
}
|
||||
|
||||
+69
-2
@@ -17,10 +17,18 @@
|
||||
package org.jetbrains.kotlin.backend.konan.ir
|
||||
|
||||
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.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
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.
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
}
|
||||
+28
-21
@@ -20,17 +20,16 @@ import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
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.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
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.createParameterDeclarations
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
@@ -91,30 +90,38 @@ internal fun ClassDescriptor.createSimpleDelegatingConstructorDescriptor(superCo
|
||||
return constructorDescriptor
|
||||
}
|
||||
|
||||
internal fun ClassDescriptor.createSimpleDelegatingConstructor(superConstructorDescriptor: ClassConstructorDescriptor,
|
||||
constructorDescriptor: ClassConstructorDescriptor,
|
||||
startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin)
|
||||
internal fun IrClass.addSimpleDelegatingConstructor(superConstructorSymbol: IrConstructorSymbol,
|
||||
constructorDescriptor: ClassConstructorDescriptor,
|
||||
origin: IrDeclarationOrigin)
|
||||
: IrConstructor {
|
||||
val body = IrBlockBodyImpl(startOffset, endOffset,
|
||||
listOf(
|
||||
IrDelegatingConstructorCallImpl(startOffset, endOffset, superConstructorDescriptor).apply {
|
||||
constructorDescriptor.valueParameters.forEachIndexed { idx, parameter ->
|
||||
putValueArgument(idx, IrGetValueImpl(startOffset, endOffset, parameter))
|
||||
}
|
||||
},
|
||||
IrInstanceInitializerCallImpl(startOffset, endOffset, this)
|
||||
)
|
||||
)
|
||||
return IrConstructorImpl(startOffset, endOffset, origin, constructorDescriptor, body).apply {
|
||||
createParameterDeclarations()
|
||||
|
||||
return IrConstructorImpl(startOffset, endOffset, origin, constructorDescriptor).also { constructor ->
|
||||
constructor.createParameterDeclarations()
|
||||
|
||||
constructor.body = IrBlockBodyImpl(startOffset, endOffset,
|
||||
listOf(
|
||||
IrDelegatingConstructorCallImpl(
|
||||
startOffset, endOffset,
|
||||
superConstructorSymbol, superConstructorSymbol.descriptor
|
||||
).apply {
|
||||
constructor.valueParameters.forEachIndexed { idx, parameter ->
|
||||
putValueArgument(idx, IrGetValueImpl(startOffset, endOffset, parameter.symbol))
|
||||
}
|
||||
},
|
||||
IrInstanceInitializerCallImpl(startOffset, endOffset, this.symbol)
|
||||
)
|
||||
)
|
||||
|
||||
this.declarations.add(constructor)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Context.createArrayOfExpression(arrayElementType: KotlinType,
|
||||
arrayElements: List<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 typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameter0.typeConstructor to TypeProjectionImpl(arrayElementType)))
|
||||
val substitutedArrayOfFun = genericArrayOfFun.substitute(typeSubstitutor)!!
|
||||
@@ -126,7 +133,7 @@ internal fun Context.createArrayOfExpression(arrayElementType: KotlinType,
|
||||
val arg0VarargElementType = valueParameter0.varargElementType!!
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
+27
-5
@@ -16,33 +16,55 @@
|
||||
|
||||
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.declarations.IrSymbolOwner
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBlock
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrContainerExpressionBase
|
||||
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.IrElementVisitor
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
//-----------------------------------------------------------------------------//
|
||||
|
||||
interface IrReturnableBlock: IrBlock {
|
||||
val descriptor: CallableDescriptor
|
||||
interface IrReturnableBlockSymbol : IrFunctionSymbol, IrBindableSymbol<FunctionDescriptor, IrReturnableBlock>
|
||||
|
||||
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,
|
||||
override val descriptor: CallableDescriptor, origin: IrStatementOrigin? = null)
|
||||
override val symbol: IrReturnableBlockSymbol, origin: IrStatementOrigin? = null)
|
||||
: IrContainerExpressionBase(startOffset, endOffset, type, origin), IrReturnableBlock {
|
||||
|
||||
override val descriptor = symbol.descriptor
|
||||
|
||||
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.statements.addAll(statements)
|
||||
}
|
||||
|
||||
init {
|
||||
symbol.bind(this)
|
||||
}
|
||||
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
||||
visitor.visitBlock(this, data)
|
||||
|
||||
|
||||
+1
-2
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||
import org.jetbrains.kotlin.resolve.constants.StringValue
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
|
||||
@@ -191,6 +190,6 @@ internal class RTTIGenerator(override val context: Context) : ContextUtils {
|
||||
} else {
|
||||
descriptor
|
||||
}
|
||||
return context.specialDescriptorsFactory.getBridgeDescriptor(OverriddenFunctionDescriptor(bridgeOwner, overriddenDescriptor))
|
||||
return context.specialDeclarationsFactory.getBridgeDescriptor(OverriddenFunctionDescriptor(bridgeOwner, overriddenDescriptor))
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -112,7 +112,7 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
|
||||
IrDeclarationOriginImpl("BRIDGE_METHOD")
|
||||
|
||||
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 delegatingCall = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, target,
|
||||
|
||||
+13
-14
@@ -19,17 +19,15 @@ package org.jetbrains.kotlin.backend.konan.lower
|
||||
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
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.util.atMostOne
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltinOperatorDescriptor
|
||||
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.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.type
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
@@ -89,17 +87,17 @@ private class BuiltinOperatorTransformer(val context: Context) : IrElementTransf
|
||||
|
||||
return when (descriptor) {
|
||||
irBuiltins.eqeq -> {
|
||||
val binary = expression as IrBinaryPrimitiveImpl
|
||||
lowerEqeq(binary.argument0, binary.argument1, expression.startOffset, expression.endOffset)
|
||||
lowerEqeq(expression.getValueArgument(0)!!, expression.getValueArgument(1)!!,
|
||||
expression.startOffset, expression.endOffset)
|
||||
}
|
||||
|
||||
irBuiltins.eqeqeq -> lowerEqeqeq(expression)
|
||||
|
||||
irBuiltins.throwNpe -> IrCallImpl(expression.startOffset, expression.endOffset,
|
||||
builtIns.getKonanInternalFunctions("ThrowNullPointerException").single())
|
||||
context.ir.symbols.ThrowNullPointerException)
|
||||
|
||||
irBuiltins.noWhenBranchMatchedException -> IrCallImpl(expression.startOffset, expression.endOffset,
|
||||
builtIns.getKonanInternalFunctions("ThrowNoWhenBranchMatchedException").single())
|
||||
context.ir.symbols.ThrowNoWhenBranchMatchedException)
|
||||
|
||||
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
|
||||
if (lhs.type.isSubtypeOf(nullableNothingType) && rhs.type.isSubtypeOf(nullableNothingType)) {
|
||||
// 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
|
||||
// and thus can be declared synthetically in the compiler instead of explicitly in the runtime.
|
||||
|
||||
// Find a type-compatible `konan.internal.areEqualByValue` intrinsic:
|
||||
builtIns.getKonanInternalFunctions("areEqualByValue").atMostOne {
|
||||
lhs.type.isSubtypeOf(it.valueParameters[0].type) && rhs.type.isSubtypeOf(it.valueParameters[1].type)
|
||||
context.ir.symbols.areEqualByValue.atMostOne {
|
||||
lhs.type.isSubtypeOf(it.owner.valueParameters[0].type) &&
|
||||
rhs.type.isSubtypeOf(it.owner.valueParameters[1].type)
|
||||
}?.let {
|
||||
return it
|
||||
}
|
||||
|
||||
return if (lhs.isNullConst() || rhs.isNullConst()) {
|
||||
// or compare by reference if left or right part is `null`:
|
||||
irBuiltins.eqeqeq
|
||||
irBuiltins.eqeqeqSymbol
|
||||
} else {
|
||||
// or use the general implementation:
|
||||
builtIns.getKonanInternalFunctions("areEqual").single()
|
||||
context.ir.symbols.areEqual
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+134
-65
@@ -33,10 +33,12 @@ import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrLocalDelegatedProperty
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCallableReference
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstKind
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
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.transformChildrenVoid
|
||||
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 genericArrayType = kotlinPackage.memberScope.getContributedClassifier(Name.identifier("Array"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor
|
||||
|
||||
private fun getKPropertyImplConstructorDescriptor(receiverTypes: List<KotlinType>,
|
||||
returnType: KotlinType,
|
||||
isLocal: Boolean,
|
||||
isMutable: Boolean) : ClassConstructorDescriptor {
|
||||
val classDescriptor =
|
||||
private fun getKPropertyImplConstructor(receiverTypes: List<KotlinType>,
|
||||
returnType: KotlinType,
|
||||
isLocal: Boolean,
|
||||
isMutable: Boolean) : Pair<IrConstructorSymbol, ClassConstructorDescriptor> {
|
||||
|
||||
val symbols = context.ir.symbols
|
||||
|
||||
val classSymbol =
|
||||
if (isLocal) {
|
||||
assert(receiverTypes.isEmpty(), { "Local delegated property cannot have explicit receiver" })
|
||||
when {
|
||||
isMutable -> reflectionTypes.kLocalDelegatedMutablePropertyImpl
|
||||
else -> reflectionTypes.kLocalDelegatedPropertyImpl
|
||||
isMutable -> symbols.kLocalDelegatedMutablePropertyImpl
|
||||
else -> symbols.kLocalDelegatedPropertyImpl
|
||||
}
|
||||
} else {
|
||||
when (receiverTypes.size) {
|
||||
0 -> when {
|
||||
isMutable -> reflectionTypes.kMutableProperty0Impl
|
||||
else -> reflectionTypes.kProperty0Impl
|
||||
isMutable -> symbols.kMutableProperty0Impl
|
||||
else -> symbols.kProperty0Impl
|
||||
}
|
||||
1 -> when {
|
||||
isMutable -> reflectionTypes.kMutableProperty1Impl
|
||||
else -> reflectionTypes.kProperty1Impl
|
||||
isMutable -> symbols.kMutableProperty1Impl
|
||||
else -> symbols.kProperty1Impl
|
||||
}
|
||||
2 -> when {
|
||||
isMutable -> reflectionTypes.kMutableProperty2Impl
|
||||
else -> reflectionTypes.kProperty2Impl
|
||||
isMutable -> symbols.kMutableProperty2Impl
|
||||
else -> symbols.kProperty2Impl
|
||||
}
|
||||
else -> throw AssertionError("More than 2 receivers is not allowed")
|
||||
}
|
||||
}
|
||||
|
||||
val classDescriptor = classSymbol.descriptor
|
||||
|
||||
val typeParameters = classDescriptor.declaredTypeParameters
|
||||
val arguments = (receiverTypes + listOf(returnType))
|
||||
.mapIndexed { index, type -> typeParameters[index].typeConstructor to TypeProjectionImpl(type) }
|
||||
.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 {
|
||||
@@ -90,14 +101,21 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
|
||||
override fun lower(irFile: IrFile) {
|
||||
val kProperties = mutableMapOf<VariableDescriptorWithAccessors, Pair<IrExpression, Int>>()
|
||||
|
||||
val arrayItemGetter = genericArrayType.unsubstitutedMemberScope.getContributedFunctions(Name.identifier("get"),
|
||||
NoLookupLocation.FROM_BACKEND).single()
|
||||
val arrayClass = context.ir.symbols.array
|
||||
|
||||
val arrayItemGetter = arrayClass.functions.single { it.descriptor.name == Name.identifier("get") }
|
||||
|
||||
val typeParameterT = genericArrayType.declaredTypeParameters[0]
|
||||
val kPropertyImplType = reflectionTypes.kProperty1Impl.replace(context.builtIns.anyType, context.builtIns.anyType)
|
||||
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() {
|
||||
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)
|
||||
val propertyDescriptor = expression.descriptor as? VariableDescriptorWithAccessors
|
||||
if (propertyDescriptor == null) return expression
|
||||
|
||||
val receiversCount = listOf(expression.dispatchReceiver, expression.extensionReceiver).count { it != null }
|
||||
if (receiversCount == 1 && propertyDescriptor is PropertyDescriptor) // Has receiver and is not local delegated.
|
||||
return createKProperty(expression, propertyDescriptor)
|
||||
if (receiversCount == 1) // Has receiver.
|
||||
return createKProperty(expression)
|
||||
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.
|
||||
val field = kProperties.getOrPut(propertyDescriptor) {
|
||||
createKProperty(expression, propertyDescriptor) to kProperties.size
|
||||
val field = kProperties.getOrPut(expression.descriptor) {
|
||||
createKProperty(expression) to kProperties.size
|
||||
}
|
||||
|
||||
return IrCallImpl(expression.startOffset, expression.endOffset, substitutedArrayItemGetter).apply {
|
||||
dispatchReceiver = IrGetFieldImpl(expression.startOffset, expression.endOffset, kPropertiesField)
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
@@ -146,66 +194,68 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
|
||||
if (kProperties.isNotEmpty()) {
|
||||
val initializers = kProperties.values.sortedBy { it.second }.map { it.first }
|
||||
// TODO: move to object for lazy initialization.
|
||||
irFile.declarations.add(0, IrFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
DECLARATION_ORIGIN_KPROPERTIES_FOR_DELEGATION,
|
||||
kPropertiesField,
|
||||
IrExpressionBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
context.createArrayOfExpression(kPropertyImplType, initializers, UNDEFINED_OFFSET, UNDEFINED_OFFSET))))
|
||||
irFile.declarations.add(0, kPropertiesField.apply {
|
||||
initializer = 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 endOffset = expression.endOffset
|
||||
val receiverTypes = mutableListOf<KotlinType>()
|
||||
val isLocal = propertyDescriptor !is PropertyDescriptor
|
||||
|
||||
val propertyDescriptor = expression.descriptor
|
||||
|
||||
val returnType = propertyDescriptor.type
|
||||
val getterCallableReference = propertyDescriptor.getter.let {
|
||||
if (it == null || isLocal) null
|
||||
else {
|
||||
val getter = propertyDescriptor.getter!!
|
||||
getter.extensionReceiverParameter.let {
|
||||
if (it != null && expression.extensionReceiver == null)
|
||||
receiverTypes.add(it.type)
|
||||
}
|
||||
getter.dispatchReceiverParameter.let {
|
||||
if (it != null && expression.dispatchReceiver == null)
|
||||
receiverTypes.add(it.type)
|
||||
}
|
||||
val getterKFunctionType = context.reflectionTypes.getKFunctionType(
|
||||
annotations = Annotations.EMPTY,
|
||||
receiverType = receiverTypes.firstOrNull(),
|
||||
parameterTypes = if (receiverTypes.size < 2) listOf() else listOf(receiverTypes[1]),
|
||||
returnType = returnType)
|
||||
IrFunctionReferenceImpl(startOffset, endOffset, getterKFunctionType, getter, null).apply {
|
||||
dispatchReceiver = expression.dispatchReceiver
|
||||
extensionReceiver = expression.extensionReceiver
|
||||
}
|
||||
val getterCallableReference = propertyDescriptor.getter?.let { getter ->
|
||||
getter.extensionReceiverParameter.let {
|
||||
if (it != null && expression.extensionReceiver == null)
|
||||
receiverTypes.add(it.type)
|
||||
}
|
||||
getter.dispatchReceiverParameter.let {
|
||||
if (it != null && expression.dispatchReceiver == null)
|
||||
receiverTypes.add(it.type)
|
||||
}
|
||||
val getterKFunctionType = context.reflectionTypes.getKFunctionType(
|
||||
annotations = Annotations.EMPTY,
|
||||
receiverType = receiverTypes.firstOrNull(),
|
||||
parameterTypes = if (receiverTypes.size < 2) listOf() else listOf(receiverTypes[1]),
|
||||
returnType = returnType)
|
||||
IrFunctionReferenceImpl(
|
||||
startOffset, endOffset,
|
||||
getterKFunctionType, expression.getter!!, getter, null
|
||||
).apply {
|
||||
dispatchReceiver = expression.dispatchReceiver
|
||||
extensionReceiver = expression.extensionReceiver
|
||||
}
|
||||
}
|
||||
|
||||
val setterCallableReference = propertyDescriptor.setter.let {
|
||||
if (it == null || isLocal || !isKMutablePropertyType(expression.type)) null
|
||||
val setterCallableReference = propertyDescriptor.setter?.let {
|
||||
if (!isKMutablePropertyType(expression.type)) null
|
||||
else {
|
||||
val setterKFunctionType = context.reflectionTypes.getKFunctionType(
|
||||
annotations = Annotations.EMPTY,
|
||||
receiverType = receiverTypes.firstOrNull(),
|
||||
parameterTypes = if (receiverTypes.size < 2) listOf(returnType) else listOf(receiverTypes[1], returnType),
|
||||
returnType = context.builtIns.unitType)
|
||||
IrFunctionReferenceImpl(startOffset, endOffset, setterKFunctionType, it, null).apply {
|
||||
IrFunctionReferenceImpl(
|
||||
startOffset, endOffset,
|
||||
setterKFunctionType, expression.setter!!, it, null
|
||||
).apply {
|
||||
dispatchReceiver = expression.dispatchReceiver
|
||||
extensionReceiver = expression.extensionReceiver
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val descriptor = getKPropertyImplConstructorDescriptor(
|
||||
val (symbol, descriptor) = getKPropertyImplConstructor(
|
||||
receiverTypes = receiverTypes,
|
||||
returnType = returnType,
|
||||
isLocal = isLocal,
|
||||
isLocal = false,
|
||||
isMutable = setterCallableReference != null)
|
||||
val initializer = IrCallImpl(startOffset, endOffset, descriptor).apply {
|
||||
val initializer = IrCallImpl(startOffset, endOffset, symbol, descriptor).apply {
|
||||
putValueArgument(0, IrConstImpl<String>(startOffset, endOffset,
|
||||
context.builtIns.stringType, IrConstKind.String, propertyDescriptor.name.asString()))
|
||||
if (getterCallableReference != null)
|
||||
@@ -216,6 +266,25 @@ internal class PropertyDelegationLowering(val context: Context) : FileLoweringPa
|
||||
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 {
|
||||
val arguments = type.arguments
|
||||
val expectedClassDescriptor = when (arguments.size) {
|
||||
|
||||
+86
-84
@@ -22,26 +22,23 @@ import org.jetbrains.kotlin.backend.common.lower.SimpleMemberScope
|
||||
import org.jetbrains.kotlin.backend.common.runOnFilePostfix
|
||||
import org.jetbrains.kotlin.backend.jvm.descriptors.createValueParameter
|
||||
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.ir.createArrayOfExpression
|
||||
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.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.ir.util.transform
|
||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -53,43 +50,47 @@ import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
internal class EnumSyntheticFunctionsBuilder(val context: Context) {
|
||||
fun buildValuesExpression(startOffset: Int, endOffset: Int,
|
||||
enumClassDescriptor: ClassDescriptor): IrExpression {
|
||||
val loweredEnum = context.specialDescriptorsFactory.getLoweredEnum(enumClassDescriptor)
|
||||
val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClassDescriptor)
|
||||
|
||||
val typeParameterT = genericValuesDescriptor.typeParameters[0]
|
||||
val enumClassType = enumClassDescriptor.defaultType
|
||||
val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(enumClassType)))
|
||||
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 {
|
||||
val receiver = IrGetObjectValueImpl(startOffset, endOffset,
|
||||
loweredEnum.implObjectDescriptor.defaultType, loweredEnum.implObjectDescriptor)
|
||||
putValueArgument(0, IrGetFieldImpl(startOffset, endOffset, loweredEnum.valuesProperty, receiver))
|
||||
loweredEnum.implObject.defaultType, loweredEnum.implObject.symbol)
|
||||
putValueArgument(0, IrGetFieldImpl(startOffset, endOffset, loweredEnum.valuesField.symbol, receiver))
|
||||
}
|
||||
}
|
||||
|
||||
fun buildValueOfExpression(startOffset: Int, endOffset: Int,
|
||||
enumClassDescriptor: ClassDescriptor,
|
||||
value: IrExpression): IrExpression {
|
||||
val loweredEnum = context.specialDescriptorsFactory.getLoweredEnum(enumClassDescriptor)
|
||||
val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(enumClassDescriptor)
|
||||
|
||||
val typeParameterT = genericValueOfDescriptor.typeParameters[0]
|
||||
val enumClassType = enumClassDescriptor.defaultType
|
||||
val typeSubstitutor = TypeSubstitutor.create(mapOf(typeParameterT.typeConstructor to TypeProjectionImpl(enumClassType)))
|
||||
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 {
|
||||
putValueArgument(0, value)
|
||||
val receiver = IrGetObjectValueImpl(startOffset, endOffset,
|
||||
loweredEnum.implObjectDescriptor.defaultType, loweredEnum.implObjectDescriptor)
|
||||
putValueArgument(1, IrGetFieldImpl(startOffset, endOffset, loweredEnum.valuesProperty, receiver))
|
||||
loweredEnum.implObject.defaultType, loweredEnum.implObject.symbol)
|
||||
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)
|
||||
@@ -142,10 +143,10 @@ internal class EnumUsageLowering(val context: Context)
|
||||
Name.identifier("enumValues"), NoLookupLocation.FROM_BACKEND).single()
|
||||
|
||||
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]!!
|
||||
return IrCallImpl(startOffset, endOffset, loweredEnum.itemGetter).apply {
|
||||
dispatchReceiver = IrCallImpl(startOffset, endOffset, loweredEnum.valuesGetter)
|
||||
return IrCallImpl(startOffset, endOffset, loweredEnum.itemGetterSymbol, loweredEnum.itemGetterDescriptor).apply {
|
||||
dispatchReceiver = IrCallImpl(startOffset, endOffset, loweredEnum.valuesGetter.symbol)
|
||||
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 val loweredEnum = context.specialDescriptorsFactory.getLoweredEnum(irClass.descriptor)
|
||||
private val loweredEnum = context.specialDeclarationsFactory.getLoweredEnum(irClass.descriptor)
|
||||
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 defaultEnumEntryConstructors = mutableMapOf<ClassConstructorDescriptor, ClassConstructorDescriptor>()
|
||||
private val defaultEnumEntryConstructors = mutableMapOf<ClassConstructorDescriptor, IrConstructor>()
|
||||
private val loweredEnumConstructorParameters = mutableMapOf<ValueParameterDescriptor, ValueParameterDescriptor>()
|
||||
private val enumSyntheticFunctionsBuilder = EnumSyntheticFunctionsBuilder(context)
|
||||
|
||||
@@ -205,7 +206,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
blockBody.statements.transformFlat {
|
||||
if (it is IrEnumConstructorCall)
|
||||
listOf(it, IrInstanceInitializerCallImpl(declaration.startOffset, declaration.startOffset,
|
||||
irClass.descriptor))
|
||||
irClass.symbol))
|
||||
else null
|
||||
}
|
||||
}
|
||||
@@ -254,21 +255,21 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
val constructors = mutableSetOf<ClassConstructorDescriptor>()
|
||||
|
||||
descriptor.constructors.forEach {
|
||||
val loweredEnumConstructor = loweredEnumConstructors[it]!!
|
||||
val loweredEnumConstructorSymbol = loweredEnumConstructors[it]!!.symbol
|
||||
val loweredEnumConstructor = loweredEnumConstructorSymbol.descriptor
|
||||
val constructorDescriptor = defaultClassDescriptor.createSimpleDelegatingConstructorDescriptor(loweredEnumConstructor)
|
||||
val constructor = defaultClassDescriptor.createSimpleDelegatingConstructor(
|
||||
loweredEnumConstructor, constructorDescriptor,
|
||||
startOffset, endOffset, DECLARATION_ORIGIN_ENUM)
|
||||
val constructor = defaultClass.addSimpleDelegatingConstructor(
|
||||
loweredEnumConstructorSymbol, constructorDescriptor,
|
||||
DECLARATION_ORIGIN_ENUM)
|
||||
constructors.add(constructorDescriptor)
|
||||
defaultClass.declarations.add(constructor)
|
||||
defaultEnumEntryConstructors.put(loweredEnumConstructor, constructorDescriptor)
|
||||
defaultEnumEntryConstructors.put(loweredEnumConstructor, constructor)
|
||||
|
||||
val irConstructor = descriptorToIrConstructorWithDefaultArguments[loweredEnumConstructor]
|
||||
if (irConstructor != null) {
|
||||
it.valueParameters.filter { it.declaresDefaultValue() }.forEach { argument ->
|
||||
val loweredArgument = loweredEnumConstructor.valueParameters[argument.loweredIndex()]
|
||||
val body = irConstructor.getDefault(loweredArgument)!!
|
||||
body.transformChildrenVoid(ParameterMapper(constructorDescriptor))
|
||||
body.transformChildrenVoid(ParameterMapper(constructor))
|
||||
constructor.putDefault(constructorDescriptor.valueParameters[loweredArgument.index], body)
|
||||
}
|
||||
}
|
||||
@@ -285,12 +286,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
}
|
||||
|
||||
private fun createImplObject() {
|
||||
val startOffset = irClass.startOffset
|
||||
val endOffset = irClass.endOffset
|
||||
val implObjectDescriptor = loweredEnum.implObjectDescriptor
|
||||
val implObject = IrClassImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, implObjectDescriptor)
|
||||
|
||||
implObject.createParameterDeclarations()
|
||||
val implObject = loweredEnum.implObject
|
||||
|
||||
val enumEntries = mutableListOf<IrEnumEntry>()
|
||||
var i = 0
|
||||
@@ -307,9 +303,9 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
if (body is IrSyntheticBody) {
|
||||
when (body.kind) {
|
||||
IrSyntheticBodyKind.ENUM_VALUEOF ->
|
||||
declaration.body = createSyntheticValueOfMethodBody(declaration.descriptor)
|
||||
declaration.body = createSyntheticValueOfMethodBody(declaration)
|
||||
IrSyntheticBodyKind.ENUM_VALUES ->
|
||||
declaration.body = createSyntheticValuesMethodBody(declaration.descriptor)
|
||||
declaration.body = createSyntheticValuesMethodBody(declaration)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -320,12 +316,12 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
++i
|
||||
}
|
||||
|
||||
val constructorOfAny = irClass.descriptor.module.builtIns.any.constructors.first()
|
||||
val constructor = implObjectDescriptor.createSimpleDelegatingConstructor(
|
||||
constructorOfAny, implObjectDescriptor.constructors.single(),
|
||||
startOffset, endOffset, DECLARATION_ORIGIN_ENUM)
|
||||
val constructorOfAny = context.ir.symbols.any.constructors.single()
|
||||
|
||||
implObject.addSimpleDelegatingConstructor(
|
||||
constructorOfAny, implObject.descriptor.constructors.single(),
|
||||
DECLARATION_ORIGIN_ENUM)
|
||||
|
||||
implObject.declarations.add(constructor)
|
||||
implObject.declarations.add(createSyntheticValuesPropertyDeclaration(enumEntries))
|
||||
|
||||
irClass.declarations.add(implObject)
|
||||
@@ -337,47 +333,42 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
val irValuesInitializer = context.createArrayOfExpression(irClass.descriptor.defaultType,
|
||||
enumEntries.sortedBy { it.descriptor.name }.map { it.initializerExpression!! }, startOffset, endOffset)
|
||||
|
||||
val irField = IrFieldImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM,
|
||||
loweredEnum.valuesProperty,
|
||||
IrExpressionBodyImpl(startOffset, endOffset, irValuesInitializer))
|
||||
val irField = loweredEnum.valuesField.apply {
|
||||
initializer = IrExpressionBodyImpl(startOffset, endOffset, irValuesInitializer)
|
||||
}
|
||||
|
||||
val getter = IrFunctionImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM, loweredEnum.valuesGetter)
|
||||
|
||||
getter.createParameterDeclarations()
|
||||
val getter = loweredEnum.valuesGetter
|
||||
|
||||
val receiver = IrGetObjectValueImpl(startOffset, endOffset,
|
||||
loweredEnum.implObjectDescriptor.defaultType, loweredEnum.implObjectDescriptor)
|
||||
val value = IrGetFieldImpl(startOffset, endOffset, loweredEnum.valuesProperty, receiver)
|
||||
val returnStatement = IrReturnImpl(startOffset, endOffset, loweredEnum.valuesGetter, value)
|
||||
loweredEnum.implObject.defaultType, loweredEnum.implObject.symbol)
|
||||
val value = IrGetFieldImpl(startOffset, endOffset, loweredEnum.valuesField.symbol, receiver)
|
||||
val returnStatement = IrReturnImpl(startOffset, endOffset, loweredEnum.valuesGetter.symbol, value)
|
||||
getter.body = IrBlockBodyImpl(startOffset, endOffset, listOf(returnStatement))
|
||||
|
||||
val irProperty = IrPropertyImpl(startOffset, endOffset, DECLARATION_ORIGIN_ENUM,
|
||||
false, loweredEnum.valuesProperty, irField, getter, null)
|
||||
false, loweredEnum.valuesField.descriptor, irField, getter, null)
|
||||
return irProperty
|
||||
}
|
||||
|
||||
private object DECLARATION_ORIGIN_ENUM :
|
||||
IrDeclarationOriginImpl("ENUM")
|
||||
|
||||
private fun createSyntheticValuesMethodBody(descriptor: FunctionDescriptor): IrBody {
|
||||
private fun createSyntheticValuesMethodBody(declaration: IrFunction): IrBody {
|
||||
val startOffset = irClass.startOffset
|
||||
val endOffset = irClass.endOffset
|
||||
val valuesExpression = enumSyntheticFunctionsBuilder.buildValuesExpression(startOffset, endOffset, irClass.descriptor)
|
||||
|
||||
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 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)
|
||||
|
||||
return IrBlockBodyImpl(
|
||||
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
|
||||
)
|
||||
|
||||
loweredEnumConstructors[constructorDescriptor] = loweredEnumConstructor
|
||||
|
||||
loweredEnumConstructor.createParameterDeclarations()
|
||||
|
||||
enumConstructor.descriptor.valueParameters.filter { it.declaresDefaultValue() }.forEach {
|
||||
val body = enumConstructor.getDefault(it)!!
|
||||
body.transformChildrenVoid(ParameterMapper(constructorDescriptor))
|
||||
body.transformChildrenVoid(ParameterMapper(enumConstructor))
|
||||
loweredEnumConstructor.putDefault(loweredConstructorDescriptor.valueParameters[it.loweredIndex()], body)
|
||||
descriptorToIrConstructorWithDefaultArguments[loweredConstructorDescriptor] = loweredEnumConstructor
|
||||
}
|
||||
@@ -428,8 +421,6 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
|
||||
loweredConstructorDescriptor.returnType = constructorDescriptor.returnType
|
||||
|
||||
loweredEnumConstructors[constructorDescriptor] = loweredConstructorDescriptor
|
||||
|
||||
return loweredConstructorDescriptor
|
||||
}
|
||||
|
||||
@@ -450,14 +441,15 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
irClass.transformChildrenVoid(EnumClassBodyTransformer())
|
||||
}
|
||||
|
||||
private inner class InEnumClassConstructor(val enumClassConstructor: ClassConstructorDescriptor) :
|
||||
private inner class InEnumClassConstructor(val enumClassConstructor: IrConstructor) :
|
||||
EnumConstructorCallTransformer {
|
||||
override fun transform(enumConstructorCall: IrEnumConstructorCall): IrExpression {
|
||||
val startOffset = enumConstructorCall.startOffset
|
||||
val endOffset = enumConstructorCall.endOffset
|
||||
val origin = enumConstructorCall.origin
|
||||
|
||||
val result = IrDelegatingConstructorCallImpl(startOffset, endOffset, enumConstructorCall.descriptor)
|
||||
val result = IrDelegatingConstructorCallImpl(startOffset, endOffset,
|
||||
enumConstructorCall.symbol, enumConstructorCall.descriptor)
|
||||
|
||||
assert(result.descriptor.valueParameters.size == 2) {
|
||||
"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")
|
||||
}
|
||||
|
||||
result.putValueArgument(0, IrGetValueImpl(startOffset, endOffset, nameParameter, origin))
|
||||
result.putValueArgument(1, IrGetValueImpl(startOffset, endOffset, ordinalParameter, origin))
|
||||
result.putValueArgument(0, IrGetValueImpl(startOffset, endOffset, nameParameter.symbol, origin))
|
||||
result.putValueArgument(1, IrGetValueImpl(startOffset, endOffset, ordinalParameter.symbol, origin))
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
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(1, IrGetValueImpl(startOffset, endOffset, enumClassConstructor.valueParameters[1]))
|
||||
result.putValueArgument(0,
|
||||
IrGetValueImpl(startOffset, endOffset, enumClassConstructor.valueParameters[0].symbol))
|
||||
result.putValueArgument(1,
|
||||
IrGetValueImpl(startOffset, endOffset, enumClassConstructor.valueParameters[1].symbol))
|
||||
|
||||
descriptor.valueParameters.forEach { 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")
|
||||
}
|
||||
|
||||
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(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")
|
||||
}
|
||||
|
||||
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) {
|
||||
override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: ClassConstructorDescriptor)
|
||||
= IrDelegatingConstructorCallImpl(startOffset, endOffset, loweredConstructor)
|
||||
override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol)
|
||||
= IrDelegatingConstructorCallImpl(startOffset, endOffset, loweredConstructor, loweredConstructor.descriptor)
|
||||
}
|
||||
|
||||
private inner class InEnumEntryInitializer(enumEntry: ClassDescriptor) : InEnumEntry(enumEntry) {
|
||||
override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: ClassConstructorDescriptor)
|
||||
= IrCallImpl(startOffset, endOffset, defaultEnumEntryConstructors[loweredConstructor] ?: loweredConstructor)
|
||||
override fun createConstructorCall(startOffset: Int, endOffset: Int, loweredConstructor: IrConstructorSymbol): IrCall {
|
||||
return IrCallImpl(startOffset, endOffset,
|
||||
defaultEnumEntryConstructors[loweredConstructor.descriptor]?.symbol ?: loweredConstructor)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class EnumClassBodyTransformer : IrElementTransformerVoid() {
|
||||
@@ -571,7 +568,7 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
enumConstructorCallTransformer = InEnumEntryClassConstructor(containingClass)
|
||||
} else if (containingClass.kind == ClassKind.ENUM_CLASS) {
|
||||
assert(enumConstructorCallTransformer == null) { "Nested enum entry initialization:\n${declaration.dump()}" }
|
||||
enumConstructorCallTransformer = InEnumClassConstructor(constructorDescriptor)
|
||||
enumConstructorCallTransformer = InEnumClassConstructor(declaration)
|
||||
}
|
||||
|
||||
val result = super.visitConstructor(declaration)
|
||||
@@ -605,10 +602,15 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
val loweredParameter = loweredEnumConstructorParameters[expression.descriptor]
|
||||
if (loweredParameter != null)
|
||||
return IrGetValueImpl(expression.startOffset, expression.endOffset, loweredParameter, expression.origin)
|
||||
else
|
||||
if (loweredParameter != null) {
|
||||
val loweredEnumConstructor = loweredEnumConstructors[expression.descriptor.containingDeclaration]!!
|
||||
val loweredIrParameter = loweredEnumConstructor.valueParameters[loweredParameter.index]
|
||||
assert(loweredIrParameter.descriptor == loweredParameter)
|
||||
return IrGetValueImpl(expression.startOffset, expression.endOffset,
|
||||
loweredIrParameter.symbol, expression.origin)
|
||||
} else {
|
||||
return expression
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -616,14 +618,14 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
|
||||
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 {
|
||||
val descriptor = expression.descriptor
|
||||
when (descriptor) {
|
||||
is ValueParameterDescriptor -> {
|
||||
return IrGetValueImpl(expression.startOffset,
|
||||
expression.endOffset,
|
||||
originalDescriptor.valueParameters[descriptor.index])
|
||||
originalConstructor.valueParameters[descriptor.index].symbol)
|
||||
}
|
||||
}
|
||||
return expression
|
||||
|
||||
+11
-13
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
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.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||
@@ -204,17 +205,21 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass
|
||||
name = Name.identifier("t"),
|
||||
outType = context.builtIns.throwable.defaultType
|
||||
)
|
||||
val catchParameter = IrVariableImpl(
|
||||
startOffset, endOffset, IrDeclarationOrigin.CATCH_PARAMETER, parameter)
|
||||
|
||||
val syntheticTry = IrTryImpl(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
type = context.builtIns.nothingType,
|
||||
tryResult = transformedTry,
|
||||
catches = listOf(
|
||||
irCatch(parameter,
|
||||
irBlock {
|
||||
irCatch(catchParameter).apply {
|
||||
result = irBlock {
|
||||
+finallyExpression.copy()
|
||||
+irThrow(irGet(parameter))
|
||||
})),
|
||||
+irThrow(irGet(catchParameter.symbol))
|
||||
}
|
||||
}),
|
||||
finallyExpression = null
|
||||
)
|
||||
using(TryScope(syntheticTry, transformedFinallyExpression, this)) {
|
||||
@@ -243,22 +248,15 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass
|
||||
+finallyExpression.copy()
|
||||
}
|
||||
else -> irBlock(value, null, returnType) {
|
||||
val tmp = IrTemporaryVariableDescriptorImpl(
|
||||
functionDescriptor,
|
||||
"tmp${tempIndex++}".synthesizedName,
|
||||
returnType
|
||||
)
|
||||
+irVar(tmp, irReturnableBlock(descriptor) {
|
||||
val tmp = irTemporary(irReturnableBlock(descriptor) {
|
||||
+irReturn(descriptor, value)
|
||||
})
|
||||
+finallyExpression.copy()
|
||||
+irGet(tmp)
|
||||
+irGet(tmp.symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var tempIndex = 0
|
||||
|
||||
private fun getFakeFunctionDescriptor(name: String, returnType: KotlinType): FunctionDescriptor {
|
||||
return SimpleFunctionDescriptorImpl.create(
|
||||
functionDescriptor,
|
||||
|
||||
+11
-11
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.ir.expressions.IrDelegatingConstructorCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrInstanceInitializerCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOriginImpl
|
||||
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.transformFlat
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
@@ -46,8 +47,8 @@ internal class InitializersLowering(val context: Context) : ClassLoweringPass {
|
||||
|
||||
fun lowerInitializers() {
|
||||
collectAndRemoveInitializers()
|
||||
val initializerMethodDescriptor = createInitializerMethod()
|
||||
lowerConstructors(initializerMethodDescriptor)
|
||||
val initializerMethodSymbol = createInitializerMethod()
|
||||
lowerConstructors(initializerMethodSymbol)
|
||||
}
|
||||
|
||||
object STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER :
|
||||
@@ -72,13 +73,12 @@ internal class InitializersLowering(val context: Context) : ClassLoweringPass {
|
||||
|
||||
override fun visitField(declaration: IrField): IrStatement {
|
||||
val initializer = declaration.initializer ?: return declaration
|
||||
val propertyDescriptor = declaration.descriptor
|
||||
val startOffset = initializer.startOffset
|
||||
val endOffset = initializer.endOffset
|
||||
initializers.add(IrBlockImpl(startOffset, endOffset, context.builtIns.unitType, STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER,
|
||||
listOf(
|
||||
IrSetFieldImpl(startOffset, endOffset, propertyDescriptor,
|
||||
IrGetValueImpl(startOffset, endOffset, irClass.descriptor.thisAsReceiverParameter),
|
||||
IrSetFieldImpl(startOffset, endOffset, declaration.symbol,
|
||||
IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol),
|
||||
initializer.expression, STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER))))
|
||||
declaration.initializer = null
|
||||
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())
|
||||
return null // Place initializers in the primary constructor.
|
||||
val initializerMethodDescriptor = SimpleFunctionDescriptorImpl.create(
|
||||
@@ -118,10 +118,10 @@ internal class InitializersLowering(val context: Context) : ClassLoweringPass {
|
||||
|
||||
irClass.declarations.add(initializer)
|
||||
|
||||
return initializerMethodDescriptor
|
||||
return initializer.symbol
|
||||
}
|
||||
|
||||
private fun lowerConstructors(initializerMethodDescriptor: FunctionDescriptor?) {
|
||||
private fun lowerConstructors(initializerMethodSymbol: IrSimpleFunctionSymbol?) {
|
||||
irClass.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
|
||||
override fun visitClass(declaration: IrClass): IrStatement {
|
||||
@@ -135,14 +135,14 @@ internal class InitializersLowering(val context: Context) : ClassLoweringPass {
|
||||
blockBody.statements.transformFlat {
|
||||
when {
|
||||
it is IrInstanceInitializerCall -> {
|
||||
if (initializerMethodDescriptor == null) {
|
||||
if (initializerMethodSymbol == null) {
|
||||
assert(declaration.descriptor.isPrimary)
|
||||
initializers
|
||||
} else {
|
||||
val startOffset = it.startOffset
|
||||
val endOffset = it.endOffset
|
||||
listOf(IrCallImpl(startOffset, endOffset, initializerMethodDescriptor).apply {
|
||||
dispatchReceiver = IrGetValueImpl(startOffset, endOffset, irClass.descriptor.thisAsReceiverParameter)
|
||||
listOf(IrCallImpl(startOffset, endOffset, initializerMethodSymbol).apply {
|
||||
dispatchReceiver = IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+16
-22
@@ -23,14 +23,14 @@ import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
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.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrGetValue
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
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.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
@@ -44,7 +44,7 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
||||
private inner class InnerClassTransformer(val irClass: IrClass) {
|
||||
val classDescriptor = irClass.descriptor
|
||||
|
||||
lateinit var outerThisFieldDescriptor: PropertyDescriptor
|
||||
lateinit var outerThisFieldSymbol: IrFieldSymbol
|
||||
|
||||
fun lowerInnerClass() {
|
||||
if (!irClass.descriptor.isInner) return
|
||||
@@ -54,17 +54,10 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
||||
lowerConstructors()
|
||||
}
|
||||
|
||||
object DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS :
|
||||
IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS")
|
||||
|
||||
private fun createOuterThisField() {
|
||||
outerThisFieldDescriptor = context.specialDescriptorsFactory.getOuterThisFieldDescriptor(classDescriptor)
|
||||
|
||||
irClass.declarations.add(IrFieldImpl(
|
||||
irClass.startOffset, irClass.endOffset,
|
||||
DECLARATION_ORIGIN_FIELD_FOR_OUTER_THIS,
|
||||
outerThisFieldDescriptor
|
||||
))
|
||||
val field = context.specialDeclarationsFactory.getOuterThisField(classDescriptor)
|
||||
outerThisFieldSymbol = field.symbol
|
||||
irClass.declarations.add(field)
|
||||
}
|
||||
|
||||
private fun lowerConstructors() {
|
||||
@@ -86,9 +79,9 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
||||
blockBody.statements.add(
|
||||
0,
|
||||
IrSetFieldImpl(
|
||||
startOffset, endOffset, outerThisFieldDescriptor,
|
||||
IrGetValueImpl(startOffset, endOffset, classDescriptor.thisAsReceiverParameter),
|
||||
IrGetValueImpl(startOffset, endOffset, irConstructor.descriptor.dispatchReceiverParameter!!)
|
||||
startOffset, endOffset, outerThisFieldSymbol,
|
||||
IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol),
|
||||
IrGetValueImpl(startOffset, endOffset, irConstructor.dispatchReceiverParameter!!.symbol)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -106,7 +99,7 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
||||
|
||||
if (implicitThisClass == classDescriptor) return expression
|
||||
|
||||
val constructorDescriptor = currentFunction!!.scope.scopeOwner as? ConstructorDescriptor
|
||||
val constructorSymbol = currentFunction!!.scope.scopeOwnerSymbol as? IrConstructorSymbol
|
||||
|
||||
val startOffset = expression.startOffset
|
||||
val endOffset = expression.endOffset
|
||||
@@ -114,14 +107,15 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
||||
|
||||
var irThis: IrExpression
|
||||
var innerClass: ClassDescriptor
|
||||
if (constructorDescriptor == null || constructorDescriptor.constructedClass != classDescriptor) {
|
||||
if (constructorSymbol == null || constructorSymbol.descriptor.constructedClass != classDescriptor) {
|
||||
innerClass = classDescriptor
|
||||
irThis = IrGetValueImpl(startOffset, endOffset, classDescriptor.thisAsReceiverParameter, origin)
|
||||
irThis = IrGetValueImpl(startOffset, endOffset, irClass.thisReceiver!!.symbol, origin)
|
||||
} else {
|
||||
// For constructor we have outer class as dispatchReceiverParameter.
|
||||
innerClass = DescriptorUtils.getContainingClass(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) {
|
||||
@@ -131,8 +125,8 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass {
|
||||
return expression
|
||||
}
|
||||
|
||||
val outerThisField = context.specialDescriptorsFactory.getOuterThisFieldDescriptor(innerClass)
|
||||
irThis = IrGetFieldImpl(startOffset, endOffset, outerThisField, irThis, origin)
|
||||
val outerThisField = context.specialDeclarationsFactory.getOuterThisField(innerClass)
|
||||
irThis = IrGetFieldImpl(startOffset, endOffset, outerThisField.symbol, irThis, origin)
|
||||
|
||||
val outer = innerClass.containingDeclaration
|
||||
innerClass = outer as? ClassDescriptor ?:
|
||||
|
||||
+30
-29
@@ -18,23 +18,21 @@ package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
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.descriptors.signature2Descriptor
|
||||
import org.jetbrains.kotlin.ir.builders.irLetSequence
|
||||
import org.jetbrains.kotlin.backend.konan.util.atMostOne
|
||||
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.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSymbolDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
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.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
@@ -57,30 +55,36 @@ private class StringConcatenationTransformer(val lower: StringConcatenationLower
|
||||
private val typesWithSpecialAppendFunction =
|
||||
PrimitiveType.values().map { builtIns.getPrimitiveKotlinType(it) } + builtIns.stringType
|
||||
|
||||
private val kotlinTextFqName = FqName.fromSegments(listOf("kotlin", "text"))
|
||||
private val nameToString = Name.identifier("toString")
|
||||
private val nameStringBuilder = Name.identifier("StringBuilder")
|
||||
private val nameAppend = Name.identifier("append")
|
||||
|
||||
private val classStringBuilder = builtIns.builtInsModule.getPackage(kotlinTextFqName).
|
||||
memberScope.getContributedClassifier(nameStringBuilder,
|
||||
NoLookupLocation.FROM_BACKEND) as ClassDescriptor
|
||||
private val stringBuilder = context.ir.symbols.stringBuilder
|
||||
|
||||
//TODO: calculate and pass string length to the constructor.
|
||||
private val constructor = classStringBuilder.constructors.firstOrNull {
|
||||
it.valueParameters.size == 0
|
||||
}!!
|
||||
private val constructor = stringBuilder.constructors.single {
|
||||
it.owner.valueParameters.size == 0
|
||||
}
|
||||
|
||||
private val toStringFunction = classStringBuilder.signature2Descriptor(nameToString)!!
|
||||
private val defaultAppendFunction =
|
||||
classStringBuilder.signature2Descriptor(nameAppend, arrayOf(builtIns.nullableAnyType))!!
|
||||
private val toStringFunction = stringBuilder.functions.single {
|
||||
it.owner.valueParameters.size == 0 && it.descriptor.name == nameToString
|
||||
}
|
||||
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 {
|
||||
it to classStringBuilder.signature2Descriptor(nameAppend, arrayOf(it))
|
||||
|
||||
private val appendFunctions: Map<KotlinType, IrFunctionSymbol?> =
|
||||
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()
|
||||
|
||||
private fun typeToAppendFunction(type : KotlinType) : FunctionDescriptor {
|
||||
private fun typeToAppendFunction(type : KotlinType) : IrFunctionSymbol {
|
||||
return appendFunctions[type]?:defaultAppendFunction
|
||||
}
|
||||
|
||||
@@ -89,11 +93,8 @@ private class StringConcatenationTransformer(val lower: StringConcatenationLower
|
||||
|
||||
expression.transformChildrenVoid(this)
|
||||
val blockBuilder = buildersStack.last()
|
||||
return blockBuilder.irLetSequence(
|
||||
value = blockBuilder.irCall(constructor),
|
||||
startOffset = expression.startOffset,
|
||||
endOffset = expression.endOffset,
|
||||
resultType = expression.type) { stringBuilderImpl ->
|
||||
return blockBuilder.irBlock(expression) {
|
||||
val stringBuilderImpl = irTemporary(irCall(constructor)).symbol
|
||||
expression.arguments.forEach { arg ->
|
||||
val appendFunction = typeToAppendFunction(arg.type)
|
||||
+irCall(appendFunction).apply {
|
||||
|
||||
+6
-9
@@ -19,9 +19,7 @@ package org.jetbrains.kotlin.backend.konan.lower
|
||||
import org.jetbrains.kotlin.backend.common.FunctionLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.lower.*
|
||||
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.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
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.IrTypeOperator
|
||||
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.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
@@ -42,19 +41,17 @@ import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
*/
|
||||
internal class TypeOperatorLowering(val context: Context) : FunctionLoweringPass {
|
||||
override fun lower(irFunction: IrFunction) {
|
||||
val transformer = TypeOperatorTransformer(context, irFunction.descriptor)
|
||||
val transformer = TypeOperatorTransformer(context, irFunction.symbol)
|
||||
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)
|
||||
|
||||
val throwTypeCastException by lazy {
|
||||
context.builtIns.getKonanInternalFunctions("ThrowTypeCastException").single()
|
||||
}
|
||||
val throwTypeCastException = context.ir.symbols.ThrowTypeCastException
|
||||
|
||||
override fun visitFunction(declaration: IrFunction): IrStatement {
|
||||
// ignore inner functions during this pass
|
||||
@@ -93,7 +90,7 @@ private class TypeOperatorTransformer(val context: Context, val function: Functi
|
||||
|
||||
expression.argument.type.isNullable() -> {
|
||||
with (builder) {
|
||||
irLet(expression.argument) { argument ->
|
||||
irLetS(expression.argument) { argument ->
|
||||
irIfThenElse(
|
||||
type = expression.type,
|
||||
condition = irEqeqeq(irGet(argument), irNull()),
|
||||
@@ -123,7 +120,7 @@ private class TypeOperatorTransformer(val context: Context, val function: Functi
|
||||
val typeOperand = expression.typeOperand.erasure()
|
||||
|
||||
return builder.irBlock(expression) {
|
||||
+irLet(expression.argument) { variable ->
|
||||
+irLetS(expression.argument) { variable ->
|
||||
irIfThenElse(expression.type,
|
||||
condition = irIs(irGet(variable), typeOperand),
|
||||
thenPart = irImplicitCast(irGet(variable), typeOperand),
|
||||
|
||||
+17
-16
@@ -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.IrConstImpl
|
||||
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.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
@@ -138,31 +139,31 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar
|
||||
descriptor = arrayHandle.setMethodDescriptor,
|
||||
typeArguments = null
|
||||
)
|
||||
setArrayElementCall.dispatchReceiver = irGet(arrayTmpVariable.descriptor)
|
||||
setArrayElementCall.putValueArgument(0, if (hasSpreadElement) irGet(indexTmpVariable.descriptor) else irConstInt(i))
|
||||
setArrayElementCall.putValueArgument(1, irGet(dst.descriptor))
|
||||
setArrayElementCall.dispatchReceiver = irGet(arrayTmpVariable.symbol)
|
||||
setArrayElementCall.putValueArgument(0, if (hasSpreadElement) irGet(indexTmpVariable.symbol) else irConstInt(i))
|
||||
setArrayElementCall.putValueArgument(1, irGet(dst.symbol))
|
||||
block.statements.add(setArrayElementCall)
|
||||
if (hasSpreadElement) {
|
||||
block.statements.add(incrementVariable(indexTmpVariable.descriptor, kIntOne))
|
||||
block.statements.add(incrementVariable(indexTmpVariable.symbol, kIntOne))
|
||||
}
|
||||
} 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)
|
||||
val copyCall = irCall(arrayHandle.copyRangeToDescriptor, null).apply {
|
||||
extensionReceiver = irGet(dst.descriptor)
|
||||
putValueArgument(0, irGet(arrayTmpVariable.descriptor)) /* destination */
|
||||
extensionReceiver = irGet(dst.symbol)
|
||||
putValueArgument(0, irGet(arrayTmpVariable.symbol)) /* destination */
|
||||
putValueArgument(1, kIntZero) /* fromIndex */
|
||||
putValueArgument(2, irGet(arraySizeVariable.descriptor)) /* toIndex */
|
||||
putValueArgument(3, irGet(indexTmpVariable.descriptor)) /* destinationIndex */
|
||||
putValueArgument(2, irGet(arraySizeVariable.symbol)) /* toIndex */
|
||||
putValueArgument(3, irGet(indexTmpVariable.symbol)) /* destinationIndex */
|
||||
}
|
||||
block.statements.add(copyCall)
|
||||
block.statements.add(incrementVariable(indexTmpVariable.descriptor,
|
||||
irGet(arraySizeVariable.descriptor)))
|
||||
block.statements.add(incrementVariable(indexTmpVariable.symbol,
|
||||
irGet(arraySizeVariable.symbol)))
|
||||
log("element:$i:spread element> ${ir2string(element.expression)}")
|
||||
}
|
||||
}
|
||||
}
|
||||
block.statements.add(irGet(arrayTmpVariable.descriptor))
|
||||
block.statements.add(irGet(arrayTmpVariable.symbol))
|
||||
return block
|
||||
}
|
||||
}
|
||||
@@ -203,9 +204,9 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrBuilderWithScope.incrementVariable(descriptor: VariableDescriptor, value: IrExpression): IrExpression {
|
||||
return irSetVar(descriptor, intPlus().apply {
|
||||
dispatchReceiver = irGet(descriptor)
|
||||
private fun IrBuilderWithScope.incrementVariable(symbol: IrVariableSymbol, value: IrExpression): IrExpression {
|
||||
return irSetVar(symbol, intPlus().apply {
|
||||
dispatchReceiver = irGet(symbol)
|
||||
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 initialValue = irConstInt(notSpreadElementCount) as IrExpression
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
+386
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
+122
-6
@@ -19,17 +19,21 @@ package org.jetbrains.kotlin.ir.util
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
|
||||
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||
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.startOffset
|
||||
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.
|
||||
@@ -59,6 +63,32 @@ internal fun IrMemberAccessExpression.getArguments(): List<Pair<ParameterDescrip
|
||||
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.
|
||||
*/
|
||||
@@ -146,7 +176,93 @@ fun IrClass.createParameterDeclarations() {
|
||||
}
|
||||
|
||||
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 =
|
||||
(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()}")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user