Continue updating compiler to IR with symbols:
The symbols produced by the lowering are now bound. Also: * Simplify interop lowering and bridges building. * Refactor IR validation.
This commit is contained in:
committed by
GitHub
parent
9d6846947e
commit
d08438da5f
+10
-9
@@ -54,13 +54,14 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
|||||||
protected open fun IrExpression.useAsArgument(parameter: ParameterDescriptor): IrExpression =
|
protected open fun IrExpression.useAsArgument(parameter: ParameterDescriptor): IrExpression =
|
||||||
this.useAsValue(parameter)
|
this.useAsValue(parameter)
|
||||||
|
|
||||||
protected open fun IrExpression.useAsDispatchReceiver(function: CallableDescriptor): IrExpression =
|
protected open fun IrExpression.useAsDispatchReceiver(expression: IrMemberAccessExpression): IrExpression =
|
||||||
this.useAsArgument(function.dispatchReceiverParameter!!)
|
this.useAsArgument(expression.descriptor.dispatchReceiverParameter!!)
|
||||||
|
|
||||||
protected open fun IrExpression.useAsExtensionReceiver(function: CallableDescriptor): IrExpression =
|
protected open fun IrExpression.useAsExtensionReceiver(expression: IrMemberAccessExpression): IrExpression =
|
||||||
this.useAsArgument(function.extensionReceiverParameter!!)
|
this.useAsArgument(expression.descriptor.extensionReceiverParameter!!)
|
||||||
|
|
||||||
protected open fun IrExpression.useAsValueArgument(parameter: ValueParameterDescriptor): IrExpression =
|
protected open fun IrExpression.useAsValueArgument(expression: IrMemberAccessExpression,
|
||||||
|
parameter: ValueParameterDescriptor): IrExpression =
|
||||||
this.useAsArgument(parameter)
|
this.useAsArgument(parameter)
|
||||||
|
|
||||||
protected open fun IrExpression.useForVariable(variable: VariableDescriptor): IrExpression =
|
protected open fun IrExpression.useForVariable(variable: VariableDescriptor): IrExpression =
|
||||||
@@ -81,12 +82,12 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
|||||||
expression.transformChildrenVoid(this)
|
expression.transformChildrenVoid(this)
|
||||||
|
|
||||||
with(expression) {
|
with(expression) {
|
||||||
dispatchReceiver = dispatchReceiver?.useAsDispatchReceiver(descriptor)
|
dispatchReceiver = dispatchReceiver?.useAsDispatchReceiver(expression)
|
||||||
extensionReceiver = extensionReceiver?.useAsExtensionReceiver(descriptor)
|
extensionReceiver = extensionReceiver?.useAsExtensionReceiver(expression)
|
||||||
for (index in descriptor.valueParameters.indices) {
|
for (index in descriptor.valueParameters.indices) {
|
||||||
val argument = getValueArgument(index) ?: continue
|
val argument = getValueArgument(index) ?: continue
|
||||||
val parameter = descriptor.valueParameters[index]
|
val parameter = descriptor.valueParameters[index]
|
||||||
putValueArgument(index, argument.useAsValueArgument(parameter))
|
putValueArgument(index, argument.useAsValueArgument(expression, parameter))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,7 +241,7 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
|||||||
declaration.descriptor.valueParameters.forEach { parameter ->
|
declaration.descriptor.valueParameters.forEach { parameter ->
|
||||||
val defaultValue = declaration.getDefault(parameter)
|
val defaultValue = declaration.getDefault(parameter)
|
||||||
if (defaultValue is IrExpressionBody) {
|
if (defaultValue is IrExpressionBody) {
|
||||||
defaultValue.expression = defaultValue.expression.useAsValueArgument(parameter)
|
defaultValue.expression = defaultValue.expression.useAsArgument(parameter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+70
@@ -17,8 +17,12 @@
|
|||||||
package org.jetbrains.kotlin.backend.common
|
package org.jetbrains.kotlin.backend.common
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||||
@@ -44,6 +48,12 @@ class CheckIrElementVisitor(val builtIns: KotlinBuiltIns, val reportError: Repor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun IrSymbol.ensureBound(expression: IrExpression) {
|
||||||
|
if (!this.isBound) {
|
||||||
|
reportError(expression, "Unbound symbol ${this}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun <T> visitConst(expression: IrConst<T>) {
|
override fun <T> visitConst(expression: IrConst<T>) {
|
||||||
super.visitConst(expression)
|
super.visitConst(expression)
|
||||||
|
|
||||||
@@ -110,6 +120,8 @@ class CheckIrElementVisitor(val builtIns: KotlinBuiltIns, val reportError: Repor
|
|||||||
} else {
|
} else {
|
||||||
expression.ensureTypeIs(returnType)
|
expression.ensureTypeIs(returnType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expression.superQualifierSymbol?.ensureBound(expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) {
|
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) {
|
||||||
@@ -128,6 +140,7 @@ class CheckIrElementVisitor(val builtIns: KotlinBuiltIns, val reportError: Repor
|
|||||||
super.visitInstanceInitializerCall(expression)
|
super.visitInstanceInitializerCall(expression)
|
||||||
|
|
||||||
expression.ensureTypeIs(builtIns.unitType)
|
expression.ensureTypeIs(builtIns.unitType)
|
||||||
|
expression.classSymbol.ensureBound(expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitTypeOperator(expression: IrTypeOperatorCall) {
|
override fun visitTypeOperator(expression: IrTypeOperatorCall) {
|
||||||
@@ -173,6 +186,7 @@ class CheckIrElementVisitor(val builtIns: KotlinBuiltIns, val reportError: Repor
|
|||||||
super.visitReturn(expression)
|
super.visitReturn(expression)
|
||||||
|
|
||||||
expression.ensureTypeIs(builtIns.nothingType)
|
expression.ensureTypeIs(builtIns.nothingType)
|
||||||
|
expression.returnTargetSymbol.ensureBound(expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitThrow(expression: IrThrow) {
|
override fun visitThrow(expression: IrThrow) {
|
||||||
@@ -180,4 +194,60 @@ class CheckIrElementVisitor(val builtIns: KotlinBuiltIns, val reportError: Repor
|
|||||||
|
|
||||||
expression.ensureTypeIs(builtIns.nothingType)
|
expression.ensureTypeIs(builtIns.nothingType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitClass(declaration: IrClass) {
|
||||||
|
super.visitClass(declaration)
|
||||||
|
|
||||||
|
if (declaration.descriptor.kind != ClassKind.ANNOTATION_CLASS) {
|
||||||
|
// Check that all functions and properties from memberScope are present in IR
|
||||||
|
// (including FAKE_OVERRIDE ones).
|
||||||
|
|
||||||
|
val allDescriptors = declaration.descriptor.unsubstitutedMemberScope
|
||||||
|
.getContributedDescriptors().filterIsInstance<CallableMemberDescriptor>()
|
||||||
|
|
||||||
|
val presentDescriptors = declaration.declarations.map { it.descriptor }
|
||||||
|
|
||||||
|
val missingDescriptors = allDescriptors - presentDescriptors
|
||||||
|
|
||||||
|
if (missingDescriptors.isNotEmpty()) {
|
||||||
|
reportError(declaration, "Missing declarations for descriptors:\n" +
|
||||||
|
missingDescriptors.joinToString("\n"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+16
-136
@@ -16,54 +16,18 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.common
|
package org.jetbrains.kotlin.backend.common
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlock
|
import org.jetbrains.kotlin.backend.konan.ir.DeepCopyKonanIrTreeWithSymbols
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlockImpl
|
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
|
||||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.expressions.IrLoop
|
||||||
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.util.DeepCopySymbolsRemapper
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.util.DescriptorsRemapper
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||||
|
|
||||||
/**
|
fun IrElement.deepCopyWithVariablesImpl(): IrElement {
|
||||||
* Copies IR tree with descriptors of all declarations inside;
|
val descriptorsRemapper = object : DescriptorsRemapper {
|
||||||
* updates the references to these declarations.
|
override fun remapDeclaredVariable(descriptor: VariableDescriptor) = LocalVariableDescriptor(
|
||||||
*/
|
|
||||||
@Deprecated("Creates unbound symbols")
|
|
||||||
open class DeepCopyIrTreeWithDeclarations : DeepCopyIrTree() {
|
|
||||||
|
|
||||||
private fun DeclarationDescriptor.notSupported(): Nothing = TODO("${this}")
|
|
||||||
|
|
||||||
override fun mapModuleDescriptor(descriptor: ModuleDescriptor) = descriptor.notSupported()
|
|
||||||
override fun mapPackageFragmentDescriptor(descriptor: PackageFragmentDescriptor) = descriptor.notSupported()
|
|
||||||
override fun mapClassDeclaration(descriptor: ClassDescriptor) = descriptor.notSupported()
|
|
||||||
override fun mapTypeAliasDeclaration(descriptor: TypeAliasDescriptor) = descriptor.notSupported()
|
|
||||||
override fun mapFunctionDeclaration(descriptor: FunctionDescriptor) = descriptor.notSupported()
|
|
||||||
override fun mapConstructorDeclaration(descriptor: ClassConstructorDescriptor) = descriptor.notSupported()
|
|
||||||
override fun mapPropertyDeclaration(descriptor: PropertyDescriptor) = descriptor.notSupported()
|
|
||||||
override fun mapLocalPropertyDeclaration(descriptor: VariableDescriptorWithAccessors) = descriptor.notSupported()
|
|
||||||
override fun mapEnumEntryDeclaration(descriptor: ClassDescriptor) = descriptor.notSupported()
|
|
||||||
|
|
||||||
val copiedVariables = mutableMapOf<VariableDescriptor, VariableDescriptor>()
|
|
||||||
|
|
||||||
override fun mapVariableDeclaration(descriptor: VariableDescriptor): VariableDescriptor {
|
|
||||||
// TODO: how to ensure that the variable is not visible from outside of the transformed IR?
|
|
||||||
|
|
||||||
if (descriptor is VariableDescriptorWithAccessors && (descriptor.getter != null || descriptor.setter != null)) {
|
|
||||||
TODO("$descriptor with accessors")
|
|
||||||
}
|
|
||||||
|
|
||||||
val newDescriptor = LocalVariableDescriptor(
|
|
||||||
/* containingDeclaration = */ descriptor.containingDeclaration,
|
/* containingDeclaration = */ descriptor.containingDeclaration,
|
||||||
/* annotations = */ descriptor.annotations,
|
/* annotations = */ descriptor.annotations,
|
||||||
/* name = */ descriptor.name,
|
/* name = */ descriptor.name,
|
||||||
@@ -72,103 +36,19 @@ open class DeepCopyIrTreeWithDeclarations : DeepCopyIrTree() {
|
|||||||
/* isDelegated = */ false,
|
/* isDelegated = */ false,
|
||||||
/* source = */ descriptor.source
|
/* source = */ descriptor.source
|
||||||
)
|
)
|
||||||
|
|
||||||
assert (descriptor !in copiedVariables)
|
|
||||||
copiedVariables[descriptor] = newDescriptor
|
|
||||||
|
|
||||||
return newDescriptor
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: the reference to a variable can be traversed only after the declaration of that variable,
|
val symbolsRemapper = DeepCopySymbolsRemapper(descriptorsRemapper)
|
||||||
// so it is correct to map only references whose descriptors have copies.
|
acceptVoid(symbolsRemapper)
|
||||||
// However such approach can be incorrect when copying functions, classes etc.
|
|
||||||
|
|
||||||
override fun mapValueReference(descriptor: ValueDescriptor) =
|
return this.transform(
|
||||||
copiedVariables[descriptor] ?: descriptor
|
object : DeepCopyKonanIrTreeWithSymbols(symbolsRemapper) {
|
||||||
|
override fun getNonTransformedLoop(irLoop: IrLoop): IrLoop {
|
||||||
override fun mapVariableReference(descriptor: VariableDescriptor) =
|
return irLoop
|
||||||
copiedVariables[descriptor] ?: descriptor
|
|
||||||
|
|
||||||
override fun visitBlock(expression: IrBlock): IrBlock {
|
|
||||||
return if (expression is IrReturnableBlock) {
|
|
||||||
IrReturnableBlockImpl(
|
|
||||||
startOffset = expression.startOffset,
|
|
||||||
endOffset = expression.endOffset,
|
|
||||||
type = expression.type,
|
|
||||||
descriptor = expression.descriptor,
|
|
||||||
origin = mapStatementOrigin(expression.origin),
|
|
||||||
statements = expression.statements.map { it.transform(this, null) }
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
super.visitBlock(expression)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
null
|
||||||
}
|
)
|
||||||
|
|
||||||
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 =
|
inline fun <reified T : IrElement> T.deepCopyWithVariables(): T =
|
||||||
|
|||||||
+1
-3
@@ -86,9 +86,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: DeclarationDe
|
|||||||
val contributedDescriptors = oldDescriptor.unsubstitutedMemberScope
|
val contributedDescriptors = oldDescriptor.unsubstitutedMemberScope
|
||||||
.getContributedDescriptors()
|
.getContributedDescriptors()
|
||||||
.map {
|
.map {
|
||||||
if (it is CallableMemberDescriptor && it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE)
|
descriptorSubstituteMap[it]!!
|
||||||
it
|
|
||||||
else descriptorSubstituteMap[it]!!
|
|
||||||
}
|
}
|
||||||
newDescriptor.initialize(
|
newDescriptor.initialize(
|
||||||
SimpleMemberScope(contributedDescriptors),
|
SimpleMemberScope(contributedDescriptors),
|
||||||
|
|||||||
+1
-153
@@ -16,21 +16,12 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.common
|
package org.jetbrains.kotlin.backend.common
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
|
||||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
|
||||||
import org.jetbrains.kotlin.ir.util.render
|
import org.jetbrains.kotlin.ir.util.render
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
|
||||||
|
|
||||||
fun validateIrFunction(context: BackendContext, irFunction: IrFunction) {
|
|
||||||
val visitor = IrValidator(context, false)
|
|
||||||
irFunction.acceptVoid(visitor)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun validateIrFile(context: BackendContext, irFile: IrFile) {
|
fun validateIrFile(context: BackendContext, irFile: IrFile) {
|
||||||
val visitor = IrValidator(context, false)
|
val visitor = IrValidator(context, false)
|
||||||
@@ -41,51 +32,7 @@ fun validateIrModule(context: BackendContext, irModule: IrModuleFragment) {
|
|||||||
val visitor = IrValidator(context, true) // TODO: consider taking the boolean from settings.
|
val visitor = IrValidator(context, true) // TODO: consider taking the boolean from settings.
|
||||||
irModule.acceptVoid(visitor)
|
irModule.acceptVoid(visitor)
|
||||||
|
|
||||||
// TODO: investigate and re-enable
|
// TODO: also check that all referenced symbol targets are reachable.
|
||||||
val ENABLE_EXTENDED_VALIDATION = false
|
|
||||||
if (!ENABLE_EXTENDED_VALIDATION) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val moduleDeclarations = visitor.foundDeclarations
|
|
||||||
|
|
||||||
irModule.acceptVoid(object : IrElementVisitorVoid {
|
|
||||||
lateinit var currentFile: IrFile
|
|
||||||
|
|
||||||
override fun visitFile(declaration: IrFile) {
|
|
||||||
currentFile = declaration
|
|
||||||
declaration.acceptChildrenVoid(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitElement(element: IrElement) {
|
|
||||||
element.acceptChildrenVoid(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitProperty(declaration: IrProperty) {
|
|
||||||
if (declaration.descriptor.modality == Modality.ABSTRACT) {
|
|
||||||
return // Workaround TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
declaration.acceptChildrenVoid(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitDeclarationReference(expression: IrDeclarationReference) {
|
|
||||||
expression.acceptChildrenVoid(this)
|
|
||||||
|
|
||||||
val declarationDescriptor = expression.irDeclarationDescriptor ?: return
|
|
||||||
|
|
||||||
val declarationModule = declarationDescriptor.module
|
|
||||||
|
|
||||||
if (declarationModule == irModule.descriptor && !moduleDeclarations.hasTarget(expression)) {
|
|
||||||
context.reportIrValidationError(
|
|
||||||
"declaration $declarationDescriptor is missing;\n" +
|
|
||||||
"references from:\n" +
|
|
||||||
expression.render(),
|
|
||||||
|
|
||||||
currentFile, expression)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun BackendContext.reportIrValidationError(message: String, irFile: IrFile, irElement: IrElement) {
|
private fun BackendContext.reportIrValidationError(message: String, irFile: IrFile, irElement: IrElement) {
|
||||||
@@ -98,86 +45,8 @@ private fun BackendContext.reportIrValidationError(message: String, irFile: IrFi
|
|||||||
// TODO: throw an exception after fixing bugs leading to invalid IR.
|
// TODO: throw an exception after fixing bugs leading to invalid IR.
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Descriptor to be found in IR element declaring target of this reference,
|
|
||||||
* or `null` if it is not supported yet.
|
|
||||||
*/
|
|
||||||
private val IrDeclarationReference.irDeclarationDescriptor: DeclarationDescriptor?
|
|
||||||
get() {
|
|
||||||
when (this) {
|
|
||||||
is IrFieldAccessExpression -> return this.descriptor.original
|
|
||||||
|
|
||||||
is IrMemberAccessExpression -> {
|
|
||||||
val original = this.descriptor.original
|
|
||||||
if (original is CallableMemberDescriptor && !original.kind.isReal) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (original is TypeAliasConstructorDescriptor) {
|
|
||||||
return original.underlyingConstructorDescriptor
|
|
||||||
}
|
|
||||||
|
|
||||||
return original
|
|
||||||
}
|
|
||||||
|
|
||||||
is IrGetValue -> {
|
|
||||||
if (this.descriptor is ParameterDescriptor) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.descriptor
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> return this.descriptor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val IrDeclarationReference.declarationKind: IrDeclarationKind
|
|
||||||
get() = when (this) {
|
|
||||||
is IrClassReference, is IrGetObjectValue -> IrDeclarationKind.CLASS
|
|
||||||
is IrFieldAccessExpression -> IrDeclarationKind.FIELD
|
|
||||||
is IrGetEnumValue -> IrDeclarationKind.ENUM_ENTRY
|
|
||||||
is IrValueAccessExpression -> IrDeclarationKind.VARIABLE
|
|
||||||
is IrMemberAccessExpression -> when (this.descriptor) {
|
|
||||||
is ConstructorDescriptor -> IrDeclarationKind.CONSTRUCTOR
|
|
||||||
is PropertyDescriptor -> IrDeclarationKind.PROPERTY
|
|
||||||
is VariableDescriptorWithAccessors -> IrDeclarationKind.LOCAL_PROPERTY
|
|
||||||
else -> IrDeclarationKind.FUNCTION
|
|
||||||
}
|
|
||||||
else -> TODO()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The collection of IR declarations.
|
|
||||||
*/
|
|
||||||
private class Declarations {
|
|
||||||
private data class DeclarationKey(val descriptor: DeclarationDescriptor, val kind: IrDeclarationKind)
|
|
||||||
|
|
||||||
private val declarations = mutableSetOf<DeclarationKey>()
|
|
||||||
|
|
||||||
private fun createKey(declaration: IrDeclaration) =
|
|
||||||
DeclarationKey(declaration.descriptor, declaration.declarationKind)
|
|
||||||
|
|
||||||
fun add(declaration: IrDeclaration) {
|
|
||||||
declarations.add(createKey(declaration))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isAlreadyDeclared(declaration: IrDeclaration): Boolean {
|
|
||||||
return createKey(declaration) in declarations
|
|
||||||
}
|
|
||||||
|
|
||||||
fun hasTarget(reference: IrDeclarationReference): Boolean {
|
|
||||||
val descriptor = reference.irDeclarationDescriptor ?: return false
|
|
||||||
val kind = reference.declarationKind
|
|
||||||
|
|
||||||
return DeclarationKey(descriptor, kind) in declarations
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class IrValidator(val context: BackendContext, performHeavyValidations: Boolean) : IrElementVisitorVoid {
|
private class IrValidator(val context: BackendContext, performHeavyValidations: Boolean) : IrElementVisitorVoid {
|
||||||
|
|
||||||
val foundDeclarations = Declarations()
|
|
||||||
|
|
||||||
val builtIns = context.builtIns
|
val builtIns = context.builtIns
|
||||||
lateinit var currentFile: IrFile
|
lateinit var currentFile: IrFile
|
||||||
|
|
||||||
@@ -200,25 +69,4 @@ private class IrValidator(val context: BackendContext, performHeavyValidations:
|
|||||||
element.acceptVoid(elementChecker)
|
element.acceptVoid(elementChecker)
|
||||||
element.acceptChildrenVoid(this)
|
element.acceptChildrenVoid(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun recordDeclaration(declaration: IrDeclaration) {
|
|
||||||
if (foundDeclarations.isAlreadyDeclared(declaration)) {
|
|
||||||
if (declaration !is IrValueParameter && declaration !is IrTypeParameter) {
|
|
||||||
// TODO: remove the check.
|
|
||||||
error(declaration, "redeclaration")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
foundDeclarations.add(declaration)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitDeclaration(declaration: IrDeclaration) {
|
|
||||||
recordDeclaration(declaration)
|
|
||||||
super.visitDeclaration(declaration)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer) {
|
|
||||||
// Do not treat anonymous initializers as declarations, because they are not unique.
|
|
||||||
super.visitDeclaration(declaration)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-14
@@ -58,20 +58,6 @@ internal val CallableDescriptor.explicitParameters: List<ParameterDescriptor>
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the parameter in the original function corresponding to given parameter of this function.
|
|
||||||
*
|
|
||||||
* Note: `parameter.original` doesn't seem to be always the parameter of `this.original`.
|
|
||||||
*
|
|
||||||
* @param parameter must be declared in this function
|
|
||||||
*/
|
|
||||||
fun CallableDescriptor.getOriginalParameter(parameter: ParameterDescriptor): ParameterDescriptor = when (parameter) {
|
|
||||||
is ValueParameterDescriptor -> this.original.valueParameters[parameter.index]
|
|
||||||
this.dispatchReceiverParameter -> this.original.dispatchReceiverParameter!!
|
|
||||||
this.extensionReceiverParameter -> this.original.extensionReceiverParameter!!
|
|
||||||
else -> TODO("$parameter in $this")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun KotlinType.replace(types: List<KotlinType>) = this.replace(types.map(::TypeProjectionImpl))
|
fun KotlinType.replace(types: List<KotlinType>) = this.replace(types.map(::TypeProjectionImpl))
|
||||||
|
|
||||||
fun FunctionDescriptor.substitute(vararg types: KotlinType): FunctionDescriptor {
|
fun FunctionDescriptor.substitute(vararg types: KotlinType): FunctionDescriptor {
|
||||||
@@ -83,6 +69,13 @@ fun FunctionDescriptor.substitute(vararg types: KotlinType): FunctionDescriptor
|
|||||||
return substitute(typeSubstitutor)!!
|
return substitute(typeSubstitutor)!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun FunctionDescriptor.substitute(typeArguments: Map<TypeParameterDescriptor, KotlinType>): FunctionDescriptor {
|
||||||
|
val typeSubstitutor = TypeSubstitutor.create(
|
||||||
|
typeParameters.associateBy({ it.typeConstructor }, { TypeProjectionImpl(typeArguments[it]!!) })
|
||||||
|
)
|
||||||
|
return substitute(typeSubstitutor)!!
|
||||||
|
}
|
||||||
|
|
||||||
fun ClassDescriptor.getFunction(name: String, types: List<KotlinType>): FunctionDescriptor {
|
fun ClassDescriptor.getFunction(name: String, types: List<KotlinType>): FunctionDescriptor {
|
||||||
val typeSubstitutor = TypeSubstitutor.create(
|
val typeSubstitutor = TypeSubstitutor.create(
|
||||||
declaredTypeParameters
|
declaredTypeParameters
|
||||||
|
|||||||
+15
-64
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.ir.IrStatement
|
|||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrDelegatingConstructorCall
|
import org.jetbrains.kotlin.ir.expressions.IrDelegatingConstructorCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||||
@@ -48,39 +47,16 @@ import org.jetbrains.kotlin.utils.Printer
|
|||||||
|
|
||||||
class IrLoweringContext(backendContext: BackendContext) : IrGeneratorContext(backendContext.irBuiltIns)
|
class IrLoweringContext(backendContext: BackendContext) : IrGeneratorContext(backendContext.irBuiltIns)
|
||||||
|
|
||||||
class DeclarationIrBuilder : IrBuilderWithScope {
|
class DeclarationIrBuilder(
|
||||||
|
backendContext: BackendContext,
|
||||||
constructor(
|
symbol: IrSymbol,
|
||||||
backendContext: BackendContext,
|
startOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET
|
||||||
symbol: IrSymbol,
|
) : IrBuilderWithScope(
|
||||||
startOffset: Int = UNDEFINED_OFFSET,
|
IrLoweringContext(backendContext),
|
||||||
endOffset: Int = UNDEFINED_OFFSET
|
Scope(symbol),
|
||||||
) : super(
|
startOffset,
|
||||||
IrLoweringContext(backendContext),
|
endOffset
|
||||||
Scope(symbol),
|
)
|
||||||
startOffset,
|
|
||||||
endOffset
|
|
||||||
)
|
|
||||||
|
|
||||||
@Deprecated("Creates unbound symbol")
|
|
||||||
constructor(
|
|
||||||
backendContext: BackendContext,
|
|
||||||
declarationDescriptor: DeclarationDescriptor,
|
|
||||||
startOffset: Int = UNDEFINED_OFFSET,
|
|
||||||
endOffset: Int = UNDEFINED_OFFSET
|
|
||||||
) : super(
|
|
||||||
IrLoweringContext(backendContext),
|
|
||||||
Scope(declarationDescriptor),
|
|
||||||
startOffset,
|
|
||||||
endOffset
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated("Creates unbound symbol")
|
|
||||||
fun BackendContext.createIrBuilder(declarationDescriptor: DeclarationDescriptor,
|
|
||||||
startOffset: Int = UNDEFINED_OFFSET,
|
|
||||||
endOffset: Int = UNDEFINED_OFFSET) =
|
|
||||||
DeclarationIrBuilder(this, declarationDescriptor, startOffset, endOffset)
|
|
||||||
|
|
||||||
fun BackendContext.createIrBuilder(symbol: IrSymbol,
|
fun BackendContext.createIrBuilder(symbol: IrSymbol,
|
||||||
startOffset: Int = UNDEFINED_OFFSET,
|
startOffset: Int = UNDEFINED_OFFSET,
|
||||||
@@ -101,25 +77,9 @@ inline fun IrGeneratorWithScope.irBlock(expression: IrExpression, origin: IrStat
|
|||||||
inline fun IrGeneratorWithScope.irBlockBody(irElement: IrElement, body: IrBlockBodyBuilder.() -> Unit) =
|
inline fun IrGeneratorWithScope.irBlockBody(irElement: IrElement, body: IrBlockBodyBuilder.() -> Unit) =
|
||||||
this.irBlockBody(irElement.startOffset, irElement.endOffset, body)
|
this.irBlockBody(irElement.startOffset, irElement.endOffset, body)
|
||||||
|
|
||||||
|
|
||||||
@Deprecated("Creates unbound symbol")
|
|
||||||
fun IrBuilderWithScope.irUnit() =
|
|
||||||
IrGetObjectValueImpl(startOffset, endOffset, context.builtIns.unitType, context.builtIns.unit)
|
|
||||||
|
|
||||||
fun IrBuilderWithScope.irIfThen(condition: IrExpression, thenPart: IrExpression) =
|
fun IrBuilderWithScope.irIfThen(condition: IrExpression, thenPart: IrExpression) =
|
||||||
IrIfThenElseImpl(startOffset, endOffset, context.builtIns.unitType, condition, thenPart, null)
|
IrIfThenElseImpl(startOffset, endOffset, context.builtIns.unitType, condition, thenPart, null)
|
||||||
|
|
||||||
@Deprecated("Creates unbound symbol")
|
|
||||||
fun IrBuilderWithScope.irGet(descriptor: PropertyDescriptor) =
|
|
||||||
IrCallImpl(startOffset, endOffset, descriptor.getter!!)
|
|
||||||
|
|
||||||
@Deprecated("Creates unbound symbol")
|
|
||||||
fun IrBuilderWithScope.irSet(receiver: IrExpression, descriptor: PropertyDescriptor, arg: IrExpression) =
|
|
||||||
IrCallImpl(startOffset, endOffset, descriptor.setter!!).apply {
|
|
||||||
dispatchReceiver = receiver
|
|
||||||
putValueArgument(0, arg)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun IrBuilderWithScope.irNot(arg: IrExpression) =
|
fun IrBuilderWithScope.irNot(arg: IrExpression) =
|
||||||
primitiveOp1(startOffset, endOffset, context.irBuiltIns.booleanNotSymbol, IrStatementOrigin.EXCL, arg)
|
primitiveOp1(startOffset, endOffset, context.irBuiltIns.booleanNotSymbol, IrStatementOrigin.EXCL, arg)
|
||||||
|
|
||||||
@@ -139,30 +99,21 @@ fun IrBuilderWithScope.irImplicitCoercionToUnit(arg: IrExpression) =
|
|||||||
IrTypeOperatorCallImpl(startOffset, endOffset, context.builtIns.unitType,
|
IrTypeOperatorCallImpl(startOffset, endOffset, context.builtIns.unitType,
|
||||||
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, context.builtIns.unitType, arg)
|
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, context.builtIns.unitType, arg)
|
||||||
|
|
||||||
@Deprecated("Creates unbound symbol")
|
|
||||||
fun IrBuilderWithScope.irGetField(receiver: IrExpression, descriptor: PropertyDescriptor) =
|
|
||||||
IrGetFieldImpl(startOffset, endOffset, descriptor, receiver)
|
|
||||||
|
|
||||||
@Deprecated("Creates unbound symbol")
|
|
||||||
fun IrBuilderWithScope.irSetField(receiver: IrExpression, descriptor: PropertyDescriptor, value: IrExpression) =
|
|
||||||
IrSetFieldImpl(startOffset, endOffset, descriptor, receiver, value)
|
|
||||||
|
|
||||||
fun IrBuilderWithScope.irGetField(receiver: IrExpression, symbol: IrFieldSymbol) =
|
fun IrBuilderWithScope.irGetField(receiver: IrExpression, symbol: IrFieldSymbol) =
|
||||||
IrGetFieldImpl(startOffset, endOffset, symbol, receiver)
|
IrGetFieldImpl(startOffset, endOffset, symbol, receiver)
|
||||||
|
|
||||||
fun IrBuilderWithScope.irSetField(receiver: IrExpression, symbol: IrFieldSymbol, value: IrExpression) =
|
fun IrBuilderWithScope.irSetField(receiver: IrExpression, symbol: IrFieldSymbol, value: IrExpression) =
|
||||||
IrSetFieldImpl(startOffset, endOffset, symbol, receiver, value)
|
IrSetFieldImpl(startOffset, endOffset, symbol, receiver, value)
|
||||||
|
|
||||||
@Deprecated("Creates unbound symbol")
|
|
||||||
open class IrBuildingTransformer(private val context: BackendContext) : IrElementTransformerVoid() {
|
open class IrBuildingTransformer(private val context: BackendContext) : IrElementTransformerVoid() {
|
||||||
private var currentBuilder: IrBuilderWithScope? = null
|
private var currentBuilder: IrBuilderWithScope? = null
|
||||||
|
|
||||||
protected val builder: IrBuilderWithScope
|
protected val builder: IrBuilderWithScope
|
||||||
get() = currentBuilder!!
|
get() = currentBuilder!!
|
||||||
|
|
||||||
private inline fun <T> withBuilder(declarationDescriptor: DeclarationDescriptor, block: () -> T): T {
|
private inline fun <T> withBuilder(symbol: IrSymbol, block: () -> T): T {
|
||||||
val oldBuilder = currentBuilder
|
val oldBuilder = currentBuilder
|
||||||
currentBuilder = context.createIrBuilder(declarationDescriptor)
|
currentBuilder = context.createIrBuilder(symbol)
|
||||||
return try {
|
return try {
|
||||||
block()
|
block()
|
||||||
} finally {
|
} finally {
|
||||||
@@ -171,20 +122,20 @@ open class IrBuildingTransformer(private val context: BackendContext) : IrElemen
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitFunction(declaration: IrFunction): IrStatement {
|
override fun visitFunction(declaration: IrFunction): IrStatement {
|
||||||
withBuilder(declaration.descriptor) {
|
withBuilder(declaration.symbol) {
|
||||||
return super.visitFunction(declaration)
|
return super.visitFunction(declaration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitField(declaration: IrField): IrStatement {
|
override fun visitField(declaration: IrField): IrStatement {
|
||||||
withBuilder(declaration.descriptor) {
|
withBuilder(declaration.symbol) {
|
||||||
// Transforms initializer:
|
// Transforms initializer:
|
||||||
return super.visitField(declaration)
|
return super.visitField(declaration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer): IrStatement {
|
override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer): IrStatement {
|
||||||
withBuilder(declaration.descriptor) {
|
withBuilder(declaration.symbol) {
|
||||||
return super.visitAnonymousInitializer(declaration)
|
return super.visitAnonymousInitializer(declaration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -33,7 +33,7 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
|||||||
* This pass lowers tail recursion calls in `tailrec` functions.
|
* This pass lowers tail recursion calls in `tailrec` functions.
|
||||||
*
|
*
|
||||||
* Note: it currently can't handle local functions and classes declared in default arguments.
|
* Note: it currently can't handle local functions and classes declared in default arguments.
|
||||||
* See [DeepCopyIrTreeWithDeclarations].
|
* See [deepCopyWithVariables].
|
||||||
*/
|
*/
|
||||||
internal class TailrecLowering(val context: BackendContext) : FunctionLoweringPass {
|
internal class TailrecLowering(val context: BackendContext) : FunctionLoweringPass {
|
||||||
override fun lower(irFunction: IrFunction) {
|
override fun lower(irFunction: IrFunction) {
|
||||||
|
|||||||
+2
-4
@@ -25,10 +25,7 @@ import org.jetbrains.kotlin.descriptors.impl.*
|
|||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.util.endOffsetOrUndefined
|
|
||||||
import org.jetbrains.kotlin.ir.util.functions
|
|
||||||
import org.jetbrains.kotlin.ir.util.startOffsetOrUndefined
|
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
@@ -75,6 +72,7 @@ internal class EnumSpecialDeclarationsFactory(val context: Context) {
|
|||||||
implObjectDescriptor.initialize(memberScope, setOf(constructorDescriptor), constructorDescriptor)
|
implObjectDescriptor.initialize(memberScope, setOf(constructorDescriptor), constructorDescriptor)
|
||||||
val implObject = IrClassImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, implObjectDescriptor).apply {
|
val implObject = IrClassImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, implObjectDescriptor).apply {
|
||||||
createParameterDeclarations()
|
createParameterDeclarations()
|
||||||
|
addFakeOverrides()
|
||||||
}
|
}
|
||||||
|
|
||||||
val (itemGetterSymbol, itemGetterDescriptor) = getEnumItemGetter(enumClassDescriptor)
|
val (itemGetterSymbol, itemGetterDescriptor) = getEnumItemGetter(enumClassDescriptor)
|
||||||
|
|||||||
-46
@@ -16,17 +16,12 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.konan
|
package org.jetbrains.kotlin.backend.konan
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
|
||||||
import org.jetbrains.kotlin.types.StarProjectionImpl
|
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.types.replace
|
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
|
||||||
|
|
||||||
private val cPointerName = "CPointer"
|
private val cPointerName = "CPointer"
|
||||||
private val nativePointedName = "NativePointed"
|
private val nativePointedName = "NativePointed"
|
||||||
@@ -67,53 +62,12 @@ internal class InteropBuiltIns(builtIns: KonanBuiltIns) {
|
|||||||
TypeUtils.getClassDescriptor(extensionReceiverParameter.type) == nativePointed
|
TypeUtils.getClassDescriptor(extensionReceiverParameter.type) == nativePointed
|
||||||
}
|
}
|
||||||
|
|
||||||
val memberAt = packageScope.getContributedFunctions("memberAt").single()
|
|
||||||
|
|
||||||
val interpretNullablePointed = packageScope.getContributedFunctions("interpretNullablePointed").single()
|
val interpretNullablePointed = packageScope.getContributedFunctions("interpretNullablePointed").single()
|
||||||
|
|
||||||
val interpretCPointer = packageScope.getContributedFunctions("interpretCPointer").single()
|
val interpretCPointer = packageScope.getContributedFunctions("interpretCPointer").single()
|
||||||
|
|
||||||
val variableClass = packageScope.getContributedClassifier("CVariable") as ClassDescriptor
|
|
||||||
|
|
||||||
val arrayGetByIntIndex = packageScope.getContributedFunctions("get").single {
|
|
||||||
KotlinBuiltIns.isInt(it.valueParameters.single().type) &&
|
|
||||||
it.typeParameters.single().upperBounds.single() == variableClass.defaultType
|
|
||||||
}
|
|
||||||
|
|
||||||
val arrayGetByLongIndex = packageScope.getContributedFunctions("get").single {
|
|
||||||
KotlinBuiltIns.isLong(it.valueParameters.single().type) &&
|
|
||||||
it.typeParameters.single().upperBounds.single() == variableClass.defaultType
|
|
||||||
}
|
|
||||||
|
|
||||||
val allocUninitializedArrayWithIntLength = packageScope.getContributedFunctions("allocArray").single {
|
|
||||||
it.valueParameters.size == 1 && KotlinBuiltIns.isInt(it.valueParameters[0].type)
|
|
||||||
}
|
|
||||||
|
|
||||||
val allocUninitializedArrayWithLongLength = packageScope.getContributedFunctions("allocArray").single {
|
|
||||||
it.valueParameters.size == 1 && KotlinBuiltIns.isLong(it.valueParameters[0].type)
|
|
||||||
}
|
|
||||||
|
|
||||||
val allocVariable = packageScope.getContributedFunctions("alloc").single {
|
|
||||||
it.valueParameters.size == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
val readValue = packageScope.getContributedFunctions("readValue").single {
|
|
||||||
it.valueParameters.size == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
val readValueBySizeAndAlign = packageScope.getContributedFunctions("readValue").single {
|
|
||||||
it.valueParameters.size == 2
|
|
||||||
}
|
|
||||||
|
|
||||||
val typeOf = packageScope.getContributedFunctions("typeOf").single()
|
val typeOf = packageScope.getContributedFunctions("typeOf").single()
|
||||||
|
|
||||||
val variableTypeClass =
|
|
||||||
variableClass.unsubstitutedInnerClassesScope.getContributedClassifier("Type") as ClassDescriptor
|
|
||||||
|
|
||||||
val variableTypeSize = variableTypeClass.unsubstitutedMemberScope.getContributedVariables("size").single()
|
|
||||||
|
|
||||||
val variableTypeAlign = variableTypeClass.unsubstitutedMemberScope.getContributedVariables("align").single()
|
|
||||||
|
|
||||||
val nativeMemUtils = packageScope.getContributedClassifier("nativeMemUtils") as ClassDescriptor
|
val nativeMemUtils = packageScope.getContributedClassifier("nativeMemUtils") as ClassDescriptor
|
||||||
|
|
||||||
private val primitives = listOf(
|
private val primitives = listOf(
|
||||||
|
|||||||
+10
-20
@@ -19,13 +19,11 @@ package org.jetbrains.kotlin.backend.konan
|
|||||||
import org.jetbrains.kotlin.backend.common.runOnFilePostfix
|
import org.jetbrains.kotlin.backend.common.runOnFilePostfix
|
||||||
import org.jetbrains.kotlin.backend.common.lower.*
|
import org.jetbrains.kotlin.backend.common.lower.*
|
||||||
import org.jetbrains.kotlin.backend.common.validateIrFile
|
import org.jetbrains.kotlin.backend.common.validateIrFile
|
||||||
|
import org.jetbrains.kotlin.backend.common.validateIrModule
|
||||||
import org.jetbrains.kotlin.backend.konan.lower.*
|
import org.jetbrains.kotlin.backend.konan.lower.*
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
import org.jetbrains.kotlin.ir.util.IrSymbolBindingChecker
|
|
||||||
import org.jetbrains.kotlin.ir.util.replaceUnboundSymbols
|
import org.jetbrains.kotlin.ir.util.replaceUnboundSymbols
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
|
||||||
|
|
||||||
internal class KonanLower(val context: Context) {
|
internal class KonanLower(val context: Context) {
|
||||||
|
|
||||||
@@ -49,9 +47,14 @@ internal class KonanLower(val context: Context) {
|
|||||||
// Inlining must be run before other phases.
|
// Inlining must be run before other phases.
|
||||||
phaser.phase(KonanPhase.LOWER_INLINE) {
|
phaser.phase(KonanPhase.LOWER_INLINE) {
|
||||||
FunctionInlining(context).inline(irModule)
|
FunctionInlining(context).inline(irModule)
|
||||||
irModule.replaceUnboundSymbols(context)
|
|
||||||
irModule.checkSymbolsBound()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
phaser.phase(KonanPhase.LOWER_INTEROP_PART1) {
|
||||||
|
irModule.files.forEach(InteropLoweringPart1(context)::lower)
|
||||||
|
}
|
||||||
|
|
||||||
|
irModule.replaceUnboundSymbols(context)
|
||||||
|
validateIrModule(context, irModule)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun lowerFile(irFile: IrFile) {
|
fun lowerFile(irFile: IrFile) {
|
||||||
@@ -59,31 +62,24 @@ internal class KonanLower(val context: Context) {
|
|||||||
|
|
||||||
phaser.phase(KonanPhase.LOWER_STRING_CONCAT) {
|
phaser.phase(KonanPhase.LOWER_STRING_CONCAT) {
|
||||||
StringConcatenationLowering(context).lower(irFile)
|
StringConcatenationLowering(context).lower(irFile)
|
||||||
irFile.checkSymbolsBound()
|
|
||||||
}
|
}
|
||||||
phaser.phase(KonanPhase.LOWER_ENUMS) {
|
phaser.phase(KonanPhase.LOWER_ENUMS) {
|
||||||
EnumClassLowering(context).run(irFile)
|
EnumClassLowering(context).run(irFile)
|
||||||
irFile.checkSymbolsBound()
|
|
||||||
}
|
}
|
||||||
phaser.phase(KonanPhase.LOWER_INITIALIZERS) {
|
phaser.phase(KonanPhase.LOWER_INITIALIZERS) {
|
||||||
InitializersLowering(context).runOnFilePostfix(irFile)
|
InitializersLowering(context).runOnFilePostfix(irFile)
|
||||||
irFile.checkSymbolsBound()
|
|
||||||
}
|
}
|
||||||
phaser.phase(KonanPhase.LOWER_SHARED_VARIABLES) {
|
phaser.phase(KonanPhase.LOWER_SHARED_VARIABLES) {
|
||||||
SharedVariablesLowering(context).runOnFilePostfix(irFile)
|
SharedVariablesLowering(context).runOnFilePostfix(irFile)
|
||||||
irFile.checkSymbolsBound()
|
|
||||||
}
|
}
|
||||||
phaser.phase(KonanPhase.LOWER_DELEGATION) {
|
phaser.phase(KonanPhase.LOWER_DELEGATION) {
|
||||||
PropertyDelegationLowering(context).lower(irFile)
|
PropertyDelegationLowering(context).lower(irFile)
|
||||||
irFile.checkSymbolsBound()
|
|
||||||
}
|
}
|
||||||
phaser.phase(KonanPhase.LOWER_LOCAL_FUNCTIONS) {
|
phaser.phase(KonanPhase.LOWER_LOCAL_FUNCTIONS) {
|
||||||
LocalDeclarationsLowering(context).runOnFilePostfix(irFile)
|
LocalDeclarationsLowering(context).runOnFilePostfix(irFile)
|
||||||
irFile.checkSymbolsBound()
|
|
||||||
}
|
}
|
||||||
phaser.phase(KonanPhase.LOWER_TAILREC) {
|
phaser.phase(KonanPhase.LOWER_TAILREC) {
|
||||||
TailrecLowering(context).runOnFilePostfix(irFile)
|
TailrecLowering(context).runOnFilePostfix(irFile)
|
||||||
irFile.checkSymbolsBound()
|
|
||||||
}
|
}
|
||||||
phaser.phase(KonanPhase.LOWER_FINALLY) {
|
phaser.phase(KonanPhase.LOWER_FINALLY) {
|
||||||
FinallyBlocksLowering(context).runOnFilePostfix(irFile)
|
FinallyBlocksLowering(context).runOnFilePostfix(irFile)
|
||||||
@@ -101,8 +97,8 @@ internal class KonanLower(val context: Context) {
|
|||||||
phaser.phase(KonanPhase.LOWER_INNER_CLASSES) {
|
phaser.phase(KonanPhase.LOWER_INNER_CLASSES) {
|
||||||
InnerClassLowering(context).runOnFilePostfix(irFile)
|
InnerClassLowering(context).runOnFilePostfix(irFile)
|
||||||
}
|
}
|
||||||
phaser.phase(KonanPhase.LOWER_INTEROP) {
|
phaser.phase(KonanPhase.LOWER_INTEROP_PART2) {
|
||||||
InteropLowering(context).lower(irFile)
|
InteropLoweringPart2(context).lower(irFile)
|
||||||
}
|
}
|
||||||
phaser.phase(KonanPhase.LOWER_CALLABLES) {
|
phaser.phase(KonanPhase.LOWER_CALLABLES) {
|
||||||
CallableReferenceLowering(context).runOnFilePostfix(irFile)
|
CallableReferenceLowering(context).runOnFilePostfix(irFile)
|
||||||
@@ -118,7 +114,6 @@ internal class KonanLower(val context: Context) {
|
|||||||
}
|
}
|
||||||
phaser.phase(KonanPhase.BRIDGES_BUILDING) {
|
phaser.phase(KonanPhase.BRIDGES_BUILDING) {
|
||||||
BridgesBuilding(context).runOnFilePostfix(irFile)
|
BridgesBuilding(context).runOnFilePostfix(irFile)
|
||||||
DirectBridgesCallsLowering(context).runOnFilePostfix(irFile)
|
|
||||||
}
|
}
|
||||||
phaser.phase(KonanPhase.AUTOBOX) {
|
phaser.phase(KonanPhase.AUTOBOX) {
|
||||||
validateIrFile(context, irFile)
|
validateIrFile(context, irFile)
|
||||||
@@ -126,9 +121,4 @@ internal class KonanLower(val context: Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrElement.checkSymbolsBound() {
|
|
||||||
if (context.shouldVerifyIr()) {
|
|
||||||
this.acceptVoid(IrSymbolBindingChecker())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -30,13 +30,14 @@ enum class KonanPhase(val description: String,
|
|||||||
/* ... ... */ LOWER_INLINE_CONSTRUCTORS("Inline constructors transformation"),
|
/* ... ... */ LOWER_INLINE_CONSTRUCTORS("Inline constructors transformation"),
|
||||||
/* ... ... */ LOWER_INLINE("Functions inlining", LOWER_INLINE_CONSTRUCTORS),
|
/* ... ... */ LOWER_INLINE("Functions inlining", LOWER_INLINE_CONSTRUCTORS),
|
||||||
/* ... ... ... */ DESERIALIZER("Deserialize inline bodies"),
|
/* ... ... ... */ DESERIALIZER("Deserialize inline bodies"),
|
||||||
|
/* ... ... */ LOWER_INTEROP_PART1("Interop lowering, part 1", LOWER_INLINE),
|
||||||
/* ... ... */ LOWER_ENUMS("Enum classes lowering"),
|
/* ... ... */ LOWER_ENUMS("Enum classes lowering"),
|
||||||
/* ... ... */ LOWER_DELEGATION("Delegation lowering"),
|
/* ... ... */ LOWER_DELEGATION("Delegation lowering"),
|
||||||
/* ... ... */ LOWER_INITIALIZERS("Initializers lowering", LOWER_ENUMS),
|
/* ... ... */ LOWER_INITIALIZERS("Initializers lowering", LOWER_ENUMS),
|
||||||
/* ... ... */ LOWER_SHARED_VARIABLES("Shared Variable Lowering", LOWER_INITIALIZERS),
|
/* ... ... */ LOWER_SHARED_VARIABLES("Shared Variable Lowering", LOWER_INITIALIZERS),
|
||||||
/* ... ... */ LOWER_LOCAL_FUNCTIONS("Local Function Lowering", LOWER_SHARED_VARIABLES),
|
/* ... ... */ LOWER_LOCAL_FUNCTIONS("Local Function Lowering", LOWER_SHARED_VARIABLES),
|
||||||
/* ... ... */ LOWER_INTEROP("Interop lowering", LOWER_LOCAL_FUNCTIONS),
|
/* ... ... */ LOWER_INTEROP_PART2("Interop lowering, part 2", LOWER_LOCAL_FUNCTIONS),
|
||||||
/* ... ... */ LOWER_CALLABLES("Callable references Lowering", LOWER_INTEROP, LOWER_DELEGATION, LOWER_LOCAL_FUNCTIONS),
|
/* ... ... */ LOWER_CALLABLES("Callable references Lowering", LOWER_INTEROP_PART2, LOWER_DELEGATION, LOWER_LOCAL_FUNCTIONS),
|
||||||
/* ... ... */ LOWER_VARARG("Vararg lowering", LOWER_CALLABLES),
|
/* ... ... */ LOWER_VARARG("Vararg lowering", LOWER_CALLABLES),
|
||||||
/* ... ... */ LOWER_TAILREC("tailrec lowering", LOWER_LOCAL_FUNCTIONS),
|
/* ... ... */ LOWER_TAILREC("tailrec lowering", LOWER_LOCAL_FUNCTIONS),
|
||||||
/* ... ... */ LOWER_FINALLY("Finally blocks lowering", LOWER_INITIALIZERS, LOWER_LOCAL_FUNCTIONS, LOWER_TAILREC),
|
/* ... ... */ LOWER_FINALLY("Finally blocks lowering", LOWER_INITIALIZERS, LOWER_LOCAL_FUNCTIONS, LOWER_TAILREC),
|
||||||
|
|||||||
+100
-2
@@ -18,23 +18,29 @@ package org.jetbrains.kotlin.backend.konan.ir
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.KonanBuiltIns
|
import org.jetbrains.kotlin.backend.konan.KonanBuiltIns
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ValueType
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalClass
|
import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalClass
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalFunctions
|
import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalFunctions
|
||||||
|
import org.jetbrains.kotlin.backend.konan.descriptors.konanInternal
|
||||||
|
import org.jetbrains.kotlin.backend.konan.util.atMostOne
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
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.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi2ir.generators.SymbolTable
|
import org.jetbrains.kotlin.psi2ir.generators.SymbolTable
|
||||||
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
|
||||||
// This is what Context collects about IR.
|
// This is what Context collects about IR.
|
||||||
internal class Ir(val context: Context, val irModule: IrModuleFragment) {
|
internal class Ir(val context: Context, val irModule: IrModuleFragment) {
|
||||||
val propertiesWithBackingFields = mutableSetOf<PropertyDescriptor>()
|
val propertiesWithBackingFields = mutableSetOf<PropertyDescriptor>()
|
||||||
|
|
||||||
val defaultParameterDescriptorsCache = mutableMapOf<FunctionDescriptor, FunctionDescriptor>()
|
val defaultParameterDeclarationsCache = mutableMapOf<FunctionDescriptor, IrFunction>()
|
||||||
|
|
||||||
val originalModuleIndex = ModuleIndex(irModule)
|
val originalModuleIndex = ModuleIndex(irModule)
|
||||||
|
|
||||||
@@ -67,13 +73,31 @@ internal class Symbols(val context: Context, val symbolTable: SymbolTable) {
|
|||||||
val ThrowTypeCastException = symbolTable.referenceSimpleFunction(
|
val ThrowTypeCastException = symbolTable.referenceSimpleFunction(
|
||||||
builtIns.getKonanInternalFunctions("ThrowTypeCastException").single())
|
builtIns.getKonanInternalFunctions("ThrowTypeCastException").single())
|
||||||
|
|
||||||
|
val ThrowUninitializedPropertyAccessException = symbolTable.referenceSimpleFunction(
|
||||||
|
builtIns.getKonanInternalFunctions("ThrowUninitializedPropertyAccessException").single()
|
||||||
|
)
|
||||||
|
|
||||||
val stringBuilder = symbolTable.referenceClass(
|
val stringBuilder = symbolTable.referenceClass(
|
||||||
builtInsPackage("kotlin", "text").getContributedClassifier(
|
builtInsPackage("kotlin", "text").getContributedClassifier(
|
||||||
Name.identifier("StringBuilder"), NoLookupLocation.FROM_BACKEND
|
Name.identifier("StringBuilder"), NoLookupLocation.FROM_BACKEND
|
||||||
) as ClassDescriptor
|
) as ClassDescriptor
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val defaultArgumentMarker = symbolTable.referenceClass(
|
||||||
|
builtIns.konanInternal.getContributedClassifier(
|
||||||
|
Name.identifier("DefaultArgumentMarker"), NoLookupLocation.FROM_BACKEND
|
||||||
|
) as ClassDescriptor
|
||||||
|
)
|
||||||
|
|
||||||
val any = symbolTable.referenceClass(builtIns.any)
|
val any = symbolTable.referenceClass(builtIns.any)
|
||||||
|
val unit = symbolTable.referenceClass(builtIns.unit)
|
||||||
|
|
||||||
|
val byte = symbolTable.referenceClass(builtIns.byte)
|
||||||
|
val short = symbolTable.referenceClass(builtIns.short)
|
||||||
|
val int = symbolTable.referenceClass(builtIns.int)
|
||||||
|
val long = symbolTable.referenceClass(builtIns.long)
|
||||||
|
|
||||||
|
val integerClasses = listOf(byte, short, int, long)
|
||||||
|
|
||||||
val arrayOf = symbolTable.referenceSimpleFunction(
|
val arrayOf = symbolTable.referenceSimpleFunction(
|
||||||
builtInsPackage("kotlin").getContributedFunctions(
|
builtInsPackage("kotlin").getContributedFunctions(
|
||||||
@@ -83,12 +107,86 @@ internal class Symbols(val context: Context, val symbolTable: SymbolTable) {
|
|||||||
|
|
||||||
val array = symbolTable.referenceClass(builtIns.array)
|
val array = symbolTable.referenceClass(builtIns.array)
|
||||||
|
|
||||||
|
private fun primitiveArrayClass(type: PrimitiveType) =
|
||||||
|
symbolTable.referenceClass(builtIns.getPrimitiveArrayClassDescriptor(type))
|
||||||
|
|
||||||
|
val byteArray = primitiveArrayClass(PrimitiveType.BYTE)
|
||||||
|
val charArray = primitiveArrayClass(PrimitiveType.CHAR)
|
||||||
|
val shortArray = primitiveArrayClass(PrimitiveType.SHORT)
|
||||||
|
val intArray = primitiveArrayClass(PrimitiveType.INT)
|
||||||
|
val longArray = primitiveArrayClass(PrimitiveType.LONG)
|
||||||
|
val floatArray = primitiveArrayClass(PrimitiveType.FLOAT)
|
||||||
|
val doubleArray = primitiveArrayClass(PrimitiveType.DOUBLE)
|
||||||
|
val booleanArray = primitiveArrayClass(PrimitiveType.BOOLEAN)
|
||||||
|
|
||||||
|
val arrays = PrimitiveType.values().map { primitiveArrayClass(it) } + array
|
||||||
|
|
||||||
|
val copyRangeTo = arrays.map { symbol ->
|
||||||
|
val packageViewDescriptor = builtIns.builtInsModule.getPackage(KotlinBuiltIns.COLLECTIONS_PACKAGE_FQ_NAME)
|
||||||
|
val functionDescriptor = packageViewDescriptor.memberScope
|
||||||
|
.getContributedFunctions(Name.identifier("copyRangeTo"), NoLookupLocation.FROM_BACKEND)
|
||||||
|
.first {
|
||||||
|
it.extensionReceiverParameter?.type?.constructor?.declarationDescriptor == symbol.descriptor
|
||||||
|
}
|
||||||
|
symbol.descriptor to symbolTable.referenceSimpleFunction(functionDescriptor)
|
||||||
|
}.toMap()
|
||||||
|
|
||||||
|
val intAnd = symbolTable.referenceFunction(
|
||||||
|
builtIns.intType.memberScope
|
||||||
|
.getContributedFunctions(OperatorNameConventions.AND, NoLookupLocation.FROM_BACKEND)
|
||||||
|
.single()
|
||||||
|
)
|
||||||
|
|
||||||
|
val intPlusInt = symbolTable.referenceFunction(
|
||||||
|
builtIns.intType.memberScope
|
||||||
|
.getContributedFunctions(OperatorNameConventions.PLUS, NoLookupLocation.FROM_BACKEND)
|
||||||
|
.single {
|
||||||
|
it.valueParameters.single().type == builtIns.intType
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
val boxFunctions = ValueType.values().associate {
|
||||||
|
val boxFunctionName = "box${it.classFqName.shortName()}"
|
||||||
|
it to symbolTable.referenceSimpleFunction(context.builtIns.getKonanInternalFunctions(boxFunctionName).single())
|
||||||
|
}
|
||||||
|
|
||||||
|
val boxClasses = ValueType.values().associate {
|
||||||
|
it to symbolTable.referenceClass(context.builtIns.getKonanInternalClass("${it.classFqName.shortName()}Box"))
|
||||||
|
}
|
||||||
|
|
||||||
|
val unboxFunctions = ValueType.values().mapNotNull {
|
||||||
|
val unboxFunctionName = "unbox${it.classFqName.shortName()}"
|
||||||
|
context.builtIns.getKonanInternalFunctions(unboxFunctionName).atMostOne()?.let { descriptor ->
|
||||||
|
it to symbolTable.referenceSimpleFunction(descriptor)
|
||||||
|
}
|
||||||
|
}.toMap()
|
||||||
|
|
||||||
|
val interopNativePointedGetRawPointer =
|
||||||
|
symbolTable.referenceSimpleFunction(context.interopBuiltIns.nativePointedGetRawPointer)
|
||||||
|
|
||||||
|
val interopCPointerGetRawValue = symbolTable.referenceSimpleFunction(context.interopBuiltIns.cPointerGetRawValue)
|
||||||
|
|
||||||
|
val getNativeNullPtr = symbolTable.referenceSimpleFunction(builtIns.getNativeNullPtr)
|
||||||
|
|
||||||
val valuesForEnum = symbolTable.referenceSimpleFunction(
|
val valuesForEnum = symbolTable.referenceSimpleFunction(
|
||||||
builtIns.getKonanInternalFunctions("valuesForEnum").single())
|
builtIns.getKonanInternalFunctions("valuesForEnum").single())
|
||||||
|
|
||||||
val valueOfForEnum = symbolTable.referenceSimpleFunction(
|
val valueOfForEnum = symbolTable.referenceSimpleFunction(
|
||||||
builtIns.getKonanInternalFunctions("valueOfForEnum").single())
|
builtIns.getKonanInternalFunctions("valueOfForEnum").single())
|
||||||
|
|
||||||
|
val getContinuation = symbolTable.referenceSimpleFunction(
|
||||||
|
context.builtIns.getKonanInternalFunctions("getContinuation").single())
|
||||||
|
|
||||||
|
val coroutineImpl = symbolTable.referenceClass(context.builtIns.getKonanInternalClass("CoroutineImpl"))
|
||||||
|
|
||||||
|
val coroutineSuspendedGetter = symbolTable.referenceSimpleFunction(
|
||||||
|
builtInsPackage("kotlin", "coroutines", "experimental", "intrinsics")
|
||||||
|
.getContributedVariables(Name.identifier("COROUTINE_SUSPENDED"), NoLookupLocation.FROM_BACKEND)
|
||||||
|
.single().getter!!
|
||||||
|
)
|
||||||
|
|
||||||
|
val kFunctionImpl = symbolTable.referenceClass(context.builtIns.getKonanInternalClass("KFunctionImpl"))
|
||||||
|
|
||||||
val kProperty0Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty0Impl)
|
val kProperty0Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty0Impl)
|
||||||
val kProperty1Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty1Impl)
|
val kProperty1Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty1Impl)
|
||||||
val kProperty2Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty2Impl)
|
val kProperty2Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty2Impl)
|
||||||
|
|||||||
+6
@@ -51,6 +51,12 @@ class IrReturnableBlockImpl(startOffset: Int, endOffset: Int, type: KotlinType,
|
|||||||
|
|
||||||
override val descriptor = symbol.descriptor
|
override val descriptor = symbol.descriptor
|
||||||
|
|
||||||
|
constructor(startOffset: Int, endOffset: Int, type: KotlinType,
|
||||||
|
symbol: IrReturnableBlockSymbol, origin: IrStatementOrigin?, statements: List<IrStatement>) :
|
||||||
|
this(startOffset, endOffset, type, symbol, origin) {
|
||||||
|
this.statements.addAll(statements)
|
||||||
|
}
|
||||||
|
|
||||||
constructor(startOffset: Int, endOffset: Int, type: KotlinType,
|
constructor(startOffset: Int, endOffset: Int, type: KotlinType,
|
||||||
descriptor: FunctionDescriptor, origin: IrStatementOrigin? = null) :
|
descriptor: FunctionDescriptor, origin: IrStatementOrigin? = null) :
|
||||||
this(startOffset, endOffset, type, IrReturnableBlockSymbolImpl(descriptor), origin)
|
this(startOffset, endOffset, type, IrReturnableBlockSymbolImpl(descriptor), origin)
|
||||||
|
|||||||
+62
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.konan.ir
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrBlock
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrReturn
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
|
||||||
|
import org.jetbrains.kotlin.ir.util.DeepCopyIrTreeWithSymbols
|
||||||
|
import org.jetbrains.kotlin.ir.util.SymbolRemapper
|
||||||
|
|
||||||
|
internal open class DeepCopyKonanIrTreeWithSymbols(
|
||||||
|
private val symbolRemapper: SymbolRemapper
|
||||||
|
) : DeepCopyIrTreeWithSymbols(symbolRemapper) {
|
||||||
|
|
||||||
|
private inline fun <reified T : IrElement> T.transform() =
|
||||||
|
transform(this@DeepCopyKonanIrTreeWithSymbols, null) as T
|
||||||
|
|
||||||
|
private val transformedReturnableBlocks = mutableMapOf<IrReturnableBlock, IrReturnableBlock>()
|
||||||
|
|
||||||
|
override fun visitBlock(expression: IrBlock): IrBlock = if (expression is IrReturnableBlock) {
|
||||||
|
IrReturnableBlockImpl(
|
||||||
|
expression.startOffset, expression.endOffset,
|
||||||
|
expression.type,
|
||||||
|
expression.descriptor,
|
||||||
|
expression.origin
|
||||||
|
).also {
|
||||||
|
transformedReturnableBlocks.put(expression, it)
|
||||||
|
it.statements.addAll(expression.statements.map { it.transform() })
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
super.visitBlock(expression)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitReturn(expression: IrReturn): IrReturn {
|
||||||
|
val returnTargetSymbol = expression.returnTargetSymbol
|
||||||
|
return if (returnTargetSymbol is IrReturnableBlockSymbol) {
|
||||||
|
IrReturnImpl(
|
||||||
|
expression.startOffset, expression.endOffset,
|
||||||
|
expression.type,
|
||||||
|
transformedReturnableBlocks.getOrElse(returnTargetSymbol.owner) { returnTargetSymbol.owner }.symbol,
|
||||||
|
expression.value.transform()
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
super.visitReturn(expression)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+36
-24
@@ -20,8 +20,8 @@ import org.jetbrains.kotlin.backend.common.AbstractValueUsageTransformer
|
|||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.isSuspend
|
import org.jetbrains.kotlin.backend.common.descriptors.isSuspend
|
||||||
import org.jetbrains.kotlin.backend.konan.*
|
import org.jetbrains.kotlin.backend.konan.*
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalClass
|
||||||
import org.jetbrains.kotlin.backend.konan.util.atMostOne
|
import org.jetbrains.kotlin.backend.konan.descriptors.target
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
@@ -29,7 +29,10 @@ import org.jetbrains.kotlin.ir.declarations.IrFunction
|
|||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
|
||||||
|
import org.jetbrains.kotlin.ir.util.getPropertyGetter
|
||||||
import org.jetbrains.kotlin.ir.util.isNullConst
|
import org.jetbrains.kotlin.ir.util.isNullConst
|
||||||
|
import org.jetbrains.kotlin.ir.util.render
|
||||||
|
import org.jetbrains.kotlin.ir.util.type
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
@@ -50,6 +53,8 @@ internal class Autoboxing(val context: Context) : FileLoweringPass {
|
|||||||
|
|
||||||
private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTransformer(context.builtIns) {
|
private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTransformer(context.builtIns) {
|
||||||
|
|
||||||
|
val symbols = context.ir.symbols
|
||||||
|
|
||||||
// TODO: should we handle the cases when expression type
|
// TODO: should we handle the cases when expression type
|
||||||
// is not equal to e.g. called function return type?
|
// is not equal to e.g. called function return type?
|
||||||
|
|
||||||
@@ -133,13 +138,13 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr
|
|||||||
override fun IrExpression.useAs(type: KotlinType): IrExpression {
|
override fun IrExpression.useAs(type: KotlinType): IrExpression {
|
||||||
val interop = context.interopBuiltIns
|
val interop = context.interopBuiltIns
|
||||||
if (this.isNullConst() && interop.nullableInteropValueTypes.any { type.isRepresentedAs(it) }) {
|
if (this.isNullConst() && interop.nullableInteropValueTypes.any { type.isRepresentedAs(it) }) {
|
||||||
return IrCallImpl(startOffset, endOffset, context.builtIns.getNativeNullPtr).uncheckedCast(type)
|
return IrCallImpl(startOffset, endOffset, symbols.getNativeNullPtr).uncheckedCast(type)
|
||||||
}
|
}
|
||||||
|
|
||||||
val actualType = when (this) {
|
val actualType = when (this) {
|
||||||
is IrCall -> {
|
is IrCall -> {
|
||||||
if (this.descriptor.isSuspend) context.builtIns.nullableAnyType
|
if (this.descriptor.isSuspend) context.builtIns.nullableAnyType
|
||||||
else this.descriptor.original.returnType ?: this.type
|
else this.callTarget.returnType ?: this.type
|
||||||
}
|
}
|
||||||
is IrGetField -> this.descriptor.original.type
|
is IrGetField -> this.descriptor.original.type
|
||||||
|
|
||||||
@@ -157,17 +162,32 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr
|
|||||||
return this.adaptIfNecessary(actualType, type)
|
return this.adaptIfNecessary(actualType, type)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun IrExpression.useAsDispatchReceiver(function: CallableDescriptor): IrExpression {
|
private val IrMemberAccessExpression.target: CallableDescriptor get() = when (this) {
|
||||||
return this.useAsArgument(function.original.dispatchReceiverParameter!!)
|
is IrCall -> this.callTarget
|
||||||
|
is IrDelegatingConstructorCall -> this.descriptor.original
|
||||||
|
else -> TODO(this.render())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun IrExpression.useAsExtensionReceiver(function: CallableDescriptor): IrExpression {
|
private val IrCall.callTarget: FunctionDescriptor
|
||||||
return this.useAsArgument(function.original.extensionReceiverParameter!!)
|
get() = if (superQualifier == null && descriptor.isOverridable) {
|
||||||
|
// A virtual call.
|
||||||
|
descriptor.original
|
||||||
|
} else {
|
||||||
|
descriptor.target
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun IrExpression.useAsDispatchReceiver(expression: IrMemberAccessExpression): IrExpression {
|
||||||
|
return this.useAsArgument(expression.target.dispatchReceiverParameter!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun IrExpression.useAsValueArgument(parameter: ValueParameterDescriptor): IrExpression {
|
override fun IrExpression.useAsExtensionReceiver(expression: IrMemberAccessExpression): IrExpression {
|
||||||
val function = parameter.containingDeclaration
|
return this.useAsArgument(expression.target.extensionReceiverParameter!!)
|
||||||
return this.useAsArgument(function.original.valueParameters[parameter.index])
|
}
|
||||||
|
|
||||||
|
override fun IrExpression.useAsValueArgument(expression: IrMemberAccessExpression,
|
||||||
|
parameter: ValueParameterDescriptor): IrExpression {
|
||||||
|
|
||||||
|
return this.useAsArgument(expression.target.valueParameters[parameter.index])
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun IrExpression.useForField(field: PropertyDescriptor): IrExpression {
|
override fun IrExpression.useForField(field: PropertyDescriptor): IrExpression {
|
||||||
@@ -211,9 +231,7 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr
|
|||||||
context.builtIns.getKonanInternalClass("${valueType.shortName}Box").defaultType
|
context.builtIns.getKonanInternalClass("${valueType.shortName}Box").defaultType
|
||||||
|
|
||||||
private fun IrExpression.box(valueType: ValueType): IrExpression {
|
private fun IrExpression.box(valueType: ValueType): IrExpression {
|
||||||
val boxFunctionName = "box${valueType.shortName}"
|
val boxFunction = symbols.boxFunctions[valueType]!!
|
||||||
val boxFunction = context.builtIns.getKonanInternalFunctions(boxFunctionName).singleOrNull() ?:
|
|
||||||
TODO(valueType.toString())
|
|
||||||
|
|
||||||
return IrCallImpl(startOffset, endOffset, boxFunction).apply {
|
return IrCallImpl(startOffset, endOffset, boxFunction).apply {
|
||||||
putValueArgument(0, this@box)
|
putValueArgument(0, this@box)
|
||||||
@@ -221,22 +239,16 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun IrExpression.unbox(valueType: ValueType): IrExpression {
|
private fun IrExpression.unbox(valueType: ValueType): IrExpression {
|
||||||
val unboxFunctionName = "unbox${valueType.shortName}"
|
symbols.unboxFunctions[valueType]?.let {
|
||||||
|
|
||||||
context.builtIns.getKonanInternalFunctions(unboxFunctionName).atMostOne()?.let {
|
|
||||||
return IrCallImpl(startOffset, endOffset, it).apply {
|
return IrCallImpl(startOffset, endOffset, it).apply {
|
||||||
putValueArgument(0, this@unbox.uncheckedCast(it.valueParameters[0].type))
|
putValueArgument(0, this@unbox.uncheckedCast(it.owner.valueParameters[0].type))
|
||||||
}.uncheckedCast(this.type)
|
}.uncheckedCast(this.type)
|
||||||
}
|
}
|
||||||
|
|
||||||
val boxGetter = getBoxType(valueType)
|
val boxGetter = symbols.boxClasses[valueType]!!.getPropertyGetter("value")!!
|
||||||
.memberScope.getContributedDescriptors()
|
|
||||||
.filterIsInstance<PropertyDescriptor>()
|
|
||||||
.single { it.name.asString() == "value" }
|
|
||||||
.getter!!
|
|
||||||
|
|
||||||
return IrCallImpl(startOffset, endOffset, boxGetter).apply {
|
return IrCallImpl(startOffset, endOffset, boxGetter).apply {
|
||||||
dispatchReceiver = this@unbox.uncheckedCast(boxGetter.dispatchReceiverParameter!!.type)
|
dispatchReceiver = this@unbox.uncheckedCast(boxGetter.descriptor.dispatchReceiverParameter!!.type)
|
||||||
}.uncheckedCast(this.type) // Try not to bring new type incompatibilities.
|
}.uncheckedCast(this.type) // Try not to bring new type incompatibilities.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+31
-62
@@ -16,13 +16,11 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.konan.lower
|
package org.jetbrains.kotlin.backend.konan.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
|
|
||||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.common.lower.irBlockBody
|
import org.jetbrains.kotlin.backend.common.lower.irBlockBody
|
||||||
import org.jetbrains.kotlin.backend.common.lower.irIfThen
|
import org.jetbrains.kotlin.backend.common.lower.irIfThen
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.ValueType
|
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
@@ -36,6 +34,7 @@ import org.jetbrains.kotlin.ir.declarations.IrProperty
|
|||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
||||||
import org.jetbrains.kotlin.ir.util.type
|
import org.jetbrains.kotlin.ir.util.type
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
@@ -43,46 +42,6 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
|||||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
|
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
internal class DirectBridgesCallsLowering(val context: Context) : BodyLoweringPass {
|
|
||||||
override fun lower(irBody: IrBody) {
|
|
||||||
irBody.transformChildrenVoid(object : IrElementTransformerVoid() {
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
|
||||||
expression.transformChildrenVoid(this)
|
|
||||||
val descriptor = expression.descriptor as? FunctionDescriptor ?: return expression
|
|
||||||
if (descriptor.modality == Modality.ABSTRACT
|
|
||||||
|| (expression.superQualifier == null && descriptor.isOverridable)) {
|
|
||||||
// A virtual call. boxing/unboxing will be in the corresponding bridge.
|
|
||||||
return expression
|
|
||||||
}
|
|
||||||
|
|
||||||
val target = descriptor.target
|
|
||||||
if (!descriptor.original.needBridgeTo(target)) return expression
|
|
||||||
|
|
||||||
return IrCallImpl(expression.startOffset, expression.endOffset,
|
|
||||||
target, remapTypeArguments(expression, target), expression.origin,
|
|
||||||
superQualifierDescriptor = target.containingDeclaration as ClassDescriptor /* Call non-virtually */
|
|
||||||
).apply {
|
|
||||||
dispatchReceiver = expression.dispatchReceiver
|
|
||||||
extensionReceiver = expression.extensionReceiver
|
|
||||||
mapValueParameters { expression.getValueArgument(it)!! }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun remapTypeArguments(oldExpression: IrMemberAccessExpression, newCallee: CallableDescriptor)
|
|
||||||
: Map<TypeParameterDescriptor, KotlinType>? {
|
|
||||||
val oldCallee = oldExpression.descriptor
|
|
||||||
|
|
||||||
return if (oldCallee.typeParameters.isEmpty())
|
|
||||||
null
|
|
||||||
else oldCallee.typeParameters.associateBy(
|
|
||||||
{ newCallee.typeParameters[it.index] },
|
|
||||||
{ oldExpression.getTypeArgument(it)!! }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
|
internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
|
||||||
|
|
||||||
private fun IrBuilderWithScope.returnIfBadType(value: IrExpression,
|
private fun IrBuilderWithScope.returnIfBadType(value: IrExpression,
|
||||||
@@ -162,30 +121,31 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
|
|||||||
private object DECLARATION_ORIGIN_BRIDGE_METHOD :
|
private object DECLARATION_ORIGIN_BRIDGE_METHOD :
|
||||||
IrDeclarationOriginImpl("BRIDGE_METHOD")
|
IrDeclarationOriginImpl("BRIDGE_METHOD")
|
||||||
|
|
||||||
private val ValueType.shortName
|
|
||||||
get() = this.classFqName.shortName()
|
|
||||||
|
|
||||||
private fun getBoxType(valueType: ValueType) =
|
|
||||||
context.builtIns.getKonanInternalClass("${valueType.shortName}Box").defaultType
|
|
||||||
|
|
||||||
private fun buildBridge(descriptor: OverriddenFunctionDescriptor, irClass: IrClass) {
|
private fun buildBridge(descriptor: OverriddenFunctionDescriptor, irClass: IrClass) {
|
||||||
val bridgeDescriptor = context.specialDeclarationsFactory.getBridgeDescriptor(descriptor)
|
val bridgeDescriptor = context.specialDeclarationsFactory.getBridgeDescriptor(descriptor)
|
||||||
val target = descriptor.descriptor.target
|
val bridge = IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, DECLARATION_ORIGIN_BRIDGE_METHOD,
|
||||||
|
bridgeDescriptor).apply { createParameterDeclarations() }
|
||||||
|
|
||||||
|
val target = descriptor.descriptor
|
||||||
|
|
||||||
|
assert(target.containingDeclaration == irClass.descriptor)
|
||||||
|
val superQualifierSymbol = irClass.symbol
|
||||||
|
val targetSymbol = irClass.findMember(target) // TODO: optimize
|
||||||
|
|
||||||
val statements = mutableListOf<IrExpression>()
|
val statements = mutableListOf<IrExpression>()
|
||||||
val irBuilder = context.createIrBuilder(bridgeDescriptor, irClass.startOffset, irClass.endOffset)
|
val irBuilder = context.createIrBuilder(bridge.symbol, irClass.startOffset, irClass.endOffset)
|
||||||
irBuilder.run {
|
irBuilder.run {
|
||||||
val typeSafeBarrierDescription = BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor.overriddenDescriptor)
|
val typeSafeBarrierDescription = BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor.overriddenDescriptor)
|
||||||
if (typeSafeBarrierDescription != null) {
|
if (typeSafeBarrierDescription != null) {
|
||||||
val valueParameters = bridgeDescriptor.valueParameters
|
val valueParameters = bridge.valueParameters
|
||||||
for (i in valueParameters.indices) {
|
for (i in valueParameters.indices) {
|
||||||
if (!typeSafeBarrierDescription.checkParameter(i))
|
if (!typeSafeBarrierDescription.checkParameter(i))
|
||||||
continue
|
continue
|
||||||
val type = target.valueParameters[i].type
|
val type = target.valueParameters[i].type
|
||||||
if (type != context.builtIns.nullableAnyType) {
|
if (type != context.builtIns.nullableAnyType) {
|
||||||
statements += returnIfBadType(irGet(valueParameters[i]), type,
|
statements += returnIfBadType(irGet(valueParameters[i].symbol), type,
|
||||||
if (typeSafeBarrierDescription == BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription.MAP_GET_OR_DEFAULT)
|
if (typeSafeBarrierDescription == BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription.MAP_GET_OR_DEFAULT)
|
||||||
irGet(valueParameters[2])
|
irGet(valueParameters[2].symbol)
|
||||||
else irConst(typeSafeBarrierDescription.defaultValue)
|
else irConst(typeSafeBarrierDescription.defaultValue)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -193,22 +153,22 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val delegatingCall = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, target,
|
val delegatingCall = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, targetSymbol, target,
|
||||||
superQualifierDescriptor = target.containingDeclaration as ClassDescriptor /* Call non-virtually */
|
superQualifierSymbol = superQualifierSymbol /* Call non-virtually */
|
||||||
).apply {
|
).apply {
|
||||||
val dispatchReceiverParameter = bridgeDescriptor.dispatchReceiverParameter
|
val dispatchReceiverParameter = bridge.dispatchReceiverParameter
|
||||||
if (dispatchReceiverParameter != null)
|
if (dispatchReceiverParameter != null)
|
||||||
dispatchReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, dispatchReceiverParameter)
|
dispatchReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, dispatchReceiverParameter.symbol)
|
||||||
val extensionReceiverParameter = bridgeDescriptor.extensionReceiverParameter
|
val extensionReceiverParameter = bridge.extensionReceiverParameter
|
||||||
if (extensionReceiverParameter != null)
|
if (extensionReceiverParameter != null)
|
||||||
extensionReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, extensionReceiverParameter)
|
extensionReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, extensionReceiverParameter.symbol)
|
||||||
bridgeDescriptor.valueParameters.forEach {
|
bridge.valueParameters.forEachIndexed { index, parameter ->
|
||||||
this.putValueArgument(it.index, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it))
|
this.putValueArgument(index, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, parameter.symbol))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val bridgeBody = if (bridgeDescriptor.returnType.let { it != null && !KotlinBuiltIns.isUnitOrNullableUnit(it) })
|
val bridgeBody = if (bridgeDescriptor.returnType.let { it != null && !KotlinBuiltIns.isUnitOrNullableUnit(it) })
|
||||||
IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, bridgeDescriptor, delegatingCall)
|
IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, bridge.symbol, delegatingCall)
|
||||||
else
|
else
|
||||||
delegatingCall
|
delegatingCall
|
||||||
statements += bridgeBody
|
statements += bridgeBody
|
||||||
@@ -219,3 +179,12 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun IrClass.findMember(descriptor: FunctionDescriptor): IrFunctionSymbol {
|
||||||
|
val functions = this.declarations.filterIsInstance<IrFunction>().map { it.symbol }
|
||||||
|
val propertyAccessors = this.declarations
|
||||||
|
.filterIsInstance<IrProperty>()
|
||||||
|
.flatMap { listOfNotNull(it.getter?.symbol, it.setter?.symbol) }
|
||||||
|
|
||||||
|
return (functions + propertyAccessors).single { it.descriptor == descriptor }
|
||||||
|
}
|
||||||
|
|||||||
+12
-12
@@ -20,8 +20,6 @@ import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
|
|||||||
import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters
|
import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters
|
||||||
import org.jetbrains.kotlin.backend.common.lower.*
|
import org.jetbrains.kotlin.backend.common.lower.*
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalClass
|
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalFunctions
|
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.isFunctionOrKFunctionType
|
import org.jetbrains.kotlin.backend.konan.descriptors.isFunctionOrKFunctionType
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.createFakeOverrideDescriptor
|
import org.jetbrains.kotlin.backend.konan.ir.createFakeOverrideDescriptor
|
||||||
@@ -45,8 +43,6 @@ import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
|||||||
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
|
||||||
import org.jetbrains.kotlin.ir.util.getArguments
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
@@ -54,9 +50,9 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
|||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.*
|
import org.jetbrains.kotlin.backend.common.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
|
|
||||||
internal class CallableReferenceLowering(val context: Context): DeclarationContainerLoweringPass {
|
internal class CallableReferenceLowering(val context: Context): DeclarationContainerLoweringPass {
|
||||||
@@ -122,7 +118,7 @@ internal class CallableReferenceLowering(val context: Context): DeclarationConta
|
|||||||
private val continuationClassDescriptor = coroutinesScope
|
private val continuationClassDescriptor = coroutinesScope
|
||||||
.getContributedClassifier(Name.identifier("Continuation"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor
|
.getContributedClassifier(Name.identifier("Continuation"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor
|
||||||
|
|
||||||
private val getContinuationDescriptor = context.builtIns.getKonanInternalFunctions("getContinuation").single()
|
private val getContinuationSymbol = context.ir.symbols.getContinuation
|
||||||
|
|
||||||
private inner class FunctionReferenceBuilder(val containingDeclaration: DeclarationDescriptor,
|
private inner class FunctionReferenceBuilder(val containingDeclaration: DeclarationDescriptor,
|
||||||
val functionReference: IrFunctionReference) {
|
val functionReference: IrFunctionReference) {
|
||||||
@@ -137,7 +133,7 @@ internal class CallableReferenceLowering(val context: Context): DeclarationConta
|
|||||||
private lateinit var functionReferenceThis: IrValueParameterSymbol
|
private lateinit var functionReferenceThis: IrValueParameterSymbol
|
||||||
private lateinit var argumentToPropertiesMap: Map<ParameterDescriptor, IrFieldSymbol>
|
private lateinit var argumentToPropertiesMap: Map<ParameterDescriptor, IrFieldSymbol>
|
||||||
|
|
||||||
private val kFunctionImplClassDescriptor = context.builtIns.getKonanInternalClass("KFunctionImpl")
|
private val kFunctionImplSymbol = context.ir.symbols.kFunctionImpl
|
||||||
|
|
||||||
fun build(): BuiltFunctionReference {
|
fun build(): BuiltFunctionReference {
|
||||||
val startOffset = functionReference.startOffset
|
val startOffset = functionReference.startOffset
|
||||||
@@ -145,7 +141,7 @@ internal class CallableReferenceLowering(val context: Context): DeclarationConta
|
|||||||
|
|
||||||
val returnType = functionDescriptor.returnType!!
|
val returnType = functionDescriptor.returnType!!
|
||||||
val superTypes = mutableListOf(
|
val superTypes = mutableListOf(
|
||||||
kFunctionImplClassDescriptor.defaultType.replace(listOf(returnType))
|
kFunctionImplSymbol.owner.defaultType.replace(listOf(returnType))
|
||||||
)
|
)
|
||||||
|
|
||||||
val numberOfParameters = unboundFunctionParameters.size
|
val numberOfParameters = unboundFunctionParameters.size
|
||||||
@@ -196,7 +192,7 @@ internal class CallableReferenceLowering(val context: Context): DeclarationConta
|
|||||||
suspendInvokeMethodBuilder = createInvokeMethodBuilder(suspendInvokeFunctionDescriptor)
|
suspendInvokeMethodBuilder = createInvokeMethodBuilder(suspendInvokeFunctionDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
val inheritedKFunctionImpl = kFunctionImplClassDescriptor.unsubstitutedMemberScope
|
val inheritedKFunctionImpl = kFunctionImplSymbol.descriptor.unsubstitutedMemberScope
|
||||||
.getContributedDescriptors()
|
.getContributedDescriptors()
|
||||||
.map { it.createFakeOverrideDescriptor(functionReferenceClassDescriptor) }
|
.map { it.createFakeOverrideDescriptor(functionReferenceClassDescriptor) }
|
||||||
.filterNotNull()
|
.filterNotNull()
|
||||||
@@ -206,6 +202,8 @@ internal class CallableReferenceLowering(val context: Context): DeclarationConta
|
|||||||
functionReferenceClassDescriptor.initialize(
|
functionReferenceClassDescriptor.initialize(
|
||||||
SimpleMemberScope(contributedDescriptors), setOf(constructorBuilder.symbol.descriptor), null)
|
SimpleMemberScope(contributedDescriptors), setOf(constructorBuilder.symbol.descriptor), null)
|
||||||
|
|
||||||
|
functionReferenceClass.addFakeOverrides()
|
||||||
|
|
||||||
constructorBuilder.initialize()
|
constructorBuilder.initialize()
|
||||||
functionReferenceClass.declarations.add(constructorBuilder.ir)
|
functionReferenceClass.declarations.add(constructorBuilder.ir)
|
||||||
|
|
||||||
@@ -223,7 +221,7 @@ internal class CallableReferenceLowering(val context: Context): DeclarationConta
|
|||||||
private fun createConstructorBuilder()
|
private fun createConstructorBuilder()
|
||||||
= object : SymbolWithIrBuilder<IrConstructorSymbol, IrConstructor>() {
|
= object : SymbolWithIrBuilder<IrConstructorSymbol, IrConstructor>() {
|
||||||
|
|
||||||
private val kFunctionImplConstructorDescriptor = kFunctionImplClassDescriptor.constructors.single()
|
private val kFunctionImplConstructorSymbol = kFunctionImplSymbol.constructors.single()
|
||||||
|
|
||||||
override fun buildSymbol() = IrConstructorSymbolImpl(
|
override fun buildSymbol() = IrConstructorSymbolImpl(
|
||||||
ClassConstructorDescriptorImpl.create(
|
ClassConstructorDescriptorImpl.create(
|
||||||
@@ -261,7 +259,8 @@ internal class CallableReferenceLowering(val context: Context): DeclarationConta
|
|||||||
createParameterDeclarations()
|
createParameterDeclarations()
|
||||||
|
|
||||||
body = irBuilder.irBlockBody {
|
body = irBuilder.irBlockBody {
|
||||||
+IrDelegatingConstructorCallImpl(startOffset, endOffset, kFunctionImplConstructorDescriptor).apply {
|
+IrDelegatingConstructorCallImpl(startOffset, endOffset,
|
||||||
|
kFunctionImplConstructorSymbol, kFunctionImplConstructorSymbol.descriptor).apply {
|
||||||
val name = IrConstImpl(startOffset, endOffset, context.builtIns.stringType,
|
val name = IrConstImpl(startOffset, endOffset, context.builtIns.stringType,
|
||||||
IrConstKind.String, functionDescriptor.name.asString())
|
IrConstKind.String, functionDescriptor.name.asString())
|
||||||
putValueArgument(0, name)
|
putValueArgument(0, name)
|
||||||
@@ -356,7 +355,8 @@ internal class CallableReferenceLowering(val context: Context): DeclarationConta
|
|||||||
else {
|
else {
|
||||||
if (ourSymbol.descriptor.isSuspend && unboundIndex == valueParameters.size)
|
if (ourSymbol.descriptor.isSuspend && unboundIndex == valueParameters.size)
|
||||||
// For suspend functions the last argument is continuation and it is implicit.
|
// For suspend functions the last argument is continuation and it is implicit.
|
||||||
irCall(getContinuationDescriptor.substitute(ourSymbol.descriptor.returnType!!))
|
irCall(getContinuationSymbol,
|
||||||
|
listOf(ourSymbol.descriptor.returnType!!))
|
||||||
else
|
else
|
||||||
irGet(valueParameters[unboundIndex++].symbol)
|
irGet(valueParameters[unboundIndex++].symbol)
|
||||||
}
|
}
|
||||||
|
|||||||
+84
-66
@@ -21,8 +21,6 @@ import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
|
|||||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.common.lower.irBlockBody
|
import org.jetbrains.kotlin.backend.common.lower.irBlockBody
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.KonanBuiltIns
|
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.konanInternal
|
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.ir2string
|
import org.jetbrains.kotlin.backend.konan.ir.ir2string
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
@@ -32,7 +30,6 @@ import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
|
|||||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||||
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
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.IrElement
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
@@ -42,8 +39,9 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
|||||||
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
|
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
@@ -52,7 +50,6 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
|||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
|
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
|
||||||
|
|
||||||
class DefaultArgumentStubGenerator internal constructor(val context: Context): DeclarationContainerLoweringPass {
|
class DefaultArgumentStubGenerator internal constructor(val context: Context): DeclarationContainerLoweringPass {
|
||||||
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
|
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
|
||||||
@@ -65,8 +62,7 @@ class DefaultArgumentStubGenerator internal constructor(val context: Context): D
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER :
|
private val symbols = context.ir.symbols
|
||||||
IrDeclarationOriginImpl("DEFAULT_PARAMETER_EXTENT")
|
|
||||||
|
|
||||||
private fun lower(irFunction: IrFunction): List<IrFunction> {
|
private fun lower(irFunction: IrFunction): List<IrFunction> {
|
||||||
val functionDescriptor = irFunction.descriptor
|
val functionDescriptor = irFunction.descriptor
|
||||||
@@ -81,27 +77,28 @@ class DefaultArgumentStubGenerator internal constructor(val context: Context): D
|
|||||||
log("detected ${functionDescriptor.name.asString()} has got #${bodies.size} default expressions")
|
log("detected ${functionDescriptor.name.asString()} has got #${bodies.size} default expressions")
|
||||||
functionDescriptor.overriddenDescriptors.forEach { context.log{"DEFAULT-REPLACER: $it"} }
|
functionDescriptor.overriddenDescriptors.forEach { context.log{"DEFAULT-REPLACER: $it"} }
|
||||||
if (bodies.isNotEmpty()) {
|
if (bodies.isNotEmpty()) {
|
||||||
val descriptor = functionDescriptor.generateDefaultsDescription(context)
|
val newIrFunction = functionDescriptor.generateDefaultsFunction(context)
|
||||||
|
val descriptor = newIrFunction.descriptor
|
||||||
log("$functionDescriptor -> $descriptor")
|
log("$functionDescriptor -> $descriptor")
|
||||||
val builder = context.createIrBuilder(descriptor)
|
val builder = context.createIrBuilder(newIrFunction.symbol)
|
||||||
val body = builder.irBlockBody(irFunction) {
|
val body = builder.irBlockBody(irFunction) {
|
||||||
val params = mutableListOf<VariableDescriptor>()
|
val params = mutableListOf<IrVariableSymbol>()
|
||||||
val variables = mutableMapOf<ValueDescriptor, ValueDescriptor>()
|
val variables = mutableMapOf<ValueDescriptor, IrValueSymbol>()
|
||||||
if (descriptor.extensionReceiverParameter != null) {
|
if (descriptor.extensionReceiverParameter != null) {
|
||||||
variables[functionDescriptor.extensionReceiverParameter!!] = descriptor.extensionReceiverParameter!!
|
variables[functionDescriptor.extensionReceiverParameter!!] =
|
||||||
|
newIrFunction.extensionReceiverParameter!!.symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
for (valueParameter in functionDescriptor.valueParameters) {
|
for (valueParameter in functionDescriptor.valueParameters) {
|
||||||
val parameterDescriptor = descriptor.valueParameters[valueParameter.index]
|
val parameterSymbol = newIrFunction.valueParameters[valueParameter.index].symbol
|
||||||
val temporaryVariableDescriptor = scope.createTemporaryVariableDescriptor(parameterDescriptor)
|
val temporaryVariableSymbol =
|
||||||
params.add(temporaryVariableDescriptor)
|
IrVariableSymbolImpl(scope.createTemporaryVariableDescriptor(parameterSymbol.descriptor))
|
||||||
variables.put(valueParameter, temporaryVariableDescriptor)
|
params.add(temporaryVariableSymbol)
|
||||||
|
variables.put(valueParameter, temporaryVariableSymbol)
|
||||||
if (valueParameter.hasDefaultValue()) {
|
if (valueParameter.hasDefaultValue()) {
|
||||||
val kIntAnd = valueParameter.builtIns.intType.memberScope
|
val kIntAnd = symbols.intAnd
|
||||||
.getContributedFunctions(OperatorNameConventions.AND, NoLookupLocation.FROM_BACKEND)
|
|
||||||
.single()
|
|
||||||
val condition = irNotEquals(irCall(kIntAnd).apply {
|
val condition = irNotEquals(irCall(kIntAnd).apply {
|
||||||
dispatchReceiver = irGet(maskParameterDescriptor(descriptor, valueParameter.index / 32))
|
dispatchReceiver = irGet(maskParameterSymbol(newIrFunction, valueParameter.index / 32))
|
||||||
putValueArgument(0, irInt(1 shl (valueParameter.index % 32)))
|
putValueArgument(0, irInt(1 shl (valueParameter.index % 32)))
|
||||||
}, irInt(0))
|
}, irInt(0))
|
||||||
val expressionBody = getDefaultParameterExpressionBody(irFunction, valueParameter)
|
val expressionBody = getDefaultParameterExpressionBody(irFunction, valueParameter)
|
||||||
@@ -110,51 +107,45 @@ class DefaultArgumentStubGenerator internal constructor(val context: Context): D
|
|||||||
expressionBody.transformChildrenVoid(object:IrElementTransformerVoid() {
|
expressionBody.transformChildrenVoid(object:IrElementTransformerVoid() {
|
||||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||||
log("GetValue: ${expression.descriptor}")
|
log("GetValue: ${expression.descriptor}")
|
||||||
val valueDescriptor = variables[expression.descriptor]
|
val valueSymbol = variables[expression.descriptor] ?: return expression
|
||||||
return when (valueDescriptor) {
|
return irGet(valueSymbol)
|
||||||
is VariableDescriptor -> irGet(valueDescriptor)
|
|
||||||
is ReceiverParameterDescriptor -> irGet(valueDescriptor)
|
|
||||||
null -> expression
|
|
||||||
else -> TODO("$valueDescriptor")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
val variableInitialization = irIfThenElse(
|
val variableInitialization = irIfThenElse(
|
||||||
type = temporaryVariableDescriptor.type,
|
type = temporaryVariableSymbol.descriptor.type,
|
||||||
condition = condition,
|
condition = condition,
|
||||||
thenPart = expressionBody.expression,
|
thenPart = expressionBody.expression,
|
||||||
elsePart = irGet(parameterDescriptor))
|
elsePart = irGet(parameterSymbol))
|
||||||
+ scope.createTemporaryVariable(
|
+ scope.createTemporaryVariable(
|
||||||
descriptor = temporaryVariableDescriptor,
|
symbol = temporaryVariableSymbol,
|
||||||
initializer = variableInitialization)
|
initializer = variableInitialization)
|
||||||
/* Mapping calculated values with its origin variables. */
|
/* Mapping calculated values with its origin variables. */
|
||||||
} else {
|
} else {
|
||||||
+ scope.createTemporaryVariable(
|
+ scope.createTemporaryVariable(
|
||||||
descriptor = temporaryVariableDescriptor,
|
symbol = temporaryVariableSymbol,
|
||||||
initializer = irGet(parameterDescriptor))
|
initializer = irGet(parameterSymbol))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (functionDescriptor is ClassConstructorDescriptor) {
|
if (irFunction is IrConstructor) {
|
||||||
+ IrDelegatingConstructorCallImpl(
|
+ IrDelegatingConstructorCallImpl(
|
||||||
startOffset = irFunction.startOffset,
|
startOffset = irFunction.startOffset,
|
||||||
endOffset = irFunction.endOffset,
|
endOffset = irFunction.endOffset,
|
||||||
constructorDescriptor = functionDescriptor
|
symbol = irFunction.symbol, descriptor = irFunction.symbol.descriptor
|
||||||
).apply {
|
).apply {
|
||||||
params.forEachIndexed { i, variable ->
|
params.forEachIndexed { i, variable ->
|
||||||
putValueArgument(i, irGet(variable))
|
putValueArgument(i, irGet(variable))
|
||||||
}
|
}
|
||||||
if (functionDescriptor.dispatchReceiverParameter != null) {
|
if (functionDescriptor.dispatchReceiverParameter != null) {
|
||||||
dispatchReceiver = irThis()
|
dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!.symbol)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
+irReturn(irCall(functionDescriptor).apply {
|
+irReturn(irCall(irFunction.symbol).apply {
|
||||||
if (functionDescriptor.dispatchReceiverParameter != null) {
|
if (functionDescriptor.dispatchReceiverParameter != null) {
|
||||||
dispatchReceiver = irThis()
|
dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!.symbol)
|
||||||
}
|
}
|
||||||
if (functionDescriptor.extensionReceiverParameter != null) {
|
if (functionDescriptor.extensionReceiverParameter != null) {
|
||||||
extensionReceiver = irGet(variables[functionDescriptor.extensionReceiverParameter!!] as ReceiverParameterDescriptor)
|
extensionReceiver = irGet(variables[functionDescriptor.extensionReceiverParameter!!]!!)
|
||||||
}
|
}
|
||||||
params.forEachIndexed { i, variable ->
|
params.forEachIndexed { i, variable ->
|
||||||
putValueArgument(i, irGet(variable))
|
putValueArgument(i, irGet(variable))
|
||||||
@@ -188,26 +179,31 @@ class DefaultArgumentStubGenerator internal constructor(val context: Context): D
|
|||||||
private fun log(msg:String) = context.log{"DEFAULT-REPLACER: $msg"}
|
private fun log(msg:String) = context.log{"DEFAULT-REPLACER: $msg"}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Scope.createTemporaryVariableDescriptor(parameterDescriptor: ValueParameterDescriptor?): VariableDescriptor =
|
private fun Scope.createTemporaryVariableDescriptor(parameterDescriptor: ParameterDescriptor?): VariableDescriptor =
|
||||||
IrTemporaryVariableDescriptorImpl(
|
IrTemporaryVariableDescriptorImpl(
|
||||||
containingDeclaration = this.scopeOwner,
|
containingDeclaration = this.scopeOwner,
|
||||||
name = parameterDescriptor!!.name.asString().synthesizedName,
|
name = parameterDescriptor!!.name.asString().synthesizedName,
|
||||||
outType = parameterDescriptor.type,
|
outType = parameterDescriptor.type,
|
||||||
isMutable = false)
|
isMutable = false)
|
||||||
|
|
||||||
private fun Scope.createTemporaryVariable(descriptor: VariableDescriptor, initializer: IrExpression) =
|
private fun Scope.createTemporaryVariable(symbol: IrVariableSymbol, initializer: IrExpression) =
|
||||||
IrVariableImpl(
|
IrVariableImpl(
|
||||||
startOffset = initializer.startOffset,
|
startOffset = initializer.startOffset,
|
||||||
endOffset = initializer.endOffset,
|
endOffset = initializer.endOffset,
|
||||||
origin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
|
origin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
|
||||||
descriptor = descriptor,
|
symbol = symbol).apply {
|
||||||
initializer = initializer)
|
|
||||||
|
this.initializer = initializer
|
||||||
|
}
|
||||||
|
|
||||||
private fun getDefaultParameterExpressionBody(irFunction: IrFunction, valueParameter: ValueParameterDescriptor):IrExpressionBody {
|
private fun getDefaultParameterExpressionBody(irFunction: IrFunction, valueParameter: ValueParameterDescriptor):IrExpressionBody {
|
||||||
return irFunction.getDefault(valueParameter) as? IrExpressionBody ?: TODO("FIXME!!!")
|
return irFunction.getDefault(valueParameter) as? IrExpressionBody ?: TODO("FIXME!!!")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun maskParameterDescriptor(descriptor: FunctionDescriptor, number:Int)= descriptor.valueParameters.single { it.name == parameterMaskName(number) }
|
private fun maskParameterDescriptor(function: IrFunction, number: Int) =
|
||||||
|
maskParameterSymbol(function, number).descriptor as ValueParameterDescriptor
|
||||||
|
private fun maskParameterSymbol(function: IrFunction, number: Int) =
|
||||||
|
function.valueParameters.single { it.descriptor.name == parameterMaskName(number) }.symbol
|
||||||
|
|
||||||
private fun markerParameterDescriptor(descriptor: FunctionDescriptor) = descriptor.valueParameters.single { it.name == kConstructorMarkerName }
|
private fun markerParameterDescriptor(descriptor: FunctionDescriptor) = descriptor.valueParameters.single { it.name == kConstructorMarkerName }
|
||||||
|
|
||||||
@@ -237,11 +233,12 @@ class DefaultParameterInjector internal constructor(val context: Context): BodyL
|
|||||||
val argumentsCount = argumentCount(expression)
|
val argumentsCount = argumentCount(expression)
|
||||||
if (argumentsCount == descriptor.valueParameters.size)
|
if (argumentsCount == descriptor.valueParameters.size)
|
||||||
return expression
|
return expression
|
||||||
val (descriptorForCall, params) = parametersForCall(expression)
|
val (symbolForCall, params) = parametersForCall(expression)
|
||||||
return IrDelegatingConstructorCallImpl(
|
return IrDelegatingConstructorCallImpl(
|
||||||
startOffset = expression.startOffset,
|
startOffset = expression.startOffset,
|
||||||
endOffset = expression.endOffset,
|
endOffset = expression.endOffset,
|
||||||
constructorDescriptor = descriptorForCall as ClassConstructorDescriptor)
|
symbol = symbolForCall as IrConstructorSymbol,
|
||||||
|
descriptor = symbolForCall.descriptor)
|
||||||
.apply {
|
.apply {
|
||||||
params.forEach {
|
params.forEach {
|
||||||
log("call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}")
|
log("call::params@${it.first.index}/${it.first.name.asString()}: ${ir2string(it.second)}")
|
||||||
@@ -254,7 +251,7 @@ class DefaultParameterInjector internal constructor(val context: Context): BodyL
|
|||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
super.visitCall(expression)
|
super.visitCall(expression)
|
||||||
val functionDescriptor = expression.descriptor as FunctionDescriptor
|
val functionDescriptor = expression.descriptor
|
||||||
|
|
||||||
if (!functionDescriptor.needsDefaultArgumentsLowering)
|
if (!functionDescriptor.needsDefaultArgumentsLowering)
|
||||||
return expression
|
return expression
|
||||||
@@ -262,13 +259,15 @@ class DefaultParameterInjector internal constructor(val context: Context): BodyL
|
|||||||
val argumentsCount = argumentCount(expression)
|
val argumentsCount = argumentCount(expression)
|
||||||
if (argumentsCount == functionDescriptor.valueParameters.size)
|
if (argumentsCount == functionDescriptor.valueParameters.size)
|
||||||
return expression
|
return expression
|
||||||
val (descriptor, params) = parametersForCall(expression)
|
val (symbol, params) = parametersForCall(expression)
|
||||||
|
val descriptor = symbol.descriptor
|
||||||
descriptor.typeParameters.forEach { log("$descriptor [${it.index}]: $it") }
|
descriptor.typeParameters.forEach { log("$descriptor [${it.index}]: $it") }
|
||||||
descriptor.original.typeParameters.forEach { log("${descriptor.original}[${it.index}] : $it") }
|
descriptor.original.typeParameters.forEach { log("${descriptor.original}[${it.index}] : $it") }
|
||||||
return IrCallImpl(
|
return IrCallImpl(
|
||||||
startOffset = expression.startOffset,
|
startOffset = expression.startOffset,
|
||||||
endOffset = expression.endOffset,
|
endOffset = expression.endOffset,
|
||||||
calleeDescriptor = descriptor,
|
symbol = symbol,
|
||||||
|
descriptor = descriptor,
|
||||||
typeArguments = expression.descriptor.typeParameters.map{it to (expression.getTypeArgument(it) ?: it.defaultType) }.toMap())
|
typeArguments = expression.descriptor.typeParameters.map{it to (expression.getTypeArgument(it) ?: it.defaultType) }.toMap())
|
||||||
.apply {
|
.apply {
|
||||||
params.forEach {
|
params.forEach {
|
||||||
@@ -286,13 +285,14 @@ class DefaultParameterInjector internal constructor(val context: Context): BodyL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parametersForCall(expression: IrMemberAccessExpression): Pair<FunctionDescriptor, List<Pair<ValueParameterDescriptor, IrExpression?>>> {
|
private fun parametersForCall(expression: IrMemberAccessExpression): Pair<IrFunctionSymbol, List<Pair<ValueParameterDescriptor, IrExpression?>>> {
|
||||||
val descriptor = expression.descriptor as FunctionDescriptor
|
val descriptor = expression.descriptor as FunctionDescriptor
|
||||||
val keyDescriptor = if (DescriptorUtils.isOverride(descriptor))
|
val keyDescriptor = if (DescriptorUtils.isOverride(descriptor))
|
||||||
DescriptorUtils.getAllOverriddenDescriptors(descriptor).first()
|
DescriptorUtils.getAllOverriddenDescriptors(descriptor).first()
|
||||||
else
|
else
|
||||||
descriptor.original
|
descriptor.original
|
||||||
val realDescriptor = keyDescriptor.generateDefaultsDescription(context)
|
val realFunction = keyDescriptor.generateDefaultsFunction(context)
|
||||||
|
val realDescriptor = realFunction.descriptor
|
||||||
|
|
||||||
log("$descriptor -> $realDescriptor")
|
log("$descriptor -> $realDescriptor")
|
||||||
val maskValues = Array(descriptor.valueParameters.size / 32 + 1, {0})
|
val maskValues = Array(descriptor.valueParameters.size / 32 + 1, {0})
|
||||||
@@ -308,24 +308,24 @@ class DefaultParameterInjector internal constructor(val context: Context): BodyL
|
|||||||
return@mapIndexed pair
|
return@mapIndexed pair
|
||||||
})
|
})
|
||||||
maskValues.forEachIndexed { i, maskValue ->
|
maskValues.forEachIndexed { i, maskValue ->
|
||||||
params += maskParameterDescriptor(realDescriptor, i) to IrConstImpl.int(
|
params += maskParameterDescriptor(realFunction, i) to IrConstImpl.int(
|
||||||
startOffset = irBody.startOffset,
|
startOffset = irBody.startOffset,
|
||||||
endOffset = irBody.endOffset,
|
endOffset = irBody.endOffset,
|
||||||
type = descriptor.builtIns.intType,
|
type = descriptor.builtIns.intType,
|
||||||
value = maskValue)
|
value = maskValue)
|
||||||
}
|
}
|
||||||
if (expression.descriptor is ClassConstructorDescriptor) {
|
if (expression.descriptor is ClassConstructorDescriptor) {
|
||||||
val defaultArgumentMarker = getDefaultArgumentMarkerClassDescriptor(context.builtIns)
|
val defaultArgumentMarker = context.ir.symbols.defaultArgumentMarker
|
||||||
params += markerParameterDescriptor(realDescriptor) to IrGetObjectValueImpl(
|
params += markerParameterDescriptor(realDescriptor) to IrGetObjectValueImpl(
|
||||||
startOffset = irBody.startOffset,
|
startOffset = irBody.startOffset,
|
||||||
endOffset = irBody.endOffset,
|
endOffset = irBody.endOffset,
|
||||||
type = defaultArgumentMarker.defaultType,
|
type = defaultArgumentMarker.owner.defaultType,
|
||||||
descriptor = defaultArgumentMarker)
|
symbol = defaultArgumentMarker)
|
||||||
}
|
}
|
||||||
params.forEach {
|
params.forEach {
|
||||||
log("descriptor::${realDescriptor.name.asString()}#${it.first.index}: ${it.first.name.asString()}")
|
log("descriptor::${realDescriptor.name.asString()}#${it.first.index}: ${it.first.name.asString()}")
|
||||||
}
|
}
|
||||||
return Pair(realDescriptor, params)
|
return Pair(realFunction.symbol, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun argumentCount(expression: IrMemberAccessExpression) =
|
private fun argumentCount(expression: IrMemberAccessExpression) =
|
||||||
@@ -339,8 +339,8 @@ class DefaultParameterInjector internal constructor(val context: Context): BodyL
|
|||||||
private val CallableMemberDescriptor.needsDefaultArgumentsLowering
|
private val CallableMemberDescriptor.needsDefaultArgumentsLowering
|
||||||
get() = valueParameters.any { it.hasDefaultValue() } && !(this is FunctionDescriptor && isInline)
|
get() = valueParameters.any { it.hasDefaultValue() } && !(this is FunctionDescriptor && isInline)
|
||||||
|
|
||||||
private fun FunctionDescriptor.generateDefaultsDescription(context: Context): FunctionDescriptor {
|
private fun FunctionDescriptor.generateDefaultsFunction(context: Context): IrFunction {
|
||||||
return context.ir.defaultParameterDescriptorsCache.getOrPut(this) {
|
return context.ir.defaultParameterDeclarationsCache.getOrPut(this) {
|
||||||
val descriptor = when (this) {
|
val descriptor = when (this) {
|
||||||
is ClassConstructorDescriptor ->
|
is ClassConstructorDescriptor ->
|
||||||
ClassConstructorDescriptorImpl.create(
|
ClassConstructorDescriptorImpl.create(
|
||||||
@@ -367,7 +367,7 @@ private fun FunctionDescriptor.generateDefaultsDescription(context: Context): Fu
|
|||||||
if (this is ClassConstructorDescriptor) {
|
if (this is ClassConstructorDescriptor) {
|
||||||
syntheticParameters += valueParameter(descriptor, syntheticParameters.last().index + 1,
|
syntheticParameters += valueParameter(descriptor, syntheticParameters.last().index + 1,
|
||||||
kConstructorMarkerName,
|
kConstructorMarkerName,
|
||||||
getDefaultArgumentMarkerClassDescriptor(context.builtIns).defaultType)
|
context.ir.symbols.defaultArgumentMarker.owner.defaultType)
|
||||||
}
|
}
|
||||||
descriptor.initialize(
|
descriptor.initialize(
|
||||||
/* receiverParameterType = */ extensionReceiverParameter?.type,
|
/* receiverParameterType = */ extensionReceiverParameter?.type,
|
||||||
@@ -407,10 +407,33 @@ private fun FunctionDescriptor.generateDefaultsDescription(context: Context): Fu
|
|||||||
/* visibility = */ this.visibility)
|
/* visibility = */ this.visibility)
|
||||||
descriptor.isSuspend = this.isSuspend
|
descriptor.isSuspend = this.isSuspend
|
||||||
context.log{"adds to cache[$this] = $descriptor"}
|
context.log{"adds to cache[$this] = $descriptor"}
|
||||||
descriptor
|
|
||||||
|
val startOffset = this.startOffsetOrUndefined
|
||||||
|
val endOffset = this.endOffsetOrUndefined
|
||||||
|
|
||||||
|
val result: IrFunction = when (descriptor) {
|
||||||
|
is ClassConstructorDescriptor -> IrConstructorImpl(
|
||||||
|
startOffset, endOffset,
|
||||||
|
DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER,
|
||||||
|
descriptor
|
||||||
|
)
|
||||||
|
|
||||||
|
else -> IrFunctionImpl(
|
||||||
|
startOffset, endOffset,
|
||||||
|
DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER,
|
||||||
|
descriptor
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
result.createParameterDeclarations()
|
||||||
|
|
||||||
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER :
|
||||||
|
IrDeclarationOriginImpl("DEFAULT_PARAMETER_EXTENT")
|
||||||
|
|
||||||
private fun valueParameter(descriptor: FunctionDescriptor, index: Int, name: Name, type: KotlinType):ValueParameterDescriptor {
|
private fun valueParameter(descriptor: FunctionDescriptor, index: Int, name: Name, type: KotlinType):ValueParameterDescriptor {
|
||||||
return ValueParameterDescriptorImpl(
|
return ValueParameterDescriptorImpl(
|
||||||
containingDeclaration = descriptor,
|
containingDeclaration = descriptor,
|
||||||
@@ -429,9 +452,4 @@ private fun valueParameter(descriptor: FunctionDescriptor, index: Int, name: Nam
|
|||||||
|
|
||||||
internal val kConstructorMarkerName = "marker".synthesizedName
|
internal val kConstructorMarkerName = "marker".synthesizedName
|
||||||
|
|
||||||
private fun getDefaultArgumentMarkerClassDescriptor(builtIns: KonanBuiltIns): ClassDescriptor =
|
|
||||||
builtIns.konanInternal.getContributedClassifier(
|
|
||||||
Name.identifier("DefaultArgumentMarker"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor
|
|
||||||
|
|
||||||
internal fun IrBuilderWithScope.irGet(descriptor: ReceiverParameterDescriptor):IrGetValue = IrGetValueImpl(startOffset, endOffset, descriptor)
|
|
||||||
private fun parameterMaskName(number: Int) = "mask$number".synthesizedName
|
private fun parameterMaskName(number: Int) = "mask$number".synthesizedName
|
||||||
|
|||||||
+2
@@ -282,6 +282,8 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
|||||||
.toList()
|
.toList()
|
||||||
defaultClassDescriptor.initialize(SimpleMemberScope(contributedDescriptors), constructors, null)
|
defaultClassDescriptor.initialize(SimpleMemberScope(contributedDescriptors), constructors, null)
|
||||||
|
|
||||||
|
defaultClass.addFakeOverrides()
|
||||||
|
|
||||||
return defaultClass
|
return defaultClass
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+33
-36
@@ -1,24 +1,25 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan.lower
|
package org.jetbrains.kotlin.backend.konan.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.DeepCopyIrTreeWithDeclarations
|
|
||||||
import org.jetbrains.kotlin.backend.common.FunctionLoweringPass
|
import org.jetbrains.kotlin.backend.common.FunctionLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.lower.*
|
import org.jetbrains.kotlin.backend.common.lower.*
|
||||||
import org.jetbrains.kotlin.backend.common.*
|
import org.jetbrains.kotlin.backend.common.*
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlockImpl
|
import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlockImpl
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlockSymbol
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlockSymbolImpl
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||||
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
|
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
@@ -32,9 +33,9 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass
|
|||||||
fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression): IrExpression
|
fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression): IrExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class Return(val functionDescriptor: FunctionDescriptor): HighLevelJump {
|
private data class Return(val target: IrFunctionSymbol): HighLevelJump {
|
||||||
override fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression)
|
override fun toIr(context: Context, startOffset: Int, endOffset: Int, value: IrExpression)
|
||||||
= IrReturnImpl(startOffset, endOffset, functionDescriptor, value)
|
= IrReturnImpl(startOffset, endOffset, target, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class Break(val loop: IrLoop): HighLevelJump {
|
private data class Break(val loop: IrLoop): HighLevelJump {
|
||||||
@@ -64,7 +65,7 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass
|
|||||||
private class TryScope(var expression: IrExpression,
|
private class TryScope(var expression: IrExpression,
|
||||||
val finallyExpression: IrExpression,
|
val finallyExpression: IrExpression,
|
||||||
val irBuilder: IrBuilderWithScope): Scope() {
|
val irBuilder: IrBuilderWithScope): Scope() {
|
||||||
val jumps = mutableMapOf<HighLevelJump, FunctionDescriptor>()
|
val jumps = mutableMapOf<HighLevelJump, IrFunctionSymbol>()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val scopeStack = mutableListOf<Scope>()
|
private val scopeStack = mutableListOf<Scope>()
|
||||||
@@ -101,26 +102,26 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass
|
|||||||
override fun visitBreak(jump: IrBreak): IrExpression {
|
override fun visitBreak(jump: IrBreak): IrExpression {
|
||||||
val startOffset = jump.startOffset
|
val startOffset = jump.startOffset
|
||||||
val endOffset = jump.endOffset
|
val endOffset = jump.endOffset
|
||||||
val irBuilder = context.createIrBuilder(functionDescriptor, startOffset, endOffset)
|
val irBuilder = context.createIrBuilder(irFunction.symbol, startOffset, endOffset)
|
||||||
return performHighLevelJump(
|
return performHighLevelJump(
|
||||||
targetScopePredicate = { it is LoopScope && it.loop == jump.loop },
|
targetScopePredicate = { it is LoopScope && it.loop == jump.loop },
|
||||||
jump = Break(jump.loop),
|
jump = Break(jump.loop),
|
||||||
startOffset = startOffset,
|
startOffset = startOffset,
|
||||||
endOffset = endOffset,
|
endOffset = endOffset,
|
||||||
value = irBuilder.irUnit()
|
value = irBuilder.irGetObject(context.ir.symbols.unit)
|
||||||
) ?: jump
|
) ?: jump
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitContinue(jump: IrContinue): IrExpression {
|
override fun visitContinue(jump: IrContinue): IrExpression {
|
||||||
val startOffset = jump.startOffset
|
val startOffset = jump.startOffset
|
||||||
val endOffset = jump.endOffset
|
val endOffset = jump.endOffset
|
||||||
val irBuilder = context.createIrBuilder(functionDescriptor, startOffset, endOffset)
|
val irBuilder = context.createIrBuilder(irFunction.symbol, startOffset, endOffset)
|
||||||
return performHighLevelJump(
|
return performHighLevelJump(
|
||||||
targetScopePredicate = { it is LoopScope && it.loop == jump.loop },
|
targetScopePredicate = { it is LoopScope && it.loop == jump.loop },
|
||||||
jump = Continue(jump.loop),
|
jump = Continue(jump.loop),
|
||||||
startOffset = startOffset,
|
startOffset = startOffset,
|
||||||
endOffset = endOffset,
|
endOffset = endOffset,
|
||||||
value = irBuilder.irUnit()
|
value = irBuilder.irGetObject(context.ir.symbols.unit)
|
||||||
) ?: jump
|
) ?: jump
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,7 +130,7 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass
|
|||||||
|
|
||||||
return performHighLevelJump(
|
return performHighLevelJump(
|
||||||
targetScopePredicate = { it is ReturnableScope && it.descriptor == expression.returnTarget },
|
targetScopePredicate = { it is ReturnableScope && it.descriptor == expression.returnTarget },
|
||||||
jump = Return(expression.returnTarget),
|
jump = Return(expression.returnTargetSymbol),
|
||||||
startOffset = expression.startOffset,
|
startOffset = expression.startOffset,
|
||||||
endOffset = expression.endOffset,
|
endOffset = expression.endOffset,
|
||||||
value = expression.value
|
value = expression.value
|
||||||
@@ -161,10 +162,10 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass
|
|||||||
|
|
||||||
val currentTryScope = tryScopes[index]
|
val currentTryScope = tryScopes[index]
|
||||||
currentTryScope.jumps.getOrPut(jump) {
|
currentTryScope.jumps.getOrPut(jump) {
|
||||||
val descriptor = getFakeFunctionDescriptor(jump.toString(), value.type)
|
val symbol = getIrReturnableBlockSymbol(jump.toString(), value.type)
|
||||||
with(currentTryScope) {
|
with(currentTryScope) {
|
||||||
irBuilder.run {
|
irBuilder.run {
|
||||||
val inlinedFinally = irInlineFinally(descriptor, expression, finallyExpression)
|
val inlinedFinally = irInlineFinally(symbol, expression, finallyExpression)
|
||||||
expression = performHighLevelJump(
|
expression = performHighLevelJump(
|
||||||
tryScopes = tryScopes,
|
tryScopes = tryScopes,
|
||||||
index = index + 1,
|
index = index + 1,
|
||||||
@@ -174,12 +175,12 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass
|
|||||||
value = inlinedFinally)
|
value = inlinedFinally)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
descriptor
|
symbol
|
||||||
}.let {
|
}.let {
|
||||||
return IrReturnImpl(
|
return IrReturnImpl(
|
||||||
startOffset = startOffset,
|
startOffset = startOffset,
|
||||||
endOffset = endOffset,
|
endOffset = endOffset,
|
||||||
returnTargetDescriptor = it,
|
returnTargetSymbol = it,
|
||||||
value = value)
|
value = value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -191,7 +192,7 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass
|
|||||||
|
|
||||||
val startOffset = aTry.startOffset
|
val startOffset = aTry.startOffset
|
||||||
val endOffset = aTry.endOffset
|
val endOffset = aTry.endOffset
|
||||||
val irBuilder = context.createIrBuilder(functionDescriptor, startOffset, endOffset)
|
val irBuilder = context.createIrBuilder(irFunction.symbol, startOffset, endOffset)
|
||||||
val transformer = this
|
val transformer = this
|
||||||
irBuilder.run {
|
irBuilder.run {
|
||||||
val transformedTry = IrTryImpl(
|
val transformedTry = IrTryImpl(
|
||||||
@@ -223,33 +224,33 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass
|
|||||||
finallyExpression = null
|
finallyExpression = null
|
||||||
)
|
)
|
||||||
using(TryScope(syntheticTry, transformedFinallyExpression, this)) {
|
using(TryScope(syntheticTry, transformedFinallyExpression, this)) {
|
||||||
val fallThroughDescriptor = getFakeFunctionDescriptor("fallThrough", aTry.type)
|
val fallThroughSymbol = getIrReturnableBlockSymbol("fallThrough", aTry.type)
|
||||||
val transformedResult = aTry.tryResult.transform(transformer, null)
|
val transformedResult = aTry.tryResult.transform(transformer, null)
|
||||||
transformedTry.tryResult = irReturn(fallThroughDescriptor, transformedResult)
|
transformedTry.tryResult = irReturn(fallThroughSymbol, transformedResult)
|
||||||
for (aCatch in aTry.catches) {
|
for (aCatch in aTry.catches) {
|
||||||
val transformedCatch = aCatch.transform(transformer, null)
|
val transformedCatch = aCatch.transform(transformer, null)
|
||||||
transformedCatch.result = irReturn(fallThroughDescriptor, transformedCatch.result)
|
transformedCatch.result = irReturn(fallThroughSymbol, transformedCatch.result)
|
||||||
transformedTry.catches.add(transformedCatch)
|
transformedTry.catches.add(transformedCatch)
|
||||||
}
|
}
|
||||||
return irInlineFinally(fallThroughDescriptor, it.expression, it.finallyExpression)
|
return irInlineFinally(fallThroughSymbol, it.expression, it.finallyExpression)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrBuilderWithScope.irInlineFinally(descriptor: FunctionDescriptor,
|
private fun IrBuilderWithScope.irInlineFinally(symbol: IrReturnableBlockSymbol,
|
||||||
value: IrExpression,
|
value: IrExpression,
|
||||||
finallyExpression: IrExpression): IrExpression {
|
finallyExpression: IrExpression): IrExpression {
|
||||||
val returnType = descriptor.returnType!!
|
val returnType = symbol.descriptor.returnType!!
|
||||||
return when {
|
return when {
|
||||||
returnType.isUnit() || returnType.isNothing() -> irBlock(value, null, returnType) {
|
returnType.isUnit() || returnType.isNothing() -> irBlock(value, null, returnType) {
|
||||||
+irReturnableBlock(descriptor) {
|
+irReturnableBlock(symbol) {
|
||||||
+value
|
+value
|
||||||
}
|
}
|
||||||
+finallyExpression.copy()
|
+finallyExpression.copy()
|
||||||
}
|
}
|
||||||
else -> irBlock(value, null, returnType) {
|
else -> irBlock(value, null, returnType) {
|
||||||
val tmp = irTemporary(irReturnableBlock(descriptor) {
|
val tmp = irTemporary(irReturnableBlock(symbol) {
|
||||||
+irReturn(descriptor, value)
|
+irReturn(symbol, value)
|
||||||
})
|
})
|
||||||
+finallyExpression.copy()
|
+finallyExpression.copy()
|
||||||
+irGet(tmp.symbol)
|
+irGet(tmp.symbol)
|
||||||
@@ -268,23 +269,19 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
private fun getIrReturnableBlockSymbol(name: String, returnType: KotlinType): IrReturnableBlockSymbol =
|
||||||
private fun <T: IrElement> T.copy() = this.transform(DeepCopyIrTreeWithDeclarations(), data = null) as T
|
IrReturnableBlockSymbolImpl(getFakeFunctionDescriptor(name, returnType))
|
||||||
|
|
||||||
|
private inline fun <reified T : IrElement> T.copy() = this.deepCopyWithVariables()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private object DECLARATION_ORIGIN_FINALLY_BLOCK :
|
fun IrBuilderWithScope.irReturn(target: IrFunctionSymbol, value: IrExpression) =
|
||||||
IrDeclarationOriginImpl("FINALLY_BLOCK")
|
|
||||||
|
|
||||||
private fun IrBuilderWithScope.irVar(descriptor: VariableDescriptor, initializer: IrExpression?) =
|
|
||||||
IrVariableImpl(startOffset, endOffset, DECLARATION_ORIGIN_FINALLY_BLOCK, descriptor, initializer)
|
|
||||||
|
|
||||||
fun IrBuilderWithScope.irReturn(target: FunctionDescriptor, value: IrExpression) =
|
|
||||||
IrReturnImpl(startOffset, endOffset, target, value)
|
IrReturnImpl(startOffset, endOffset, target, value)
|
||||||
|
|
||||||
inline fun IrBuilderWithScope.irReturnableBlock(descriptor: FunctionDescriptor, body: IrBlockBuilder.() -> Unit) =
|
inline fun IrBuilderWithScope.irReturnableBlock(symbol: IrReturnableBlockSymbol, body: IrBlockBuilder.() -> Unit) =
|
||||||
IrReturnableBlockImpl(startOffset, endOffset, descriptor.returnType!!, descriptor, null,
|
IrReturnableBlockImpl(startOffset, endOffset, symbol.descriptor.returnType!!, symbol, null,
|
||||||
IrBlockBuilder(context, scope, startOffset, endOffset, null, descriptor.returnType!!)
|
IrBlockBuilder(context, scope, startOffset, endOffset, null, symbol.descriptor.returnType!!)
|
||||||
.block(body).statements)
|
.block(body).statements)
|
||||||
}
|
}
|
||||||
+52
-185
@@ -25,32 +25,60 @@ import org.jetbrains.kotlin.backend.konan.ValueType
|
|||||||
import org.jetbrains.kotlin.backend.konan.isRepresentedAs
|
import org.jetbrains.kotlin.backend.konan.isRepresentedAs
|
||||||
import org.jetbrains.kotlin.backend.konan.reportCompilationError
|
import org.jetbrains.kotlin.backend.konan.reportCompilationError
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
|
||||||
import org.jetbrains.kotlin.ir.builders.IrBuilder
|
import org.jetbrains.kotlin.ir.builders.IrBuilder
|
||||||
import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
|
|
||||||
import org.jetbrains.kotlin.ir.builders.irCall
|
import org.jetbrains.kotlin.ir.builders.irCall
|
||||||
import org.jetbrains.kotlin.ir.builders.irGet
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetObjectValueImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetObjectValueImpl
|
||||||
|
import org.jetbrains.kotlin.ir.util.defaultType
|
||||||
|
import org.jetbrains.kotlin.ir.util.functions
|
||||||
import org.jetbrains.kotlin.ir.util.getArguments
|
import org.jetbrains.kotlin.ir.util.getArguments
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||||
|
|
||||||
|
internal class InteropLoweringPart1(val context: Context) : IrElementTransformerVoid(), FileLoweringPass {
|
||||||
|
override fun lower(irFile: IrFile) {
|
||||||
|
irFile.transformChildrenVoid(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
|
expression.transformChildrenVoid()
|
||||||
|
|
||||||
|
return when (expression.descriptor.original) {
|
||||||
|
context.interopBuiltIns.typeOf -> {
|
||||||
|
val typeArgument = expression.getSingleTypeArgument()
|
||||||
|
val classDescriptor = TypeUtils.getClassDescriptor(typeArgument)
|
||||||
|
|
||||||
|
if (classDescriptor == null) {
|
||||||
|
expression
|
||||||
|
} else {
|
||||||
|
val companionObjectDescriptor = classDescriptor.companionObjectDescriptor ?:
|
||||||
|
error("native variable class $classDescriptor must have the companion object")
|
||||||
|
|
||||||
|
IrGetObjectValueImpl(
|
||||||
|
expression.startOffset, expression.endOffset,
|
||||||
|
companionObjectDescriptor.defaultType, companionObjectDescriptor
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> expression
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lowers some interop intrinsic calls.
|
* Lowers some interop intrinsic calls.
|
||||||
*/
|
*/
|
||||||
internal class InteropLowering(val context: Context) : FileLoweringPass {
|
internal class InteropLoweringPart2(val context: Context) : FileLoweringPass {
|
||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
val transformer = InteropTransformer(context, irFile)
|
val transformer = InteropTransformer(context, irFile)
|
||||||
irFile.transformChildrenVoid(transformer)
|
irFile.transformChildrenVoid(transformer)
|
||||||
@@ -60,142 +88,7 @@ internal class InteropLowering(val context: Context) : FileLoweringPass {
|
|||||||
private class InteropTransformer(val context: Context, val irFile: IrFile) : IrBuildingTransformer(context) {
|
private class InteropTransformer(val context: Context, val irFile: IrFile) : IrBuildingTransformer(context) {
|
||||||
|
|
||||||
val interop = context.interopBuiltIns
|
val interop = context.interopBuiltIns
|
||||||
val konanBuiltins = context.builtIns
|
val symbols = context.ir.symbols
|
||||||
|
|
||||||
private fun MemberScope.getSingleContributedFunction(name: String,
|
|
||||||
predicate: (SimpleFunctionDescriptor) -> Boolean) =
|
|
||||||
this.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).single(predicate)
|
|
||||||
|
|
||||||
private fun IrBuilder.irGetObject(descriptor: ClassDescriptor): IrExpression {
|
|
||||||
return IrGetObjectValueImpl(startOffset, endOffset, descriptor.defaultType, descriptor)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrBuilder.typeOf(descriptor: ClassDescriptor): IrExpression {
|
|
||||||
val companionObject = descriptor.companionObjectDescriptor ?:
|
|
||||||
error("native variable class $descriptor must have the companion object")
|
|
||||||
// TODO: add more checks and produce the compile error instead of exception.
|
|
||||||
|
|
||||||
return irGetObject(companionObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrBuilder.typeOf(type: KotlinType): IrExpression? {
|
|
||||||
val descriptor = TypeUtils.getClassDescriptor(type) ?: return null
|
|
||||||
return typeOf(descriptor)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun KotlinType.findOverride(property: PropertyDescriptor): PropertyDescriptor {
|
|
||||||
val result = this.memberScope.getContributedVariables(property.name, NoLookupLocation.FROM_BACKEND).single()
|
|
||||||
assert (OverridingUtil.overrides(result, property))
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrBuilderWithScope.sizeOf(typeObject: IrExpression): IrExpression {
|
|
||||||
val sizeProperty = typeObject.type.findOverride(interop.variableTypeSize)
|
|
||||||
return irGet(typeObject, sizeProperty)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrBuilderWithScope.sizeOf(type: KotlinType): IrExpression? {
|
|
||||||
val typeObject = typeOf(type) ?: return null
|
|
||||||
return sizeOf(typeObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrBuilderWithScope.alignOf(typeObject: IrExpression): IrExpression {
|
|
||||||
val alignProperty = typeObject.type.findOverride(interop.variableTypeAlign)
|
|
||||||
return irGet(typeObject, alignProperty)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrBuilderWithScope.alignOf(type: KotlinType): IrExpression? {
|
|
||||||
val typeObject = typeOf(type) ?: return null
|
|
||||||
return alignOf(typeObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
|
||||||
private fun IrBuilderWithScope.interpretPointed(expression: IrCall, type: KotlinType): IrExpression =
|
|
||||||
irCall(interop.interpretNullablePointed).apply {
|
|
||||||
putValueArgument(0, expression)
|
|
||||||
}
|
|
||||||
// TODO: make the result type more correct.
|
|
||||||
|
|
||||||
private fun IrBuilderWithScope.arrayGet(array: IrExpression, index: IrExpression): IrExpression? {
|
|
||||||
val elementType = array.type.arguments.single().type
|
|
||||||
val elementSize = sizeOf(elementType) ?: return null
|
|
||||||
|
|
||||||
val resultRawPtr = irCall(konanBuiltins.nativePtrPlusLong).apply {
|
|
||||||
dispatchReceiver = irCall(interop.cPointerGetRawValue).apply {
|
|
||||||
extensionReceiver = array
|
|
||||||
}
|
|
||||||
putValueArgument(0, times(elementSize, index))
|
|
||||||
}
|
|
||||||
return interpretPointed(resultRawPtr, elementType)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrBuilderWithScope.times(left: IrExpression, right: IrExpression): IrCall {
|
|
||||||
val times = left.type.memberScope.getSingleContributedFunction("times") {
|
|
||||||
right.type.isSubtypeOf(it.valueParameters.single().type)
|
|
||||||
}
|
|
||||||
|
|
||||||
return irCall(times).apply {
|
|
||||||
dispatchReceiver = left
|
|
||||||
putValueArgument(0, right)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrBuilderWithScope.alloc(placement: IrExpression, size: IrExpression, align: IrExpression): IrExpression {
|
|
||||||
val alloc = placement.type.memberScope.getSingleContributedFunction("alloc") {
|
|
||||||
size.type.isSubtypeOf(it.valueParameters[0]!!.type) &&
|
|
||||||
align.type.isSubtypeOf(it.valueParameters[1]!!.type)
|
|
||||||
}
|
|
||||||
|
|
||||||
return irCall(alloc).apply {
|
|
||||||
dispatchReceiver = placement
|
|
||||||
putValueArgument(0, size)
|
|
||||||
putValueArgument(1, align)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
|
||||||
private fun IrBuilderWithScope.nativePointedToCPointer(
|
|
||||||
expression: IrExpression, pointeeType: KotlinType
|
|
||||||
): IrExpression = irCall(interop.interpretCPointer).apply {
|
|
||||||
putValueArgument(0, irCall(interop.nativePointedGetRawPointer).apply {
|
|
||||||
extensionReceiver = expression
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// TODO: make the result type more correct.
|
|
||||||
|
|
||||||
private fun IrBuilderWithScope.allocArray(placement: IrExpression,
|
|
||||||
elementType: KotlinType,
|
|
||||||
length: IrExpression
|
|
||||||
): IrExpression? {
|
|
||||||
|
|
||||||
val elementSize = sizeOf(elementType) ?: return null
|
|
||||||
val size = times(elementSize, length)
|
|
||||||
val align = alignOf(elementType) ?: return null
|
|
||||||
|
|
||||||
return nativePointedToCPointer(alloc(placement, size, align), elementType)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrBuilderWithScope.alloc(placement: IrExpression, type: KotlinType): IrExpression? {
|
|
||||||
val size = sizeOf(type) ?: return null
|
|
||||||
val align = alignOf(type) ?: return null
|
|
||||||
|
|
||||||
return alloc(placement, size, align)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun IrBuilderWithScope.readValue(receiver: IrExpression, typeArgument: KotlinType): IrCallImpl? {
|
|
||||||
val size = sizeOf(typeArgument) ?: return null
|
|
||||||
val align = alignOf(typeArgument) ?: return null
|
|
||||||
|
|
||||||
val callee = interop.readValueBySizeAndAlign
|
|
||||||
val typeParameter = callee.typeParameters.single()
|
|
||||||
val typeArguments = mapOf(typeParameter to typeArgument)
|
|
||||||
|
|
||||||
return irCall(callee, typeArguments).apply {
|
|
||||||
extensionReceiver = receiver
|
|
||||||
putValueArgument(0, size)
|
|
||||||
putValueArgument(1, align)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
|
|
||||||
@@ -214,7 +107,7 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
|||||||
OverridingUtil.overrides(descriptor, interop.nativePointedRawPtrGetter)) {
|
OverridingUtil.overrides(descriptor, interop.nativePointedRawPtrGetter)) {
|
||||||
|
|
||||||
// Replace by the intrinsic call to be handled by code generator:
|
// Replace by the intrinsic call to be handled by code generator:
|
||||||
return builder.irCall(interop.nativePointedGetRawPointer).apply {
|
return builder.irCall(symbols.interopNativePointedGetRawPointer).apply {
|
||||||
extensionReceiver = expression.dispatchReceiver
|
extensionReceiver = expression.dispatchReceiver
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -222,34 +115,10 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
|||||||
return when (descriptor) {
|
return when (descriptor) {
|
||||||
interop.cPointerRawValue.getter ->
|
interop.cPointerRawValue.getter ->
|
||||||
// Replace by the intrinsic call to be handled by code generator:
|
// Replace by the intrinsic call to be handled by code generator:
|
||||||
builder.irCall(interop.cPointerGetRawValue).apply {
|
builder.irCall(symbols.interopCPointerGetRawValue).apply {
|
||||||
extensionReceiver = expression.dispatchReceiver
|
extensionReceiver = expression.dispatchReceiver
|
||||||
}
|
}
|
||||||
|
|
||||||
interop.arrayGetByIntIndex, interop.arrayGetByLongIndex -> {
|
|
||||||
val array = expression.extensionReceiver!!
|
|
||||||
val index = expression.getValueArgument(0)!!
|
|
||||||
builder.arrayGet(array, index) ?: expression
|
|
||||||
}
|
|
||||||
|
|
||||||
interop.allocUninitializedArrayWithIntLength, interop.allocUninitializedArrayWithLongLength -> {
|
|
||||||
val placement = expression.extensionReceiver!!
|
|
||||||
val elementType = expression.type.arguments.single().type
|
|
||||||
val length = expression.getValueArgument(0)!!
|
|
||||||
builder.allocArray(placement, elementType, length) ?: expression
|
|
||||||
}
|
|
||||||
|
|
||||||
interop.allocVariable -> {
|
|
||||||
val placement = expression.extensionReceiver!!
|
|
||||||
val type = expression.getSingleTypeArgument()
|
|
||||||
builder.alloc(placement, type) ?: expression
|
|
||||||
}
|
|
||||||
|
|
||||||
interop.typeOf -> {
|
|
||||||
val type = expression.getSingleTypeArgument()
|
|
||||||
builder.typeOf(type) ?: expression
|
|
||||||
}
|
|
||||||
|
|
||||||
interop.bitsToFloat -> {
|
interop.bitsToFloat -> {
|
||||||
val argument = expression.getValueArgument(0)
|
val argument = expression.getValueArgument(0)
|
||||||
if (argument is IrConst<*> && argument.kind == IrConstKind.Int) {
|
if (argument is IrConst<*> && argument.kind == IrConstKind.Int) {
|
||||||
@@ -270,13 +139,6 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interop.readValue -> {
|
|
||||||
val typeArgument = expression.getSingleTypeArgument()
|
|
||||||
val receiver = expression.extensionReceiver!!
|
|
||||||
|
|
||||||
builder.readValue(receiver, typeArgument) ?: expression
|
|
||||||
}
|
|
||||||
|
|
||||||
in interop.staticCFunction -> {
|
in interop.staticCFunction -> {
|
||||||
val irCallableReference = unwrapStaticFunctionArgument(expression.getValueArgument(0)!!)
|
val irCallableReference = unwrapStaticFunctionArgument(expression.getValueArgument(0)!!)
|
||||||
|
|
||||||
@@ -288,7 +150,8 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
|||||||
// TODO: should probably be reported during analysis.
|
// TODO: should probably be reported during analysis.
|
||||||
}
|
}
|
||||||
|
|
||||||
val target = irCallableReference.descriptor.original
|
val targetSymbol = irCallableReference.symbol
|
||||||
|
val target = targetSymbol.descriptor
|
||||||
val signatureTypes = target.allParameters.map { it.type } + target.returnType!!
|
val signatureTypes = target.allParameters.map { it.type } + target.returnType!!
|
||||||
|
|
||||||
signatureTypes.forEachIndexed { index, type ->
|
signatureTypes.forEachIndexed { index, type ->
|
||||||
@@ -312,7 +175,7 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
|||||||
IrFunctionReferenceImpl(
|
IrFunctionReferenceImpl(
|
||||||
builder.startOffset, builder.endOffset,
|
builder.startOffset, builder.endOffset,
|
||||||
expression.type,
|
expression.type,
|
||||||
target,
|
targetSymbol, target,
|
||||||
typeArguments = null)
|
typeArguments = null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,10 +215,14 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
|||||||
else -> throw Error()
|
else -> throw Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
val conversionDescriptor = receiver.type.memberScope.getContributedFunctions(
|
val receiverClass = symbols.integerClasses.single {
|
||||||
Name.identifier("to$typeOperand"), NoLookupLocation.FROM_BACKEND).single()
|
receiver.type.isSubtypeOf(it.owner.defaultType)
|
||||||
|
}
|
||||||
|
val conversionSymbol = receiverClass.functions.single {
|
||||||
|
it.descriptor.name == Name.identifier("to$typeOperand")
|
||||||
|
}
|
||||||
|
|
||||||
builder.irCall(conversionDescriptor).apply {
|
builder.irCall(conversionSymbol).apply {
|
||||||
dispatchReceiver = receiver
|
dispatchReceiver = receiver
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -415,11 +282,11 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
|||||||
|
|
||||||
return argument.statements.last() as? IrFunctionReference
|
return argument.statements.last() as? IrFunctionReference
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun IrCall.getSingleTypeArgument(): KotlinType {
|
private fun IrCall.getSingleTypeArgument(): KotlinType {
|
||||||
val typeParameter = descriptor.original.typeParameters.single()
|
val typeParameter = descriptor.original.typeParameters.single()
|
||||||
return getTypeArgument(typeParameter)!!
|
return getTypeArgument(typeParameter)!!
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrBuilder.irFloat(value: Float) =
|
private fun IrBuilder.irFloat(value: Float) =
|
||||||
|
|||||||
+12
-15
@@ -19,19 +19,16 @@ package org.jetbrains.kotlin.backend.konan.lower
|
|||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalFunctions
|
|
||||||
import org.jetbrains.kotlin.backend.konan.isValueType
|
import org.jetbrains.kotlin.backend.konan.isValueType
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrBlock
|
import org.jetbrains.kotlin.ir.expressions.IrBlock
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
|
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
@@ -41,22 +38,24 @@ internal class LateinitLowering(val context: Context): FileLoweringPass {
|
|||||||
irFile.transformChildrenVoid(object: IrElementTransformerVoid() {
|
irFile.transformChildrenVoid(object: IrElementTransformerVoid() {
|
||||||
override fun visitProperty(declaration: IrProperty): IrStatement {
|
override fun visitProperty(declaration: IrProperty): IrStatement {
|
||||||
if (declaration.descriptor.isLateInit)
|
if (declaration.descriptor.isLateInit)
|
||||||
transformGetter(declaration.descriptor, declaration.getter!!)
|
transformGetter(declaration.backingField!!.symbol, declaration.getter!!)
|
||||||
return declaration
|
return declaration
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun transformGetter(propertyDescriptor: PropertyDescriptor, getter: IrFunction) {
|
private fun transformGetter(backingFieldSymbol: IrFieldSymbol, getter: IrFunction) {
|
||||||
assert (!propertyDescriptor.type.isValueType(), { "'lateinit' modifier is not allowed on value types" })
|
val type = backingFieldSymbol.descriptor.type
|
||||||
|
assert (!type.isValueType(), { "'lateinit' modifier is not allowed on value types" })
|
||||||
val startOffset = getter.startOffset
|
val startOffset = getter.startOffset
|
||||||
val endOffset = getter.endOffset
|
val endOffset = getter.endOffset
|
||||||
val irBuilder = context.createIrBuilder(getter.descriptor, startOffset, endOffset)
|
val irBuilder = context.createIrBuilder(getter.symbol, startOffset, endOffset)
|
||||||
irBuilder.run {
|
irBuilder.run {
|
||||||
val block = irBlock(propertyDescriptor.type)
|
val block = irBlock(type)
|
||||||
val resultVar = scope.createTemporaryVariable(irGetField(irThis(), propertyDescriptor))
|
val resultVar = scope.createTemporaryVariable(
|
||||||
|
irGetField(irGet(getter.dispatchReceiverParameter!!.symbol), backingFieldSymbol))
|
||||||
block.statements.add(resultVar)
|
block.statements.add(resultVar)
|
||||||
val throwIfNull = irIfThenElse(context.builtIns.nothingType,
|
val throwIfNull = irIfThenElse(context.builtIns.nothingType,
|
||||||
irNotEquals(irGet(resultVar.descriptor), irNull()),
|
irNotEquals(irGet(resultVar.symbol), irNull()),
|
||||||
irReturn(irGet(resultVar.descriptor)),
|
irReturn(irGet(resultVar.symbol)),
|
||||||
irCall(throwErrorFunction))
|
irCall(throwErrorFunction))
|
||||||
block.statements.add(throwIfNull)
|
block.statements.add(throwIfNull)
|
||||||
getter.body = IrExpressionBodyImpl(startOffset, endOffset, block)
|
getter.body = IrExpressionBodyImpl(startOffset, endOffset, block)
|
||||||
@@ -65,11 +64,9 @@ internal class LateinitLowering(val context: Context): FileLoweringPass {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private val throwErrorFunction = context.builtIns.getKonanInternalFunctions("ThrowUninitializedPropertyAccessException").single()
|
private val throwErrorFunction = context.ir.symbols.ThrowUninitializedPropertyAccessException
|
||||||
|
|
||||||
private fun IrBuilderWithScope.irBlock(type: KotlinType): IrBlock
|
private fun IrBuilderWithScope.irBlock(type: KotlinType): IrBlock
|
||||||
= IrBlockImpl(startOffset, endOffset, type)
|
= IrBlockImpl(startOffset, endOffset, type)
|
||||||
|
|
||||||
private fun IrBuilderWithScope.irGetField(receiver: IrExpression?, property: PropertyDescriptor): IrExpression
|
|
||||||
= IrGetFieldImpl(startOffset, endOffset, property, receiver)
|
|
||||||
}
|
}
|
||||||
+31
-59
@@ -21,9 +21,7 @@ import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters
|
|||||||
import org.jetbrains.kotlin.backend.common.lower.*
|
import org.jetbrains.kotlin.backend.common.lower.*
|
||||||
import org.jetbrains.kotlin.backend.common.*
|
import org.jetbrains.kotlin.backend.common.*
|
||||||
import org.jetbrains.kotlin.backend.konan.Context
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalClass
|
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalFunctions
|
import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalFunctions
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.isSuspendFunctionInvoke
|
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.*
|
import org.jetbrains.kotlin.backend.konan.ir.*
|
||||||
import org.jetbrains.kotlin.backend.konan.util.atMostOne
|
import org.jetbrains.kotlin.backend.konan.util.atMostOne
|
||||||
@@ -43,9 +41,6 @@ import org.jetbrains.kotlin.ir.symbols.*
|
|||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
|
||||||
import org.jetbrains.kotlin.ir.util.getArguments
|
|
||||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.*
|
import org.jetbrains.kotlin.ir.visitors.*
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
@@ -53,6 +48,7 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.*
|
import org.jetbrains.kotlin.backend.common.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
|
||||||
internal class SuspendFunctionsLowering(val context: Context): DeclarationContainerLoweringPass {
|
internal class SuspendFunctionsLowering(val context: Context): DeclarationContainerLoweringPass {
|
||||||
|
|
||||||
@@ -67,7 +63,6 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
else null
|
else null
|
||||||
}
|
}
|
||||||
transformCallableReferencesToSuspendLambdas(irDeclarationContainer)
|
transformCallableReferencesToSuspendLambdas(irDeclarationContainer)
|
||||||
transformCallsToExtensionSuspendFunctions(irDeclarationContainer)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun markSuspendLambdas(irDeclarationContainer: IrDeclarationContainer) {
|
private fun markSuspendLambdas(irDeclarationContainer: IrDeclarationContainer) {
|
||||||
@@ -116,36 +111,6 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun transformCallsToExtensionSuspendFunctions(irDeclarationContainer: IrDeclarationContainer) {
|
|
||||||
irDeclarationContainer.declarations.forEach {
|
|
||||||
it.transformChildrenVoid(object: IrElementTransformerVoid() {
|
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
|
||||||
expression.transformChildrenVoid(this)
|
|
||||||
|
|
||||||
val descriptor = expression.descriptor
|
|
||||||
|
|
||||||
if (!descriptor.isSuspendFunctionInvoke || descriptor.extensionReceiverParameter == null)
|
|
||||||
return expression
|
|
||||||
|
|
||||||
val invokeFunctionDescriptor = descriptor.dispatchReceiverParameter!!.type.memberScope
|
|
||||||
.getContributedFunctions(Name.identifier("invoke"), NoLookupLocation.FROM_BACKEND).single()
|
|
||||||
return IrCallImpl(
|
|
||||||
startOffset = expression.startOffset,
|
|
||||||
endOffset = expression.endOffset,
|
|
||||||
calleeDescriptor = invokeFunctionDescriptor
|
|
||||||
).apply {
|
|
||||||
dispatchReceiver = expression.dispatchReceiver
|
|
||||||
putValueArgument(0, expression.extensionReceiver)
|
|
||||||
invokeFunctionDescriptor.valueParameters.drop(1).forEach {
|
|
||||||
putValueArgument(it.index, expression.getValueArgument(it.index - 1))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum class SuspendFunctionKind {
|
private enum class SuspendFunctionKind {
|
||||||
NO_SUSPEND_CALLS,
|
NO_SUSPEND_CALLS,
|
||||||
DELEGATING,
|
DELEGATING,
|
||||||
@@ -235,7 +200,8 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val getContinuationDescriptor = context.builtIns.getKonanInternalFunctions("getContinuation").single()
|
private val symbols = context.ir.symbols
|
||||||
|
private val getContinuationSymbol = symbols.getContinuation
|
||||||
private val returnIfSuspendedDescriptor = context.builtIns.getKonanInternalFunctions("returnIfSuspended").single()
|
private val returnIfSuspendedDescriptor = context.builtIns.getKonanInternalFunctions("returnIfSuspended").single()
|
||||||
|
|
||||||
private fun removeReturnIfSuspendedCall(irFunction: IrFunction) {
|
private fun removeReturnIfSuspendedCall(irFunction: IrFunction) {
|
||||||
@@ -262,15 +228,15 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
+irReturn(
|
+irReturn(
|
||||||
irCall(coroutine.doResumeFunction.symbol).apply {
|
irCall(coroutine.doResumeFunction.symbol).apply {
|
||||||
dispatchReceiver = irCall(coroutine.coroutineConstructor.symbol).apply {
|
dispatchReceiver = irCall(coroutine.coroutineConstructor.symbol).apply {
|
||||||
val functionParameters = irFunction.descriptor.explicitParameters
|
val functionParameters = irFunction.explicitParameters
|
||||||
functionParameters.forEachIndexed { index, argument ->
|
functionParameters.forEachIndexed { index, argument ->
|
||||||
putValueArgument(index, irGet(argument))
|
putValueArgument(index, irGet(argument))
|
||||||
}
|
}
|
||||||
putValueArgument(functionParameters.size,
|
putValueArgument(functionParameters.size,
|
||||||
irCall(getContinuationDescriptor.substitute(descriptor.returnType!!)))
|
irCall(getContinuationSymbol, listOf(descriptor.returnType!!)))
|
||||||
}
|
}
|
||||||
putValueArgument(0, irUnit()) // value
|
putValueArgument(0, irGetObject(symbols.unit)) // value
|
||||||
putValueArgument(1, irNull()) // exception
|
putValueArgument(1, irNull()) // exception
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -285,17 +251,13 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
private var coroutineId = 0
|
private var coroutineId = 0
|
||||||
|
|
||||||
private val COROUTINES_FQ_NAME = FqName.fromSegments(listOf("kotlin", "coroutines", "experimental"))
|
private val COROUTINES_FQ_NAME = FqName.fromSegments(listOf("kotlin", "coroutines", "experimental"))
|
||||||
private val COROUTINES_INTRINSICS_FQ_NAME = FqName.fromSegments(listOf("kotlin", "coroutines", "experimental", "intrinsics"))
|
|
||||||
private val KOTLIN_FQ_NAME = FqName("kotlin")
|
private val KOTLIN_FQ_NAME = FqName("kotlin")
|
||||||
|
|
||||||
private val coroutinesScope = context.irModule!!.descriptor.getPackage(COROUTINES_FQ_NAME).memberScope
|
private val coroutinesScope = context.irModule!!.descriptor.getPackage(COROUTINES_FQ_NAME).memberScope
|
||||||
private val coroutinesIntrinsicsScope = context.irModule!!.descriptor.getPackage(COROUTINES_INTRINSICS_FQ_NAME).memberScope
|
|
||||||
private val kotlinPackageScope = context.irModule!!.descriptor.getPackage(KOTLIN_FQ_NAME).memberScope
|
private val kotlinPackageScope = context.irModule!!.descriptor.getPackage(KOTLIN_FQ_NAME).memberScope
|
||||||
|
|
||||||
private val continuationClassDescriptor = coroutinesScope
|
private val continuationClassDescriptor = coroutinesScope
|
||||||
.getContributedClassifier(Name.identifier("Continuation"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor
|
.getContributedClassifier(Name.identifier("Continuation"), NoLookupLocation.FROM_BACKEND) as ClassDescriptor
|
||||||
private val COROUTINE_SUSPENDED = coroutinesIntrinsicsScope
|
|
||||||
.getContributedVariables(Name.identifier("COROUTINE_SUSPENDED"), NoLookupLocation.FROM_BACKEND).first()
|
|
||||||
|
|
||||||
private inner class CoroutineBuilder(val irFunction: IrFunction, val functionReference: IrFunctionReference?) {
|
private inner class CoroutineBuilder(val irFunction: IrFunction, val functionReference: IrFunctionReference?) {
|
||||||
|
|
||||||
@@ -313,12 +275,17 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
private lateinit var coroutineClassThis: IrValueParameterSymbol
|
private lateinit var coroutineClassThis: IrValueParameterSymbol
|
||||||
private lateinit var argumentToPropertiesMap: Map<ParameterDescriptor, IrFieldSymbol>
|
private lateinit var argumentToPropertiesMap: Map<ParameterDescriptor, IrFieldSymbol>
|
||||||
|
|
||||||
private val coroutineImplClassDescriptor = context.builtIns.getKonanInternalClass("CoroutineImpl")
|
private val coroutineImplSymbol = symbols.coroutineImpl
|
||||||
|
private val coroutineImplConstructorSymbol = coroutineImplSymbol.constructors.single()
|
||||||
|
private val coroutineImplClassDescriptor = coroutineImplSymbol.descriptor
|
||||||
private val create1FunctionDescriptor = coroutineImplClassDescriptor.unsubstitutedMemberScope
|
private val create1FunctionDescriptor = coroutineImplClassDescriptor.unsubstitutedMemberScope
|
||||||
.getContributedFunctions(Name.identifier("create"), NoLookupLocation.FROM_BACKEND)
|
.getContributedFunctions(Name.identifier("create"), NoLookupLocation.FROM_BACKEND)
|
||||||
.single { it.valueParameters.size == 1 }
|
.single { it.valueParameters.size == 1 }
|
||||||
private val create1CompletionParameter = create1FunctionDescriptor.valueParameters[0]
|
private val create1CompletionParameter = create1FunctionDescriptor.valueParameters[0]
|
||||||
|
|
||||||
|
private val coroutineImplLabelGetterSymbol = coroutineImplSymbol.getPropertyGetter("label")!!
|
||||||
|
private val coroutineImplLabelSetterSymbol = coroutineImplSymbol.getPropertySetter("label")!!
|
||||||
|
|
||||||
fun build(): BuiltCoroutine {
|
fun build(): BuiltCoroutine {
|
||||||
val superTypes = mutableListOf<KotlinType>(coroutineImplClassDescriptor.defaultType)
|
val superTypes = mutableListOf<KotlinType>(coroutineImplClassDescriptor.defaultType)
|
||||||
var suspendFunctionClassDescriptor: ClassDescriptor? = null
|
var suspendFunctionClassDescriptor: ClassDescriptor? = null
|
||||||
@@ -406,6 +373,8 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
).filterNotNull().toList()
|
).filterNotNull().toList()
|
||||||
coroutineClassDescriptor.initialize(SimpleMemberScope(contributedDescriptors), constructors, null)
|
coroutineClassDescriptor.initialize(SimpleMemberScope(contributedDescriptors), constructors, null)
|
||||||
|
|
||||||
|
coroutineClass.addFakeOverrides()
|
||||||
|
|
||||||
coroutineConstructorBuilder.initialize()
|
coroutineConstructorBuilder.initialize()
|
||||||
coroutineClass.declarations.add(coroutineConstructorBuilder.ir)
|
coroutineClass.declarations.add(coroutineConstructorBuilder.ir)
|
||||||
|
|
||||||
@@ -437,8 +406,6 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
private fun createConstructorBuilder()
|
private fun createConstructorBuilder()
|
||||||
= object : SymbolWithIrBuilder<IrConstructorSymbol, IrConstructor>() {
|
= object : SymbolWithIrBuilder<IrConstructorSymbol, IrConstructor>() {
|
||||||
|
|
||||||
private val coroutineImplConstructorDescriptor = coroutineImplClassDescriptor.constructors.single()
|
|
||||||
|
|
||||||
override fun buildSymbol() = IrConstructorSymbolImpl(
|
override fun buildSymbol() = IrConstructorSymbolImpl(
|
||||||
ClassConstructorDescriptorImpl.create(
|
ClassConstructorDescriptorImpl.create(
|
||||||
/* containingDeclaration = */ coroutineClassDescriptor,
|
/* containingDeclaration = */ coroutineClassDescriptor,
|
||||||
@@ -452,7 +419,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
val descriptor = symbol.descriptor as ClassConstructorDescriptorImpl
|
val descriptor = symbol.descriptor as ClassConstructorDescriptorImpl
|
||||||
val constructorParameters = (
|
val constructorParameters = (
|
||||||
functionParameters
|
functionParameters
|
||||||
+ coroutineImplConstructorDescriptor.valueParameters[0] // completion.
|
+ coroutineImplConstructorSymbol.descriptor.valueParameters[0] // completion.
|
||||||
).mapIndexed { index, parameter -> parameter.copyAsValueParameter(descriptor, index) }
|
).mapIndexed { index, parameter -> parameter.copyAsValueParameter(descriptor, index) }
|
||||||
|
|
||||||
descriptor.initialize(constructorParameters, Visibilities.PUBLIC)
|
descriptor.initialize(constructorParameters, Visibilities.PUBLIC)
|
||||||
@@ -478,7 +445,8 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
||||||
body = irBuilder.irBlockBody {
|
body = irBuilder.irBlockBody {
|
||||||
val completionParameter = valueParameters.last()
|
val completionParameter = valueParameters.last()
|
||||||
+IrDelegatingConstructorCallImpl(startOffset, endOffset, coroutineImplConstructorDescriptor).apply {
|
+IrDelegatingConstructorCallImpl(startOffset, endOffset,
|
||||||
|
coroutineImplConstructorSymbol, coroutineImplConstructorSymbol.descriptor).apply {
|
||||||
putValueArgument(0, irGet(completionParameter.symbol))
|
putValueArgument(0, irGet(completionParameter.symbol))
|
||||||
}
|
}
|
||||||
+IrInstanceInitializerCallImpl(startOffset, endOffset, coroutineClass.symbol)
|
+IrInstanceInitializerCallImpl(startOffset, endOffset, coroutineClass.symbol)
|
||||||
@@ -493,8 +461,6 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
private fun createFactoryConstructorBuilder(boundParams: List<ParameterDescriptor>)
|
private fun createFactoryConstructorBuilder(boundParams: List<ParameterDescriptor>)
|
||||||
= object : SymbolWithIrBuilder<IrConstructorSymbol, IrConstructor>() {
|
= object : SymbolWithIrBuilder<IrConstructorSymbol, IrConstructor>() {
|
||||||
|
|
||||||
private val coroutineImplConstructorDescriptor = coroutineImplClassDescriptor.constructors.single()
|
|
||||||
|
|
||||||
override fun buildSymbol() = IrConstructorSymbolImpl(
|
override fun buildSymbol() = IrConstructorSymbolImpl(
|
||||||
ClassConstructorDescriptorImpl.create(
|
ClassConstructorDescriptorImpl.create(
|
||||||
/* containingDeclaration = */ coroutineClassDescriptor,
|
/* containingDeclaration = */ coroutineClassDescriptor,
|
||||||
@@ -526,7 +492,8 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
|
|
||||||
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
||||||
body = irBuilder.irBlockBody {
|
body = irBuilder.irBlockBody {
|
||||||
+IrDelegatingConstructorCallImpl(startOffset, endOffset, coroutineImplConstructorDescriptor).apply {
|
+IrDelegatingConstructorCallImpl(startOffset, endOffset,
|
||||||
|
coroutineImplConstructorSymbol, coroutineImplConstructorSymbol.descriptor).apply {
|
||||||
putValueArgument(0, irNull()) // Completion.
|
putValueArgument(0, irNull()) // Completion.
|
||||||
}
|
}
|
||||||
+IrInstanceInitializerCallImpl(startOffset, endOffset, coroutineClass.symbol)
|
+IrInstanceInitializerCallImpl(startOffset, endOffset, coroutineClass.symbol)
|
||||||
@@ -669,9 +636,9 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
putValueArgument(index, irGet(parameter.symbol))
|
putValueArgument(index, irGet(parameter.symbol))
|
||||||
}
|
}
|
||||||
putValueArgument(valueParameters.size,
|
putValueArgument(valueParameters.size,
|
||||||
irCall(getContinuationDescriptor.substitute(symbol.descriptor.returnType!!)))
|
irCall(getContinuationSymbol, listOf(symbol.descriptor.returnType!!)))
|
||||||
}
|
}
|
||||||
putValueArgument(0, irUnit()) // value
|
putValueArgument(0, irGetObject(symbols.unit)) // value
|
||||||
putValueArgument(1, irNull()) // exception
|
putValueArgument(1, irNull()) // exception
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -803,7 +770,10 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
scope.forEach {
|
scope.forEach {
|
||||||
+irSetField(irGet(coroutineClassThis), localToPropertyMap[it]!!, irGet(localsMap[it.descriptor] ?: it))
|
+irSetField(irGet(coroutineClassThis), localToPropertyMap[it]!!, irGet(localsMap[it.descriptor] ?: it))
|
||||||
}
|
}
|
||||||
+irSet(irGet(coroutineClassThis), label, irGet(suspensionPoint.suspensionPointIdParameter.symbol))
|
+irCall(coroutineImplLabelSetterSymbol).apply {
|
||||||
|
dispatchReceiver = irGet(coroutineClassThis)
|
||||||
|
putValueArgument(0, irGet(suspensionPoint.suspensionPointIdParameter.symbol))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
restoreStateSymbol -> {
|
restoreStateSymbol -> {
|
||||||
@@ -828,13 +798,15 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
startOffset = startOffset,
|
startOffset = startOffset,
|
||||||
endOffset = endOffset,
|
endOffset = endOffset,
|
||||||
type = context.builtIns.unitType,
|
type = context.builtIns.unitType,
|
||||||
suspensionPointId = irGet(irGet(coroutineClassThis), label),
|
suspensionPointId = irCall(coroutineImplLabelGetterSymbol).apply {
|
||||||
|
dispatchReceiver = irGet(coroutineClassThis)
|
||||||
|
},
|
||||||
result = irBlock(startOffset, endOffset) {
|
result = irBlock(startOffset, endOffset) {
|
||||||
+irThrowIfNotNull(exceptionArgument) // Coroutine might start with an exception.
|
+irThrowIfNotNull(exceptionArgument) // Coroutine might start with an exception.
|
||||||
statements.forEach { +it }
|
statements.forEach { +it }
|
||||||
})
|
})
|
||||||
if (irFunction.descriptor.returnType!!.isUnit())
|
if (irFunction.descriptor.returnType!!.isUnit())
|
||||||
+irReturn(irUnit()) // Insert explicit return for Unit functions.
|
+irReturn(irGetObject(symbols.unit)) // Insert explicit return for Unit functions.
|
||||||
}
|
}
|
||||||
return function
|
return function
|
||||||
}
|
}
|
||||||
@@ -1156,7 +1128,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun IrBuilderWithScope.irReturnIfSuspended(value: IrValueSymbol) =
|
private fun IrBuilderWithScope.irReturnIfSuspended(value: IrValueSymbol) =
|
||||||
irIfThen(irEqeqeq(irGet(value), irGet(COROUTINE_SUSPENDED)),
|
irIfThen(irEqeqeq(irGet(value), irCall(symbols.coroutineSuspendedGetter)),
|
||||||
irReturn(irGet(value)))
|
irReturn(irGet(value)))
|
||||||
|
|
||||||
private fun IrBuilderWithScope.irThrowIfNotNull(exception: IrValueSymbol) =
|
private fun IrBuilderWithScope.irThrowIfNotNull(exception: IrValueSymbol) =
|
||||||
|
|||||||
+54
-74
@@ -23,47 +23,50 @@ import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedString
|
|||||||
import org.jetbrains.kotlin.backend.konan.ir.ir2string
|
import org.jetbrains.kotlin.backend.konan.ir.ir2string
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.builders.IrBuilderWithScope
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.builders.Scope
|
|
||||||
import org.jetbrains.kotlin.ir.builders.irGet
|
|
||||||
import org.jetbrains.kotlin.ir.builders.irSetVar
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
|
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.IrConstImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.util.constructors
|
||||||
|
import org.jetbrains.kotlin.ir.util.defaultType
|
||||||
|
import org.jetbrains.kotlin.ir.util.functions
|
||||||
|
import org.jetbrains.kotlin.ir.util.getPropertyGetter
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.FqName
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
|
||||||
|
|
||||||
class VarargInjectionLowering internal constructor(val context: Context): DeclarationContainerLoweringPass {
|
class VarargInjectionLowering internal constructor(val context: Context): DeclarationContainerLoweringPass {
|
||||||
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
|
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
|
||||||
irDeclarationContainer.declarations.forEach{
|
irDeclarationContainer.declarations.forEach{
|
||||||
when (it) {
|
when (it) {
|
||||||
is IrField -> lower(it.descriptor, it.initializer)
|
is IrField -> lower(it.symbol, it.initializer)
|
||||||
is IrFunction -> lower(it.descriptor, it.body)
|
is IrFunction -> lower(it.symbol, it.body)
|
||||||
is IrProperty -> {
|
is IrProperty -> {
|
||||||
lower(it.descriptor, it.backingField)
|
it.backingField?.let { field ->
|
||||||
if (it.getter != null)
|
lower(field.symbol, field)
|
||||||
lower(it.getter!!.descriptor, it.getter)
|
}
|
||||||
if (it.setter != null)
|
it.getter?.let { getter ->
|
||||||
lower(it.setter!!.descriptor, it.setter)
|
lower(getter.symbol, getter)
|
||||||
|
}
|
||||||
|
it.setter?.let { setter ->
|
||||||
|
lower(setter.symbol, setter)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun lower(owner:DeclarationDescriptor, element: IrElement?) {
|
private fun lower(owner: IrSymbol, element: IrElement?) {
|
||||||
element?.transformChildrenVoid(object: IrElementTransformerVoid() {
|
element?.transformChildrenVoid(object: IrElementTransformerVoid() {
|
||||||
val transformer = this
|
val transformer = this
|
||||||
|
|
||||||
@@ -107,11 +110,13 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar
|
|||||||
val type = expression.varargElementType
|
val type = expression.varargElementType
|
||||||
log("$expression: array type:$type, is array of primitives ${!KotlinBuiltIns.isArray(expression.type)}")
|
log("$expression: array type:$type, is array of primitives ${!KotlinBuiltIns.isArray(expression.type)}")
|
||||||
val arrayHandle = arrayType(expression.type)
|
val arrayHandle = arrayType(expression.type)
|
||||||
val arrayConstructor = arrayHandle.arrayDescriptor.constructors.find { it.valueParameters.size == 1 }!!
|
val arrayConstructor = arrayHandle.arraySymbol.constructors.find { it.owner.valueParameters.size == 1 }!!
|
||||||
val block = irBlock(arrayHandle.arrayDescriptor.defaultType)
|
val block = irBlock(arrayHandle.arraySymbol.owner.defaultType)
|
||||||
val arrayConstructorCall = irCall(
|
val arrayConstructorCall = if (arrayConstructor.owner.typeParameters.isEmpty()) {
|
||||||
descriptor = arrayConstructor,
|
irCall(arrayConstructor)
|
||||||
typeArguments = typeArgument(arrayConstructor, type))
|
} else {
|
||||||
|
irCall(arrayConstructor, listOf(type))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
val vars = expression.elements.map {
|
val vars = expression.elements.map {
|
||||||
@@ -135,10 +140,7 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar
|
|||||||
log("element:$i> ${ir2string(element)}")
|
log("element:$i> ${ir2string(element)}")
|
||||||
val dst = vars[element]!!
|
val dst = vars[element]!!
|
||||||
if (element !is IrSpreadElement) {
|
if (element !is IrSpreadElement) {
|
||||||
val setArrayElementCall = irCall(
|
val setArrayElementCall = irCall(arrayHandle.setMethodSymbol)
|
||||||
descriptor = arrayHandle.setMethodDescriptor,
|
|
||||||
typeArguments = null
|
|
||||||
)
|
|
||||||
setArrayElementCall.dispatchReceiver = irGet(arrayTmpVariable.symbol)
|
setArrayElementCall.dispatchReceiver = irGet(arrayTmpVariable.symbol)
|
||||||
setArrayElementCall.putValueArgument(0, if (hasSpreadElement) irGet(indexTmpVariable.symbol) else irConstInt(i))
|
setArrayElementCall.putValueArgument(0, if (hasSpreadElement) irGet(indexTmpVariable.symbol) else irConstInt(i))
|
||||||
setArrayElementCall.putValueArgument(1, irGet(dst.symbol))
|
setArrayElementCall.putValueArgument(1, irGet(dst.symbol))
|
||||||
@@ -149,7 +151,7 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar
|
|||||||
} else {
|
} else {
|
||||||
val arraySizeVariable = scope.createTemporaryVariable(irArraySize(arrayHandle, irGet(dst.symbol)), "length".synthesizedString)
|
val arraySizeVariable = scope.createTemporaryVariable(irArraySize(arrayHandle, irGet(dst.symbol)), "length".synthesizedString)
|
||||||
block.statements.add(arraySizeVariable)
|
block.statements.add(arraySizeVariable)
|
||||||
val copyCall = irCall(arrayHandle.copyRangeToDescriptor, null).apply {
|
val copyCall = irCall(arrayHandle.copyRangeToSymbol).apply {
|
||||||
extensionReceiver = irGet(dst.symbol)
|
extensionReceiver = irGet(dst.symbol)
|
||||||
putValueArgument(0, irGet(arrayTmpVariable.symbol)) /* destination */
|
putValueArgument(0, irGet(arrayTmpVariable.symbol)) /* destination */
|
||||||
putValueArgument(1, kIntZero) /* fromIndex */
|
putValueArgument(1, kIntZero) /* fromIndex */
|
||||||
@@ -170,13 +172,8 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val symbols = context.ir.symbols
|
||||||
private fun typeArgument(arrayConstructor: ClassConstructorDescriptor, type: KotlinType):Map<TypeParameterDescriptor, KotlinType>? {
|
private val intPlusInt = symbols.intPlusInt
|
||||||
return if (!arrayConstructor.typeParameters.isEmpty())
|
|
||||||
mapOf(arrayConstructor.typeParameters.first() to type)
|
|
||||||
else
|
|
||||||
null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun arrayType(type: KotlinType): ArrayHandle = when {
|
private fun arrayType(type: KotlinType): ArrayHandle = when {
|
||||||
KotlinBuiltIns.isPrimitiveArray(type) -> {
|
KotlinBuiltIns.isPrimitiveArray(type) -> {
|
||||||
@@ -196,7 +193,7 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar
|
|||||||
else -> kArrayHandler
|
else -> kArrayHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrBuilderWithScope.intPlus() = irCall(kIntPlusDescriptor, null)
|
private fun IrBuilderWithScope.intPlus() = irCall(intPlusInt)
|
||||||
private fun IrBuilderWithScope.increment(expression: IrExpression, value: IrExpression): IrExpression {
|
private fun IrBuilderWithScope.increment(expression: IrExpression, value: IrExpression): IrExpression {
|
||||||
return intPlus().apply {
|
return intPlus().apply {
|
||||||
dispatchReceiver = expression
|
dispatchReceiver = expression
|
||||||
@@ -211,7 +208,7 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
private fun calculateArraySize(arrayHandle: ArrayHandle, hasSpreadElement: Boolean, scope:Scope, expression: IrVararg, vars: Map<IrVarargElement, IrVariable>): IrExpression? {
|
private fun calculateArraySize(arrayHandle: ArrayHandle, hasSpreadElement: Boolean, scope:Scope, expression: IrVararg, vars: Map<IrVarargElement, IrVariable>): IrExpression? {
|
||||||
context.createIrBuilder(scope.scopeOwner, expression.startOffset, expression.endOffset).run {
|
context.createIrBuilder(scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset).run {
|
||||||
if (!hasSpreadElement)
|
if (!hasSpreadElement)
|
||||||
return irConstInt(expression.elements.size)
|
return irConstInt(expression.elements.size)
|
||||||
val notSpreadElementCount = expression.elements.filter { it !is IrSpreadElement}.size
|
val notSpreadElementCount = expression.elements.filter { it !is IrSpreadElement}.size
|
||||||
@@ -224,7 +221,7 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun IrBuilderWithScope.irArraySize(arrayHandle: ArrayHandle, expression: IrExpression): IrExpression {
|
private fun IrBuilderWithScope.irArraySize(arrayHandle: ArrayHandle, expression: IrExpression): IrExpression {
|
||||||
val arraySize = irCall((arrayHandle.sizeDescriptor as PropertyDescriptor).getter as FunctionDescriptor, null).apply {
|
val arraySize = irCall(arrayHandle.sizeGetterSymbol).apply {
|
||||||
dispatchReceiver = expression
|
dispatchReceiver = expression
|
||||||
}
|
}
|
||||||
return arraySize
|
return arraySize
|
||||||
@@ -237,48 +234,31 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar
|
|||||||
context.log{"VARARG-INJECTOR: $msg"}
|
context.log{"VARARG-INJECTOR: $msg"}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class ArrayHandle(val arrayDescriptor:ClassDescriptor,
|
data class ArrayHandle(val arraySymbol: IrClassSymbol,
|
||||||
val setMethodDescriptor: FunctionDescriptor,
|
val setMethodSymbol: IrFunctionSymbol,
|
||||||
val sizeDescriptor:DeclarationDescriptor,
|
val sizeGetterSymbol: IrFunctionSymbol,
|
||||||
val copyRangeToDescriptor:FunctionDescriptor)
|
val copyRangeToSymbol: IrFunctionSymbol)
|
||||||
val kKotlinPackage = context.builtIns.builtInsModule.getPackage(FqName("kotlin"))
|
|
||||||
val kByteArrayHandler = handle(arrayClassDescriptor("ByteArray"))
|
|
||||||
val kCharArrayHandler = handle(arrayClassDescriptor("CharArray"))
|
|
||||||
val kShortArrayHandler = handle(arrayClassDescriptor("ShortArray"))
|
|
||||||
val kIntArrayHandler = handle(arrayClassDescriptor("IntArray"))
|
|
||||||
val kLongArrayHandler = handle(arrayClassDescriptor("LongArray"))
|
|
||||||
val kFloatArrayHandler = handle(arrayClassDescriptor("FloatArray"))
|
|
||||||
val kDoubleArrayHandler = handle(arrayClassDescriptor("DoubleArray"))
|
|
||||||
val kBooleanArrayHandler = handle(arrayClassDescriptor("BooleanArray"))
|
|
||||||
val kArrayHandler = handle(context.builtIns.array)
|
|
||||||
|
|
||||||
val kInt = context.builtIns.int
|
val kByteArrayHandler = handle(symbols.byteArray)
|
||||||
val kIntType = context.builtIns.intType
|
val kCharArrayHandler = handle(symbols.charArray)
|
||||||
val kIntPlusDescriptor = DescriptorUtils.getAllDescriptors(kInt.unsubstitutedMemberScope).find {
|
val kShortArrayHandler = handle(symbols.shortArray)
|
||||||
it.name.asString() == "plus"
|
val kIntArrayHandler = handle(symbols.intArray)
|
||||||
&& (it as FunctionDescriptor).valueParameters[0].type == kIntType} as FunctionDescriptor
|
val kLongArrayHandler = handle(symbols.longArray)
|
||||||
|
val kFloatArrayHandler = handle(symbols.floatArray)
|
||||||
|
val kDoubleArrayHandler = handle(symbols.doubleArray)
|
||||||
|
val kBooleanArrayHandler = handle(symbols.booleanArray)
|
||||||
|
val kArrayHandler = handle(symbols.array)
|
||||||
|
|
||||||
private fun handle(descriptor:ClassDescriptor) = ArrayHandle(
|
private fun handle(symbol: IrClassSymbol) = ArrayHandle(
|
||||||
arrayDescriptor = descriptor,
|
arraySymbol = symbol,
|
||||||
setMethodDescriptor = setMethodDescriptor(descriptor),
|
setMethodSymbol = symbol.functions.single { it.descriptor.name == OperatorNameConventions.SET },
|
||||||
sizeDescriptor = sizeMethodDescriptor(descriptor)!!,
|
sizeGetterSymbol = symbol.getPropertyGetter("size")!!,
|
||||||
copyRangeToDescriptor = copyRangeToFunctionDescriptor(descriptor))
|
copyRangeToSymbol = symbols.copyRangeTo[symbol.descriptor]!!
|
||||||
|
)
|
||||||
|
|
||||||
private fun copyRangeToFunctionDescriptor(descriptor: ClassDescriptor): FunctionDescriptor {
|
|
||||||
val packageViewDescriptor = descriptor.module.getPackage(KotlinBuiltIns.COLLECTIONS_PACKAGE_FQ_NAME)
|
|
||||||
return packageViewDescriptor.memberScope.getContributedFunctions(Name.identifier("copyRangeTo"), NoLookupLocation.FROM_BACKEND).first {
|
|
||||||
it.extensionReceiverParameter?.type?.constructor?.declarationDescriptor == descriptor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private fun setMethodDescriptor(descriptor:ClassDescriptor) = methodDescriptor(descriptor, "set")
|
|
||||||
private fun sizeMethodDescriptor(descriptor:ClassDescriptor) = descriptor(descriptor, "size")
|
|
||||||
private fun methodDescriptor(descriptor:ClassDescriptor, methodName:String) = DescriptorUtils.getFunctionByName(descriptor.unsubstitutedMemberScope, Name.identifier(methodName))
|
|
||||||
private fun arrayClassDescriptor(name:String) = kKotlinPackage.memberScope.getContributedClassifier(Name.identifier(name), NoLookupLocation.FROM_BACKEND) as ClassDescriptor
|
|
||||||
private fun descriptor(descriptor: ClassDescriptor, name:String) = DescriptorUtils.getAllDescriptors(descriptor.unsubstitutedMemberScope).find{it.name.asString() == name}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun IrBuilderWithScope.irConstInt(value: Int): IrConst<Int> = IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, value)
|
private fun IrBuilderWithScope.irConstInt(value: Int): IrConst<Int> = IrConstImpl.int(startOffset, endOffset, context.builtIns.intType, value)
|
||||||
private fun IrBuilderWithScope.irBlock(type: KotlinType): IrBlock = IrBlockImpl(startOffset, endOffset, type)
|
private fun IrBuilderWithScope.irBlock(type: KotlinType): IrBlock = IrBlockImpl(startOffset, endOffset, type)
|
||||||
private fun IrBuilderWithScope.irCall(descriptor: FunctionDescriptor, typeArguments: Map<TypeParameterDescriptor, KotlinType>?): IrCall = IrCallImpl(startOffset, endOffset, descriptor, typeArguments)
|
|
||||||
private val IrBuilderWithScope.kIntZero get() = irConstInt(0)
|
private val IrBuilderWithScope.kIntZero get() = irConstInt(0)
|
||||||
private val IrBuilderWithScope.kIntOne get() = irConstInt(1)
|
private val IrBuilderWithScope.kIntOne get() = irConstInt(1)
|
||||||
|
|||||||
+2
@@ -37,6 +37,7 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
|||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.util.addFakeOverrides
|
||||||
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
||||||
import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer
|
import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer
|
||||||
import org.jetbrains.kotlin.serialization.KonanIr
|
import org.jetbrains.kotlin.serialization.KonanIr
|
||||||
@@ -1057,6 +1058,7 @@ internal class IrDeserializer(val context: Context,
|
|||||||
val clazz = IrClassImpl(start, end, origin, descriptor, members)
|
val clazz = IrClassImpl(start, end, origin, descriptor, members)
|
||||||
|
|
||||||
clazz.createParameterDeclarations()
|
clazz.createParameterDeclarations()
|
||||||
|
clazz.addFakeOverrides()
|
||||||
|
|
||||||
return clazz
|
return clazz
|
||||||
|
|
||||||
|
|||||||
-1
@@ -35,7 +35,6 @@ import org.jetbrains.kotlin.backend.konan.PhaseManager
|
|||||||
import org.jetbrains.kotlin.backend.konan.KonanPhase
|
import org.jetbrains.kotlin.backend.konan.KonanPhase
|
||||||
import org.jetbrains.kotlin.serialization.MutableTypeTable
|
import org.jetbrains.kotlin.serialization.MutableTypeTable
|
||||||
import org.jetbrains.kotlin.serialization.KonanLinkData
|
import org.jetbrains.kotlin.serialization.KonanLinkData
|
||||||
import org.jetbrains.kotlin.backend.common.validateIrFunction
|
|
||||||
|
|
||||||
internal class DeserializerDriver(val context: Context) {
|
internal class DeserializerDriver(val context: Context) {
|
||||||
|
|
||||||
|
|||||||
+13
-57
@@ -16,33 +16,17 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.builders
|
package org.jetbrains.kotlin.ir.builders
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.backend.common.descriptors.substitute
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrLoop
|
import org.jetbrains.kotlin.ir.expressions.IrLoop
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.util.defaultType
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
|
||||||
|
|
||||||
inline fun IrBuilderWithScope.irLetSequence(
|
|
||||||
value: IrExpression,
|
|
||||||
nameHint: String? = null,
|
|
||||||
startOffset: Int = this.startOffset,
|
|
||||||
endOffset: Int = this.endOffset,
|
|
||||||
origin: IrStatementOrigin? = null,
|
|
||||||
resultType: KotlinType? = null,
|
|
||||||
body: IrBlockBuilder.(VariableDescriptor) -> Unit
|
|
||||||
): IrExpression = irBlock(startOffset, endOffset, origin, resultType) {
|
|
||||||
val irTemporary = defineTemporary(value, nameHint)
|
|
||||||
this.body(irTemporary)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun IrBuilderWithScope.irWhile(origin: IrStatementOrigin? = null) =
|
fun IrBuilderWithScope.irWhile(origin: IrStatementOrigin? = null) =
|
||||||
IrWhileLoopImpl(startOffset, endOffset, context.builtIns.unitType, origin)
|
IrWhileLoopImpl(startOffset, endOffset, context.builtIns.unitType, origin)
|
||||||
@@ -57,46 +41,18 @@ fun IrBuilderWithScope.irTrue() = IrConstImpl.boolean(startOffset, endOffset, co
|
|||||||
|
|
||||||
fun IrBuilderWithScope.irFalse() = IrConstImpl.boolean(startOffset, endOffset, context.builtIns.booleanType, false)
|
fun IrBuilderWithScope.irFalse() = IrConstImpl.boolean(startOffset, endOffset, context.builtIns.booleanType, false)
|
||||||
|
|
||||||
@Deprecated("Creates unbound symbol")
|
|
||||||
fun IrBuilderWithScope.irGet(value: ValueDescriptor) =
|
|
||||||
IrGetValueImpl(startOffset, endOffset, value)
|
|
||||||
|
|
||||||
@Deprecated("Creates unbound symbol")
|
|
||||||
fun IrBuilderWithScope.irGet(receiver: IrExpression?, property: PropertyDescriptor): IrCall =
|
|
||||||
IrCallImpl(startOffset, endOffset, property.getter!!).apply {
|
|
||||||
dispatchReceiver = receiver
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated("Creates unbound symbol")
|
|
||||||
fun IrBuilderWithScope.irThis() =
|
|
||||||
scope.classOwner().let { classOwner ->
|
|
||||||
IrGetValueImpl(startOffset, endOffset, classOwner.thisAsReceiverParameter)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated("Creates unbound symbol")
|
|
||||||
fun IrBuilderWithScope.irSetVar(variable: VariableDescriptor, value: IrExpression) =
|
|
||||||
IrSetVariableImpl(startOffset, endOffset, variable, value, IrStatementOrigin.EQ)
|
|
||||||
|
|
||||||
@Deprecated("Creates unbound symbol")
|
|
||||||
fun IrBuilderWithScope.irCall(descriptor: FunctionDescriptor): IrCallImpl {
|
|
||||||
return IrCallImpl(this.startOffset, this.endOffset, descriptor)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun IrBuilderWithScope.irCall(symbol: IrFunctionSymbol): IrCallImpl {
|
fun IrBuilderWithScope.irCall(symbol: IrFunctionSymbol): IrCallImpl {
|
||||||
return IrCallImpl(this.startOffset, this.endOffset, symbol)
|
return IrCallImpl(this.startOffset, this.endOffset, symbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("Creates unbound symbol")
|
fun IrBuilderWithScope.irCall(symbol: IrFunctionSymbol, typeArguments: Map<TypeParameterDescriptor, KotlinType>) =
|
||||||
fun IrBuilderWithScope.irCall(
|
IrCallImpl(this.startOffset, this.endOffset, symbol, symbol.descriptor.substitute(typeArguments), typeArguments)
|
||||||
callee: FunctionDescriptor,
|
|
||||||
typeArguments: Map<TypeParameterDescriptor, KotlinType>
|
|
||||||
): IrCallImpl {
|
|
||||||
val substitutionContext = typeArguments.map { (typeParameter, typeArgument) ->
|
|
||||||
typeParameter.typeConstructor to TypeProjectionImpl(typeArgument)
|
|
||||||
}.toMap()
|
|
||||||
|
|
||||||
val substitutor = TypeSubstitutor.create(substitutionContext)
|
fun IrBuilderWithScope.irCall(symbol: IrFunctionSymbol, typeArguments: List<KotlinType>) =
|
||||||
val substitutedCallee = callee.substitute(substitutor)!!
|
irCall(symbol, symbol.descriptor.typeParameters.zip(typeArguments).toMap())
|
||||||
|
|
||||||
return IrCallImpl(this.startOffset, this.endOffset, substitutedCallee, typeArguments)
|
fun IrBuilderWithScope.irGetObject(classSymbol: IrClassSymbol) =
|
||||||
}
|
IrGetObjectValueImpl(startOffset, endOffset, classSymbol.owner.defaultType, classSymbol)
|
||||||
|
|
||||||
|
fun IrBuilderWithScope.irGetField(receiver: IrExpression?, symbol: IrFieldSymbol) =
|
||||||
|
IrGetFieldImpl(startOffset, endOffset, symbol, receiver)
|
||||||
+44
-71
@@ -16,20 +16,19 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.util
|
package org.jetbrains.kotlin.ir.util
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.konan.util.atMostOne
|
||||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.impl.IrPropertyImpl
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.*
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||||
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
||||||
@@ -175,6 +174,35 @@ fun IrClass.createParameterDeclarations() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun IrClass.addFakeOverrides() {
|
||||||
|
|
||||||
|
val startOffset = this.startOffset
|
||||||
|
val endOffset = this.endOffset
|
||||||
|
|
||||||
|
fun FunctionDescriptor.createFunction(): IrFunction = IrFunctionImpl(
|
||||||
|
startOffset, endOffset,
|
||||||
|
IrDeclarationOrigin.FAKE_OVERRIDE, this
|
||||||
|
).apply {
|
||||||
|
createParameterDeclarations()
|
||||||
|
}
|
||||||
|
|
||||||
|
descriptor.unsubstitutedMemberScope.getContributedDescriptors()
|
||||||
|
.filterIsInstance<CallableMemberDescriptor>()
|
||||||
|
.filter { it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE }
|
||||||
|
.mapTo(this.declarations) {
|
||||||
|
when (it) {
|
||||||
|
is FunctionDescriptor -> it.createFunction()
|
||||||
|
is PropertyDescriptor ->
|
||||||
|
IrPropertyImpl(startOffset, endOffset, IrDeclarationOrigin.FAKE_OVERRIDE, it).apply {
|
||||||
|
// TODO: add field if getter is missing?
|
||||||
|
getter = it.getter?.createFunction()
|
||||||
|
setter = it.setter?.createFunction()
|
||||||
|
}
|
||||||
|
else -> TODO(it.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun IrElement.innerStartOffset(descriptor: DeclarationDescriptorWithSource): Int =
|
private fun IrElement.innerStartOffset(descriptor: DeclarationDescriptorWithSource): Int =
|
||||||
descriptor.startOffset ?: this.startOffset
|
descriptor.startOffset ?: this.startOffset
|
||||||
|
|
||||||
@@ -193,6 +221,16 @@ val IrClassSymbol.functions: Sequence<IrSimpleFunctionSymbol>
|
|||||||
val IrClassSymbol.constructors: Sequence<IrConstructorSymbol>
|
val IrClassSymbol.constructors: Sequence<IrConstructorSymbol>
|
||||||
get() = this.owner.declarations.asSequence().filterIsInstance<IrConstructor>().map { it.symbol }
|
get() = this.owner.declarations.asSequence().filterIsInstance<IrConstructor>().map { it.symbol }
|
||||||
|
|
||||||
|
private fun IrClassSymbol.getPropertyDeclaration(name: String) =
|
||||||
|
this.owner.declarations.filterIsInstance<IrProperty>()
|
||||||
|
.atMostOne { it.descriptor.name == Name.identifier(name) }
|
||||||
|
|
||||||
|
fun IrClassSymbol.getPropertyGetter(name: String): IrFunctionSymbol? =
|
||||||
|
this.getPropertyDeclaration(name)?.getter?.symbol
|
||||||
|
|
||||||
|
fun IrClassSymbol.getPropertySetter(name: String): IrFunctionSymbol? =
|
||||||
|
this.getPropertyDeclaration(name)?.setter?.symbol
|
||||||
|
|
||||||
val IrFunction.explicitParameters: List<IrValueParameterSymbol>
|
val IrFunction.explicitParameters: List<IrValueParameterSymbol>
|
||||||
get() = (listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters).map { it.symbol }
|
get() = (listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters).map { it.symbol }
|
||||||
|
|
||||||
@@ -201,68 +239,3 @@ val IrValueParameter.type: KotlinType
|
|||||||
|
|
||||||
val IrClass.defaultType: KotlinType
|
val IrClass.defaultType: KotlinType
|
||||||
get() = this.descriptor.defaultType
|
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()}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
+1
-1
@@ -24,5 +24,5 @@ testDataVersion=1067176:id
|
|||||||
kotlinCompilerRepo=http://dl.bintray.com/jetbrains/kotlin-native-dependencies
|
kotlinCompilerRepo=http://dl.bintray.com/jetbrains/kotlin-native-dependencies
|
||||||
#kotlinCompilerRepo=http://oss.sonatype.org/content/repositories/snapshots
|
#kotlinCompilerRepo=http://oss.sonatype.org/content/repositories/snapshots
|
||||||
#kotlinCompilerRepo=http://dl.bintray.com/kotlin/kotlin-dev
|
#kotlinCompilerRepo=http://dl.bintray.com/kotlin/kotlin-dev
|
||||||
kotlinCompilerModule=org.jetbrains.kotlin:kotlin-compiler:1.1-20170519.065155-538
|
kotlinCompilerModule=org.jetbrains.kotlin:kotlin-compiler:1.1-20170521.012435-545
|
||||||
konanVersion=0.2
|
konanVersion=0.2
|
||||||
|
|||||||
Reference in New Issue
Block a user