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 =
|
||||
this.useAsValue(parameter)
|
||||
|
||||
protected open fun IrExpression.useAsDispatchReceiver(function: CallableDescriptor): IrExpression =
|
||||
this.useAsArgument(function.dispatchReceiverParameter!!)
|
||||
protected open fun IrExpression.useAsDispatchReceiver(expression: IrMemberAccessExpression): IrExpression =
|
||||
this.useAsArgument(expression.descriptor.dispatchReceiverParameter!!)
|
||||
|
||||
protected open fun IrExpression.useAsExtensionReceiver(function: CallableDescriptor): IrExpression =
|
||||
this.useAsArgument(function.extensionReceiverParameter!!)
|
||||
protected open fun IrExpression.useAsExtensionReceiver(expression: IrMemberAccessExpression): IrExpression =
|
||||
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)
|
||||
|
||||
protected open fun IrExpression.useForVariable(variable: VariableDescriptor): IrExpression =
|
||||
@@ -81,12 +82,12 @@ abstract class AbstractValueUsageTransformer(val builtIns: KotlinBuiltIns): IrEl
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
with(expression) {
|
||||
dispatchReceiver = dispatchReceiver?.useAsDispatchReceiver(descriptor)
|
||||
extensionReceiver = extensionReceiver?.useAsExtensionReceiver(descriptor)
|
||||
dispatchReceiver = dispatchReceiver?.useAsDispatchReceiver(expression)
|
||||
extensionReceiver = extensionReceiver?.useAsExtensionReceiver(expression)
|
||||
for (index in descriptor.valueParameters.indices) {
|
||||
val argument = getValueArgument(index) ?: continue
|
||||
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 ->
|
||||
val defaultValue = declaration.getDefault(parameter)
|
||||
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
|
||||
|
||||
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.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
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>) {
|
||||
super.visitConst(expression)
|
||||
|
||||
@@ -110,6 +120,8 @@ class CheckIrElementVisitor(val builtIns: KotlinBuiltIns, val reportError: Repor
|
||||
} else {
|
||||
expression.ensureTypeIs(returnType)
|
||||
}
|
||||
|
||||
expression.superQualifierSymbol?.ensureBound(expression)
|
||||
}
|
||||
|
||||
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) {
|
||||
@@ -128,6 +140,7 @@ class CheckIrElementVisitor(val builtIns: KotlinBuiltIns, val reportError: Repor
|
||||
super.visitInstanceInitializerCall(expression)
|
||||
|
||||
expression.ensureTypeIs(builtIns.unitType)
|
||||
expression.classSymbol.ensureBound(expression)
|
||||
}
|
||||
|
||||
override fun visitTypeOperator(expression: IrTypeOperatorCall) {
|
||||
@@ -173,6 +186,7 @@ class CheckIrElementVisitor(val builtIns: KotlinBuiltIns, val reportError: Repor
|
||||
super.visitReturn(expression)
|
||||
|
||||
expression.ensureTypeIs(builtIns.nothingType)
|
||||
expression.returnTargetSymbol.ensureBound(expression)
|
||||
}
|
||||
|
||||
override fun visitThrow(expression: IrThrow) {
|
||||
@@ -180,4 +194,60 @@ class CheckIrElementVisitor(val builtIns: KotlinBuiltIns, val reportError: Repor
|
||||
|
||||
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
|
||||
|
||||
import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlock
|
||||
import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlockImpl
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.backend.konan.ir.DeepCopyKonanIrTreeWithSymbols
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrSetVariableImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.util.DeepCopyIrTree
|
||||
import org.jetbrains.kotlin.ir.util.DeepCopyIrTreeWithSymbols
|
||||
import org.jetbrains.kotlin.ir.expressions.IrLoop
|
||||
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
|
||||
|
||||
/**
|
||||
* Copies IR tree with descriptors of all declarations inside;
|
||||
* updates the references to these declarations.
|
||||
*/
|
||||
@Deprecated("Creates unbound symbols")
|
||||
open class DeepCopyIrTreeWithDeclarations : DeepCopyIrTree() {
|
||||
|
||||
private fun DeclarationDescriptor.notSupported(): Nothing = TODO("${this}")
|
||||
|
||||
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(
|
||||
fun IrElement.deepCopyWithVariablesImpl(): IrElement {
|
||||
val descriptorsRemapper = object : DescriptorsRemapper {
|
||||
override fun remapDeclaredVariable(descriptor: VariableDescriptor) = LocalVariableDescriptor(
|
||||
/* containingDeclaration = */ descriptor.containingDeclaration,
|
||||
/* annotations = */ descriptor.annotations,
|
||||
/* name = */ descriptor.name,
|
||||
@@ -72,103 +36,19 @@ open class DeepCopyIrTreeWithDeclarations : DeepCopyIrTree() {
|
||||
/* isDelegated = */ false,
|
||||
/* 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,
|
||||
// so it is correct to map only references whose descriptors have copies.
|
||||
// However such approach can be incorrect when copying functions, classes etc.
|
||||
val symbolsRemapper = DeepCopySymbolsRemapper(descriptorsRemapper)
|
||||
acceptVoid(symbolsRemapper)
|
||||
|
||||
override fun mapValueReference(descriptor: ValueDescriptor) =
|
||||
copiedVariables[descriptor] ?: descriptor
|
||||
|
||||
override fun mapVariableReference(descriptor: VariableDescriptor) =
|
||||
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
|
||||
return this.transform(
|
||||
object : DeepCopyKonanIrTreeWithSymbols(symbolsRemapper) {
|
||||
override fun getNonTransformedLoop(irLoop: IrLoop): IrLoop {
|
||||
return irLoop
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
},
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
inline fun <reified T : IrElement> T.deepCopyWithVariables(): T =
|
||||
|
||||
+1
-3
@@ -86,9 +86,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: DeclarationDe
|
||||
val contributedDescriptors = oldDescriptor.unsubstitutedMemberScope
|
||||
.getContributedDescriptors()
|
||||
.map {
|
||||
if (it is CallableMemberDescriptor && it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE)
|
||||
it
|
||||
else descriptorSubstituteMap[it]!!
|
||||
descriptorSubstituteMap[it]!!
|
||||
}
|
||||
newDescriptor.initialize(
|
||||
SimpleMemberScope(contributedDescriptors),
|
||||
|
||||
+1
-153
@@ -16,21 +16,12 @@
|
||||
|
||||
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.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
|
||||
fun validateIrFunction(context: BackendContext, irFunction: IrFunction) {
|
||||
val visitor = IrValidator(context, false)
|
||||
irFunction.acceptVoid(visitor)
|
||||
}
|
||||
|
||||
fun validateIrFile(context: BackendContext, irFile: IrFile) {
|
||||
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.
|
||||
irModule.acceptVoid(visitor)
|
||||
|
||||
// TODO: investigate and re-enable
|
||||
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)
|
||||
}
|
||||
}
|
||||
})
|
||||
// TODO: also check that all referenced symbol targets are reachable.
|
||||
}
|
||||
|
||||
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.
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
val foundDeclarations = Declarations()
|
||||
|
||||
val builtIns = context.builtIns
|
||||
lateinit var currentFile: IrFile
|
||||
|
||||
@@ -200,25 +69,4 @@ private class IrValidator(val context: BackendContext, performHeavyValidations:
|
||||
element.acceptVoid(elementChecker)
|
||||
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
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 FunctionDescriptor.substitute(vararg types: KotlinType): FunctionDescriptor {
|
||||
@@ -83,6 +69,13 @@ fun FunctionDescriptor.substitute(vararg types: KotlinType): FunctionDescriptor
|
||||
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 {
|
||||
val typeSubstitutor = TypeSubstitutor.create(
|
||||
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.builders.*
|
||||
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.IrExpression
|
||||
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 DeclarationIrBuilder : IrBuilderWithScope {
|
||||
|
||||
constructor(
|
||||
backendContext: BackendContext,
|
||||
symbol: IrSymbol,
|
||||
startOffset: Int = UNDEFINED_OFFSET,
|
||||
endOffset: Int = UNDEFINED_OFFSET
|
||||
) : super(
|
||||
IrLoweringContext(backendContext),
|
||||
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)
|
||||
class DeclarationIrBuilder(
|
||||
backendContext: BackendContext,
|
||||
symbol: IrSymbol,
|
||||
startOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET
|
||||
) : IrBuilderWithScope(
|
||||
IrLoweringContext(backendContext),
|
||||
Scope(symbol),
|
||||
startOffset,
|
||||
endOffset
|
||||
)
|
||||
|
||||
fun BackendContext.createIrBuilder(symbol: IrSymbol,
|
||||
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) =
|
||||
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) =
|
||||
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) =
|
||||
primitiveOp1(startOffset, endOffset, context.irBuiltIns.booleanNotSymbol, IrStatementOrigin.EXCL, arg)
|
||||
|
||||
@@ -139,30 +99,21 @@ fun IrBuilderWithScope.irImplicitCoercionToUnit(arg: IrExpression) =
|
||||
IrTypeOperatorCallImpl(startOffset, endOffset, context.builtIns.unitType,
|
||||
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) =
|
||||
IrGetFieldImpl(startOffset, endOffset, symbol, receiver)
|
||||
|
||||
fun IrBuilderWithScope.irSetField(receiver: IrExpression, symbol: IrFieldSymbol, value: IrExpression) =
|
||||
IrSetFieldImpl(startOffset, endOffset, symbol, receiver, value)
|
||||
|
||||
@Deprecated("Creates unbound symbol")
|
||||
open class IrBuildingTransformer(private val context: BackendContext) : IrElementTransformerVoid() {
|
||||
private var currentBuilder: IrBuilderWithScope? = null
|
||||
|
||||
protected val builder: IrBuilderWithScope
|
||||
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
|
||||
currentBuilder = context.createIrBuilder(declarationDescriptor)
|
||||
currentBuilder = context.createIrBuilder(symbol)
|
||||
return try {
|
||||
block()
|
||||
} finally {
|
||||
@@ -171,20 +122,20 @@ open class IrBuildingTransformer(private val context: BackendContext) : IrElemen
|
||||
}
|
||||
|
||||
override fun visitFunction(declaration: IrFunction): IrStatement {
|
||||
withBuilder(declaration.descriptor) {
|
||||
withBuilder(declaration.symbol) {
|
||||
return super.visitFunction(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitField(declaration: IrField): IrStatement {
|
||||
withBuilder(declaration.descriptor) {
|
||||
withBuilder(declaration.symbol) {
|
||||
// Transforms initializer:
|
||||
return super.visitField(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer): IrStatement {
|
||||
withBuilder(declaration.descriptor) {
|
||||
withBuilder(declaration.symbol) {
|
||||
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.
|
||||
*
|
||||
* 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 {
|
||||
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.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
||||
import org.jetbrains.kotlin.ir.util.endOffsetOrUndefined
|
||||
import org.jetbrains.kotlin.ir.util.functions
|
||||
import org.jetbrains.kotlin.ir.util.startOffsetOrUndefined
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
@@ -75,6 +72,7 @@ internal class EnumSpecialDeclarationsFactory(val context: Context) {
|
||||
implObjectDescriptor.initialize(memberScope, setOf(constructorDescriptor), constructorDescriptor)
|
||||
val implObject = IrClassImpl(startOffset, endOffset, IrDeclarationOrigin.DEFINED, implObjectDescriptor).apply {
|
||||
createParameterDeclarations()
|
||||
addFakeOverrides()
|
||||
}
|
||||
|
||||
val (itemGetterSymbol, itemGetterDescriptor) = getEnumItemGetter(enumClassDescriptor)
|
||||
|
||||
-46
@@ -16,17 +16,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.konan
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
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.replace
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
|
||||
private val cPointerName = "CPointer"
|
||||
private val nativePointedName = "NativePointed"
|
||||
@@ -67,53 +62,12 @@ internal class InteropBuiltIns(builtIns: KonanBuiltIns) {
|
||||
TypeUtils.getClassDescriptor(extensionReceiverParameter.type) == nativePointed
|
||||
}
|
||||
|
||||
val memberAt = packageScope.getContributedFunctions("memberAt").single()
|
||||
|
||||
val interpretNullablePointed = packageScope.getContributedFunctions("interpretNullablePointed").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 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
|
||||
|
||||
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.lower.*
|
||||
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.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.util.IrSymbolBindingChecker
|
||||
import org.jetbrains.kotlin.ir.util.replaceUnboundSymbols
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
|
||||
internal class KonanLower(val context: Context) {
|
||||
|
||||
@@ -49,9 +47,14 @@ internal class KonanLower(val context: Context) {
|
||||
// Inlining must be run before other phases.
|
||||
phaser.phase(KonanPhase.LOWER_INLINE) {
|
||||
FunctionInlining(context).inline(irModule)
|
||||
irModule.replaceUnboundSymbols(context)
|
||||
irModule.checkSymbolsBound()
|
||||
}
|
||||
|
||||
phaser.phase(KonanPhase.LOWER_INTEROP_PART1) {
|
||||
irModule.files.forEach(InteropLoweringPart1(context)::lower)
|
||||
}
|
||||
|
||||
irModule.replaceUnboundSymbols(context)
|
||||
validateIrModule(context, irModule)
|
||||
}
|
||||
|
||||
fun lowerFile(irFile: IrFile) {
|
||||
@@ -59,31 +62,24 @@ internal class KonanLower(val context: Context) {
|
||||
|
||||
phaser.phase(KonanPhase.LOWER_STRING_CONCAT) {
|
||||
StringConcatenationLowering(context).lower(irFile)
|
||||
irFile.checkSymbolsBound()
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_ENUMS) {
|
||||
EnumClassLowering(context).run(irFile)
|
||||
irFile.checkSymbolsBound()
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_INITIALIZERS) {
|
||||
InitializersLowering(context).runOnFilePostfix(irFile)
|
||||
irFile.checkSymbolsBound()
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_SHARED_VARIABLES) {
|
||||
SharedVariablesLowering(context).runOnFilePostfix(irFile)
|
||||
irFile.checkSymbolsBound()
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_DELEGATION) {
|
||||
PropertyDelegationLowering(context).lower(irFile)
|
||||
irFile.checkSymbolsBound()
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_LOCAL_FUNCTIONS) {
|
||||
LocalDeclarationsLowering(context).runOnFilePostfix(irFile)
|
||||
irFile.checkSymbolsBound()
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_TAILREC) {
|
||||
TailrecLowering(context).runOnFilePostfix(irFile)
|
||||
irFile.checkSymbolsBound()
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_FINALLY) {
|
||||
FinallyBlocksLowering(context).runOnFilePostfix(irFile)
|
||||
@@ -101,8 +97,8 @@ internal class KonanLower(val context: Context) {
|
||||
phaser.phase(KonanPhase.LOWER_INNER_CLASSES) {
|
||||
InnerClassLowering(context).runOnFilePostfix(irFile)
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_INTEROP) {
|
||||
InteropLowering(context).lower(irFile)
|
||||
phaser.phase(KonanPhase.LOWER_INTEROP_PART2) {
|
||||
InteropLoweringPart2(context).lower(irFile)
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_CALLABLES) {
|
||||
CallableReferenceLowering(context).runOnFilePostfix(irFile)
|
||||
@@ -118,7 +114,6 @@ internal class KonanLower(val context: Context) {
|
||||
}
|
||||
phaser.phase(KonanPhase.BRIDGES_BUILDING) {
|
||||
BridgesBuilding(context).runOnFilePostfix(irFile)
|
||||
DirectBridgesCallsLowering(context).runOnFilePostfix(irFile)
|
||||
}
|
||||
phaser.phase(KonanPhase.AUTOBOX) {
|
||||
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("Functions inlining", LOWER_INLINE_CONSTRUCTORS),
|
||||
/* ... ... ... */ DESERIALIZER("Deserialize inline bodies"),
|
||||
/* ... ... */ LOWER_INTEROP_PART1("Interop lowering, part 1", LOWER_INLINE),
|
||||
/* ... ... */ LOWER_ENUMS("Enum classes lowering"),
|
||||
/* ... ... */ LOWER_DELEGATION("Delegation lowering"),
|
||||
/* ... ... */ LOWER_INITIALIZERS("Initializers lowering", LOWER_ENUMS),
|
||||
/* ... ... */ LOWER_SHARED_VARIABLES("Shared Variable Lowering", LOWER_INITIALIZERS),
|
||||
/* ... ... */ LOWER_LOCAL_FUNCTIONS("Local Function Lowering", LOWER_SHARED_VARIABLES),
|
||||
/* ... ... */ LOWER_INTEROP("Interop lowering", LOWER_LOCAL_FUNCTIONS),
|
||||
/* ... ... */ LOWER_CALLABLES("Callable references Lowering", LOWER_INTEROP, LOWER_DELEGATION, LOWER_LOCAL_FUNCTIONS),
|
||||
/* ... ... */ LOWER_INTEROP_PART2("Interop lowering, part 2", LOWER_LOCAL_FUNCTIONS),
|
||||
/* ... ... */ LOWER_CALLABLES("Callable references Lowering", LOWER_INTEROP_PART2, LOWER_DELEGATION, LOWER_LOCAL_FUNCTIONS),
|
||||
/* ... ... */ LOWER_VARARG("Vararg lowering", LOWER_CALLABLES),
|
||||
/* ... ... */ LOWER_TAILREC("tailrec lowering", LOWER_LOCAL_FUNCTIONS),
|
||||
/* ... ... */ 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.KonanBuiltIns
|
||||
import org.jetbrains.kotlin.backend.konan.ValueType
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalClass
|
||||
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.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
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.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi2ir.generators.SymbolTable
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
// This is what Context collects about IR.
|
||||
internal class Ir(val context: Context, val irModule: IrModuleFragment) {
|
||||
val propertiesWithBackingFields = mutableSetOf<PropertyDescriptor>()
|
||||
|
||||
val defaultParameterDescriptorsCache = mutableMapOf<FunctionDescriptor, FunctionDescriptor>()
|
||||
val defaultParameterDeclarationsCache = mutableMapOf<FunctionDescriptor, IrFunction>()
|
||||
|
||||
val originalModuleIndex = ModuleIndex(irModule)
|
||||
|
||||
@@ -67,13 +73,31 @@ internal class Symbols(val context: Context, val symbolTable: SymbolTable) {
|
||||
val ThrowTypeCastException = symbolTable.referenceSimpleFunction(
|
||||
builtIns.getKonanInternalFunctions("ThrowTypeCastException").single())
|
||||
|
||||
val ThrowUninitializedPropertyAccessException = symbolTable.referenceSimpleFunction(
|
||||
builtIns.getKonanInternalFunctions("ThrowUninitializedPropertyAccessException").single()
|
||||
)
|
||||
|
||||
val stringBuilder = symbolTable.referenceClass(
|
||||
builtInsPackage("kotlin", "text").getContributedClassifier(
|
||||
Name.identifier("StringBuilder"), NoLookupLocation.FROM_BACKEND
|
||||
) as ClassDescriptor
|
||||
)
|
||||
|
||||
val defaultArgumentMarker = symbolTable.referenceClass(
|
||||
builtIns.konanInternal.getContributedClassifier(
|
||||
Name.identifier("DefaultArgumentMarker"), NoLookupLocation.FROM_BACKEND
|
||||
) as ClassDescriptor
|
||||
)
|
||||
|
||||
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(
|
||||
builtInsPackage("kotlin").getContributedFunctions(
|
||||
@@ -83,12 +107,86 @@ internal class Symbols(val context: Context, val symbolTable: SymbolTable) {
|
||||
|
||||
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(
|
||||
builtIns.getKonanInternalFunctions("valuesForEnum").single())
|
||||
|
||||
val valueOfForEnum = symbolTable.referenceSimpleFunction(
|
||||
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 kProperty1Impl = symbolTable.referenceClass(context.reflectionTypes.kProperty1Impl)
|
||||
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
|
||||
|
||||
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,
|
||||
descriptor: FunctionDescriptor, origin: IrStatementOrigin? = null) :
|
||||
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.descriptors.isSuspend
|
||||
import org.jetbrains.kotlin.backend.konan.*
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||
import org.jetbrains.kotlin.backend.konan.util.atMostOne
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalClass
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.target
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
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.impl.IrCallImpl
|
||||
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.render
|
||||
import org.jetbrains.kotlin.ir.util.type
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
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) {
|
||||
|
||||
val symbols = context.ir.symbols
|
||||
|
||||
// TODO: should we handle the cases when expression 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 {
|
||||
val interop = context.interopBuiltIns
|
||||
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) {
|
||||
is IrCall -> {
|
||||
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
|
||||
|
||||
@@ -157,17 +162,32 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr
|
||||
return this.adaptIfNecessary(actualType, type)
|
||||
}
|
||||
|
||||
override fun IrExpression.useAsDispatchReceiver(function: CallableDescriptor): IrExpression {
|
||||
return this.useAsArgument(function.original.dispatchReceiverParameter!!)
|
||||
private val IrMemberAccessExpression.target: CallableDescriptor get() = when (this) {
|
||||
is IrCall -> this.callTarget
|
||||
is IrDelegatingConstructorCall -> this.descriptor.original
|
||||
else -> TODO(this.render())
|
||||
}
|
||||
|
||||
override fun IrExpression.useAsExtensionReceiver(function: CallableDescriptor): IrExpression {
|
||||
return this.useAsArgument(function.original.extensionReceiverParameter!!)
|
||||
private val IrCall.callTarget: FunctionDescriptor
|
||||
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 {
|
||||
val function = parameter.containingDeclaration
|
||||
return this.useAsArgument(function.original.valueParameters[parameter.index])
|
||||
override fun IrExpression.useAsExtensionReceiver(expression: IrMemberAccessExpression): IrExpression {
|
||||
return this.useAsArgument(expression.target.extensionReceiverParameter!!)
|
||||
}
|
||||
|
||||
override fun IrExpression.useAsValueArgument(expression: IrMemberAccessExpression,
|
||||
parameter: ValueParameterDescriptor): IrExpression {
|
||||
|
||||
return this.useAsArgument(expression.target.valueParameters[parameter.index])
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
private fun IrExpression.box(valueType: ValueType): IrExpression {
|
||||
val boxFunctionName = "box${valueType.shortName}"
|
||||
val boxFunction = context.builtIns.getKonanInternalFunctions(boxFunctionName).singleOrNull() ?:
|
||||
TODO(valueType.toString())
|
||||
val boxFunction = symbols.boxFunctions[valueType]!!
|
||||
|
||||
return IrCallImpl(startOffset, endOffset, boxFunction).apply {
|
||||
putValueArgument(0, this@box)
|
||||
@@ -221,22 +239,16 @@ private class AutoboxingTransformer(val context: Context) : AbstractValueUsageTr
|
||||
}
|
||||
|
||||
private fun IrExpression.unbox(valueType: ValueType): IrExpression {
|
||||
val unboxFunctionName = "unbox${valueType.shortName}"
|
||||
|
||||
context.builtIns.getKonanInternalFunctions(unboxFunctionName).atMostOne()?.let {
|
||||
symbols.unboxFunctions[valueType]?.let {
|
||||
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)
|
||||
}
|
||||
|
||||
val boxGetter = getBoxType(valueType)
|
||||
.memberScope.getContributedDescriptors()
|
||||
.filterIsInstance<PropertyDescriptor>()
|
||||
.single { it.name.asString() == "value" }
|
||||
.getter!!
|
||||
val boxGetter = symbols.boxClasses[valueType]!!.getPropertyGetter("value")!!
|
||||
|
||||
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.
|
||||
}
|
||||
|
||||
|
||||
+31
-62
@@ -16,13 +16,11 @@
|
||||
|
||||
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.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irBlockBody
|
||||
import org.jetbrains.kotlin.backend.common.lower.irIfThen
|
||||
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.builtins.KotlinBuiltIns
|
||||
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.expressions.*
|
||||
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.type
|
||||
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.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 {
|
||||
|
||||
private fun IrBuilderWithScope.returnIfBadType(value: IrExpression,
|
||||
@@ -162,30 +121,31 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
|
||||
private object DECLARATION_ORIGIN_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) {
|
||||
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 irBuilder = context.createIrBuilder(bridgeDescriptor, irClass.startOffset, irClass.endOffset)
|
||||
val irBuilder = context.createIrBuilder(bridge.symbol, irClass.startOffset, irClass.endOffset)
|
||||
irBuilder.run {
|
||||
val typeSafeBarrierDescription = BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor.overriddenDescriptor)
|
||||
if (typeSafeBarrierDescription != null) {
|
||||
val valueParameters = bridgeDescriptor.valueParameters
|
||||
val valueParameters = bridge.valueParameters
|
||||
for (i in valueParameters.indices) {
|
||||
if (!typeSafeBarrierDescription.checkParameter(i))
|
||||
continue
|
||||
val type = target.valueParameters[i].type
|
||||
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)
|
||||
irGet(valueParameters[2])
|
||||
irGet(valueParameters[2].symbol)
|
||||
else irConst(typeSafeBarrierDescription.defaultValue)
|
||||
)
|
||||
}
|
||||
@@ -193,22 +153,22 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
|
||||
}
|
||||
}
|
||||
|
||||
val delegatingCall = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, target,
|
||||
superQualifierDescriptor = target.containingDeclaration as ClassDescriptor /* Call non-virtually */
|
||||
val delegatingCall = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, targetSymbol, target,
|
||||
superQualifierSymbol = superQualifierSymbol /* Call non-virtually */
|
||||
).apply {
|
||||
val dispatchReceiverParameter = bridgeDescriptor.dispatchReceiverParameter
|
||||
val dispatchReceiverParameter = bridge.dispatchReceiverParameter
|
||||
if (dispatchReceiverParameter != null)
|
||||
dispatchReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, dispatchReceiverParameter)
|
||||
val extensionReceiverParameter = bridgeDescriptor.extensionReceiverParameter
|
||||
dispatchReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, dispatchReceiverParameter.symbol)
|
||||
val extensionReceiverParameter = bridge.extensionReceiverParameter
|
||||
if (extensionReceiverParameter != null)
|
||||
extensionReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, extensionReceiverParameter)
|
||||
bridgeDescriptor.valueParameters.forEach {
|
||||
this.putValueArgument(it.index, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, it))
|
||||
extensionReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, extensionReceiverParameter.symbol)
|
||||
bridge.valueParameters.forEachIndexed { index, parameter ->
|
||||
this.putValueArgument(index, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, parameter.symbol))
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
delegatingCall
|
||||
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.lower.*
|
||||
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.synthesizedName
|
||||
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.impl.IrConstructorSymbolImpl
|
||||
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.name.FqName
|
||||
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.ir.IrStatement
|
||||
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.backend.common.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.types.*
|
||||
|
||||
internal class CallableReferenceLowering(val context: Context): DeclarationContainerLoweringPass {
|
||||
@@ -122,7 +118,7 @@ internal class CallableReferenceLowering(val context: Context): DeclarationConta
|
||||
private val continuationClassDescriptor = coroutinesScope
|
||||
.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,
|
||||
val functionReference: IrFunctionReference) {
|
||||
@@ -137,7 +133,7 @@ internal class CallableReferenceLowering(val context: Context): DeclarationConta
|
||||
private lateinit var functionReferenceThis: IrValueParameterSymbol
|
||||
private lateinit var argumentToPropertiesMap: Map<ParameterDescriptor, IrFieldSymbol>
|
||||
|
||||
private val kFunctionImplClassDescriptor = context.builtIns.getKonanInternalClass("KFunctionImpl")
|
||||
private val kFunctionImplSymbol = context.ir.symbols.kFunctionImpl
|
||||
|
||||
fun build(): BuiltFunctionReference {
|
||||
val startOffset = functionReference.startOffset
|
||||
@@ -145,7 +141,7 @@ internal class CallableReferenceLowering(val context: Context): DeclarationConta
|
||||
|
||||
val returnType = functionDescriptor.returnType!!
|
||||
val superTypes = mutableListOf(
|
||||
kFunctionImplClassDescriptor.defaultType.replace(listOf(returnType))
|
||||
kFunctionImplSymbol.owner.defaultType.replace(listOf(returnType))
|
||||
)
|
||||
|
||||
val numberOfParameters = unboundFunctionParameters.size
|
||||
@@ -196,7 +192,7 @@ internal class CallableReferenceLowering(val context: Context): DeclarationConta
|
||||
suspendInvokeMethodBuilder = createInvokeMethodBuilder(suspendInvokeFunctionDescriptor)
|
||||
}
|
||||
|
||||
val inheritedKFunctionImpl = kFunctionImplClassDescriptor.unsubstitutedMemberScope
|
||||
val inheritedKFunctionImpl = kFunctionImplSymbol.descriptor.unsubstitutedMemberScope
|
||||
.getContributedDescriptors()
|
||||
.map { it.createFakeOverrideDescriptor(functionReferenceClassDescriptor) }
|
||||
.filterNotNull()
|
||||
@@ -206,6 +202,8 @@ internal class CallableReferenceLowering(val context: Context): DeclarationConta
|
||||
functionReferenceClassDescriptor.initialize(
|
||||
SimpleMemberScope(contributedDescriptors), setOf(constructorBuilder.symbol.descriptor), null)
|
||||
|
||||
functionReferenceClass.addFakeOverrides()
|
||||
|
||||
constructorBuilder.initialize()
|
||||
functionReferenceClass.declarations.add(constructorBuilder.ir)
|
||||
|
||||
@@ -223,7 +221,7 @@ internal class CallableReferenceLowering(val context: Context): DeclarationConta
|
||||
private fun createConstructorBuilder()
|
||||
= object : SymbolWithIrBuilder<IrConstructorSymbol, IrConstructor>() {
|
||||
|
||||
private val kFunctionImplConstructorDescriptor = kFunctionImplClassDescriptor.constructors.single()
|
||||
private val kFunctionImplConstructorSymbol = kFunctionImplSymbol.constructors.single()
|
||||
|
||||
override fun buildSymbol() = IrConstructorSymbolImpl(
|
||||
ClassConstructorDescriptorImpl.create(
|
||||
@@ -261,7 +259,8 @@ internal class CallableReferenceLowering(val context: Context): DeclarationConta
|
||||
createParameterDeclarations()
|
||||
|
||||
body = irBuilder.irBlockBody {
|
||||
+IrDelegatingConstructorCallImpl(startOffset, endOffset, kFunctionImplConstructorDescriptor).apply {
|
||||
+IrDelegatingConstructorCallImpl(startOffset, endOffset,
|
||||
kFunctionImplConstructorSymbol, kFunctionImplConstructorSymbol.descriptor).apply {
|
||||
val name = IrConstImpl(startOffset, endOffset, context.builtIns.stringType,
|
||||
IrConstKind.String, functionDescriptor.name.asString())
|
||||
putValueArgument(0, name)
|
||||
@@ -356,7 +355,8 @@ internal class CallableReferenceLowering(val context: Context): DeclarationConta
|
||||
else {
|
||||
if (ourSymbol.descriptor.isSuspend && unboundIndex == valueParameters.size)
|
||||
// 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
|
||||
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.irBlockBody
|
||||
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.ir.ir2string
|
||||
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.TypeParameterDescriptorImpl
|
||||
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.builders.*
|
||||
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.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
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.transformChildrenVoid
|
||||
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.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
class DefaultArgumentStubGenerator internal constructor(val context: Context): DeclarationContainerLoweringPass {
|
||||
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
|
||||
@@ -65,8 +62,7 @@ class DefaultArgumentStubGenerator internal constructor(val context: Context): D
|
||||
|
||||
}
|
||||
|
||||
object DECLARATION_ORIGIN_FUNCTION_FOR_DEFAULT_PARAMETER :
|
||||
IrDeclarationOriginImpl("DEFAULT_PARAMETER_EXTENT")
|
||||
private val symbols = context.ir.symbols
|
||||
|
||||
private fun lower(irFunction: IrFunction): List<IrFunction> {
|
||||
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")
|
||||
functionDescriptor.overriddenDescriptors.forEach { context.log{"DEFAULT-REPLACER: $it"} }
|
||||
if (bodies.isNotEmpty()) {
|
||||
val descriptor = functionDescriptor.generateDefaultsDescription(context)
|
||||
val newIrFunction = functionDescriptor.generateDefaultsFunction(context)
|
||||
val descriptor = newIrFunction.descriptor
|
||||
log("$functionDescriptor -> $descriptor")
|
||||
val builder = context.createIrBuilder(descriptor)
|
||||
val builder = context.createIrBuilder(newIrFunction.symbol)
|
||||
val body = builder.irBlockBody(irFunction) {
|
||||
val params = mutableListOf<VariableDescriptor>()
|
||||
val variables = mutableMapOf<ValueDescriptor, ValueDescriptor>()
|
||||
val params = mutableListOf<IrVariableSymbol>()
|
||||
val variables = mutableMapOf<ValueDescriptor, IrValueSymbol>()
|
||||
if (descriptor.extensionReceiverParameter != null) {
|
||||
variables[functionDescriptor.extensionReceiverParameter!!] = descriptor.extensionReceiverParameter!!
|
||||
variables[functionDescriptor.extensionReceiverParameter!!] =
|
||||
newIrFunction.extensionReceiverParameter!!.symbol
|
||||
}
|
||||
|
||||
for (valueParameter in functionDescriptor.valueParameters) {
|
||||
val parameterDescriptor = descriptor.valueParameters[valueParameter.index]
|
||||
val temporaryVariableDescriptor = scope.createTemporaryVariableDescriptor(parameterDescriptor)
|
||||
params.add(temporaryVariableDescriptor)
|
||||
variables.put(valueParameter, temporaryVariableDescriptor)
|
||||
val parameterSymbol = newIrFunction.valueParameters[valueParameter.index].symbol
|
||||
val temporaryVariableSymbol =
|
||||
IrVariableSymbolImpl(scope.createTemporaryVariableDescriptor(parameterSymbol.descriptor))
|
||||
params.add(temporaryVariableSymbol)
|
||||
variables.put(valueParameter, temporaryVariableSymbol)
|
||||
if (valueParameter.hasDefaultValue()) {
|
||||
val kIntAnd = valueParameter.builtIns.intType.memberScope
|
||||
.getContributedFunctions(OperatorNameConventions.AND, NoLookupLocation.FROM_BACKEND)
|
||||
.single()
|
||||
val kIntAnd = symbols.intAnd
|
||||
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)))
|
||||
}, irInt(0))
|
||||
val expressionBody = getDefaultParameterExpressionBody(irFunction, valueParameter)
|
||||
@@ -110,51 +107,45 @@ class DefaultArgumentStubGenerator internal constructor(val context: Context): D
|
||||
expressionBody.transformChildrenVoid(object:IrElementTransformerVoid() {
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression {
|
||||
log("GetValue: ${expression.descriptor}")
|
||||
val valueDescriptor = variables[expression.descriptor]
|
||||
return when (valueDescriptor) {
|
||||
is VariableDescriptor -> irGet(valueDescriptor)
|
||||
is ReceiverParameterDescriptor -> irGet(valueDescriptor)
|
||||
null -> expression
|
||||
else -> TODO("$valueDescriptor")
|
||||
}
|
||||
|
||||
val valueSymbol = variables[expression.descriptor] ?: return expression
|
||||
return irGet(valueSymbol)
|
||||
}
|
||||
})
|
||||
val variableInitialization = irIfThenElse(
|
||||
type = temporaryVariableDescriptor.type,
|
||||
type = temporaryVariableSymbol.descriptor.type,
|
||||
condition = condition,
|
||||
thenPart = expressionBody.expression,
|
||||
elsePart = irGet(parameterDescriptor))
|
||||
elsePart = irGet(parameterSymbol))
|
||||
+ scope.createTemporaryVariable(
|
||||
descriptor = temporaryVariableDescriptor,
|
||||
symbol = temporaryVariableSymbol,
|
||||
initializer = variableInitialization)
|
||||
/* Mapping calculated values with its origin variables. */
|
||||
} else {
|
||||
+ scope.createTemporaryVariable(
|
||||
descriptor = temporaryVariableDescriptor,
|
||||
initializer = irGet(parameterDescriptor))
|
||||
symbol = temporaryVariableSymbol,
|
||||
initializer = irGet(parameterSymbol))
|
||||
}
|
||||
}
|
||||
if (functionDescriptor is ClassConstructorDescriptor) {
|
||||
if (irFunction is IrConstructor) {
|
||||
+ IrDelegatingConstructorCallImpl(
|
||||
startOffset = irFunction.startOffset,
|
||||
endOffset = irFunction.endOffset,
|
||||
constructorDescriptor = functionDescriptor
|
||||
symbol = irFunction.symbol, descriptor = irFunction.symbol.descriptor
|
||||
).apply {
|
||||
params.forEachIndexed { i, variable ->
|
||||
putValueArgument(i, irGet(variable))
|
||||
}
|
||||
if (functionDescriptor.dispatchReceiverParameter != null) {
|
||||
dispatchReceiver = irThis()
|
||||
dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!.symbol)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
+irReturn(irCall(functionDescriptor).apply {
|
||||
+irReturn(irCall(irFunction.symbol).apply {
|
||||
if (functionDescriptor.dispatchReceiverParameter != null) {
|
||||
dispatchReceiver = irThis()
|
||||
dispatchReceiver = irGet(newIrFunction.dispatchReceiverParameter!!.symbol)
|
||||
}
|
||||
if (functionDescriptor.extensionReceiverParameter != null) {
|
||||
extensionReceiver = irGet(variables[functionDescriptor.extensionReceiverParameter!!] as ReceiverParameterDescriptor)
|
||||
extensionReceiver = irGet(variables[functionDescriptor.extensionReceiverParameter!!]!!)
|
||||
}
|
||||
params.forEachIndexed { i, 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 Scope.createTemporaryVariableDescriptor(parameterDescriptor: ValueParameterDescriptor?): VariableDescriptor =
|
||||
private fun Scope.createTemporaryVariableDescriptor(parameterDescriptor: ParameterDescriptor?): VariableDescriptor =
|
||||
IrTemporaryVariableDescriptorImpl(
|
||||
containingDeclaration = this.scopeOwner,
|
||||
name = parameterDescriptor!!.name.asString().synthesizedName,
|
||||
outType = parameterDescriptor.type,
|
||||
isMutable = false)
|
||||
|
||||
private fun Scope.createTemporaryVariable(descriptor: VariableDescriptor, initializer: IrExpression) =
|
||||
private fun Scope.createTemporaryVariable(symbol: IrVariableSymbol, initializer: IrExpression) =
|
||||
IrVariableImpl(
|
||||
startOffset = initializer.startOffset,
|
||||
endOffset = initializer.endOffset,
|
||||
origin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
|
||||
descriptor = descriptor,
|
||||
initializer = initializer)
|
||||
symbol = symbol).apply {
|
||||
|
||||
this.initializer = initializer
|
||||
}
|
||||
|
||||
private fun getDefaultParameterExpressionBody(irFunction: IrFunction, valueParameter: ValueParameterDescriptor):IrExpressionBody {
|
||||
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 }
|
||||
|
||||
@@ -237,11 +233,12 @@ class DefaultParameterInjector internal constructor(val context: Context): BodyL
|
||||
val argumentsCount = argumentCount(expression)
|
||||
if (argumentsCount == descriptor.valueParameters.size)
|
||||
return expression
|
||||
val (descriptorForCall, params) = parametersForCall(expression)
|
||||
val (symbolForCall, params) = parametersForCall(expression)
|
||||
return IrDelegatingConstructorCallImpl(
|
||||
startOffset = expression.startOffset,
|
||||
endOffset = expression.endOffset,
|
||||
constructorDescriptor = descriptorForCall as ClassConstructorDescriptor)
|
||||
symbol = symbolForCall as IrConstructorSymbol,
|
||||
descriptor = symbolForCall.descriptor)
|
||||
.apply {
|
||||
params.forEach {
|
||||
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 {
|
||||
super.visitCall(expression)
|
||||
val functionDescriptor = expression.descriptor as FunctionDescriptor
|
||||
val functionDescriptor = expression.descriptor
|
||||
|
||||
if (!functionDescriptor.needsDefaultArgumentsLowering)
|
||||
return expression
|
||||
@@ -262,13 +259,15 @@ class DefaultParameterInjector internal constructor(val context: Context): BodyL
|
||||
val argumentsCount = argumentCount(expression)
|
||||
if (argumentsCount == functionDescriptor.valueParameters.size)
|
||||
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.original.typeParameters.forEach { log("${descriptor.original}[${it.index}] : $it") }
|
||||
return IrCallImpl(
|
||||
startOffset = expression.startOffset,
|
||||
endOffset = expression.endOffset,
|
||||
calleeDescriptor = descriptor,
|
||||
symbol = symbol,
|
||||
descriptor = descriptor,
|
||||
typeArguments = expression.descriptor.typeParameters.map{it to (expression.getTypeArgument(it) ?: it.defaultType) }.toMap())
|
||||
.apply {
|
||||
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 keyDescriptor = if (DescriptorUtils.isOverride(descriptor))
|
||||
DescriptorUtils.getAllOverriddenDescriptors(descriptor).first()
|
||||
else
|
||||
descriptor.original
|
||||
val realDescriptor = keyDescriptor.generateDefaultsDescription(context)
|
||||
val realFunction = keyDescriptor.generateDefaultsFunction(context)
|
||||
val realDescriptor = realFunction.descriptor
|
||||
|
||||
log("$descriptor -> $realDescriptor")
|
||||
val maskValues = Array(descriptor.valueParameters.size / 32 + 1, {0})
|
||||
@@ -308,24 +308,24 @@ class DefaultParameterInjector internal constructor(val context: Context): BodyL
|
||||
return@mapIndexed pair
|
||||
})
|
||||
maskValues.forEachIndexed { i, maskValue ->
|
||||
params += maskParameterDescriptor(realDescriptor, i) to IrConstImpl.int(
|
||||
params += maskParameterDescriptor(realFunction, i) to IrConstImpl.int(
|
||||
startOffset = irBody.startOffset,
|
||||
endOffset = irBody.endOffset,
|
||||
type = descriptor.builtIns.intType,
|
||||
value = maskValue)
|
||||
}
|
||||
if (expression.descriptor is ClassConstructorDescriptor) {
|
||||
val defaultArgumentMarker = getDefaultArgumentMarkerClassDescriptor(context.builtIns)
|
||||
val defaultArgumentMarker = context.ir.symbols.defaultArgumentMarker
|
||||
params += markerParameterDescriptor(realDescriptor) to IrGetObjectValueImpl(
|
||||
startOffset = irBody.startOffset,
|
||||
endOffset = irBody.endOffset,
|
||||
type = defaultArgumentMarker.defaultType,
|
||||
descriptor = defaultArgumentMarker)
|
||||
type = defaultArgumentMarker.owner.defaultType,
|
||||
symbol = defaultArgumentMarker)
|
||||
}
|
||||
params.forEach {
|
||||
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) =
|
||||
@@ -339,8 +339,8 @@ class DefaultParameterInjector internal constructor(val context: Context): BodyL
|
||||
private val CallableMemberDescriptor.needsDefaultArgumentsLowering
|
||||
get() = valueParameters.any { it.hasDefaultValue() } && !(this is FunctionDescriptor && isInline)
|
||||
|
||||
private fun FunctionDescriptor.generateDefaultsDescription(context: Context): FunctionDescriptor {
|
||||
return context.ir.defaultParameterDescriptorsCache.getOrPut(this) {
|
||||
private fun FunctionDescriptor.generateDefaultsFunction(context: Context): IrFunction {
|
||||
return context.ir.defaultParameterDeclarationsCache.getOrPut(this) {
|
||||
val descriptor = when (this) {
|
||||
is ClassConstructorDescriptor ->
|
||||
ClassConstructorDescriptorImpl.create(
|
||||
@@ -367,7 +367,7 @@ private fun FunctionDescriptor.generateDefaultsDescription(context: Context): Fu
|
||||
if (this is ClassConstructorDescriptor) {
|
||||
syntheticParameters += valueParameter(descriptor, syntheticParameters.last().index + 1,
|
||||
kConstructorMarkerName,
|
||||
getDefaultArgumentMarkerClassDescriptor(context.builtIns).defaultType)
|
||||
context.ir.symbols.defaultArgumentMarker.owner.defaultType)
|
||||
}
|
||||
descriptor.initialize(
|
||||
/* receiverParameterType = */ extensionReceiverParameter?.type,
|
||||
@@ -407,10 +407,33 @@ private fun FunctionDescriptor.generateDefaultsDescription(context: Context): Fu
|
||||
/* visibility = */ this.visibility)
|
||||
descriptor.isSuspend = this.isSuspend
|
||||
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 {
|
||||
return ValueParameterDescriptorImpl(
|
||||
containingDeclaration = descriptor,
|
||||
@@ -429,9 +452,4 @@ private fun valueParameter(descriptor: FunctionDescriptor, index: Int, name: Nam
|
||||
|
||||
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
|
||||
|
||||
+2
@@ -282,6 +282,8 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
|
||||
.toList()
|
||||
defaultClassDescriptor.initialize(SimpleMemberScope(contributedDescriptors), constructors, null)
|
||||
|
||||
defaultClass.addFakeOverrides()
|
||||
|
||||
return defaultClass
|
||||
}
|
||||
|
||||
|
||||
+33
-36
@@ -1,24 +1,25 @@
|
||||
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.lower.*
|
||||
import org.jetbrains.kotlin.backend.common.*
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
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.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
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.transformChildrenVoid
|
||||
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
|
||||
}
|
||||
|
||||
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)
|
||||
= IrReturnImpl(startOffset, endOffset, functionDescriptor, value)
|
||||
= IrReturnImpl(startOffset, endOffset, target, value)
|
||||
}
|
||||
|
||||
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,
|
||||
val finallyExpression: IrExpression,
|
||||
val irBuilder: IrBuilderWithScope): Scope() {
|
||||
val jumps = mutableMapOf<HighLevelJump, FunctionDescriptor>()
|
||||
val jumps = mutableMapOf<HighLevelJump, IrFunctionSymbol>()
|
||||
}
|
||||
|
||||
private val scopeStack = mutableListOf<Scope>()
|
||||
@@ -101,26 +102,26 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass
|
||||
override fun visitBreak(jump: IrBreak): IrExpression {
|
||||
val startOffset = jump.startOffset
|
||||
val endOffset = jump.endOffset
|
||||
val irBuilder = context.createIrBuilder(functionDescriptor, startOffset, endOffset)
|
||||
val irBuilder = context.createIrBuilder(irFunction.symbol, startOffset, endOffset)
|
||||
return performHighLevelJump(
|
||||
targetScopePredicate = { it is LoopScope && it.loop == jump.loop },
|
||||
jump = Break(jump.loop),
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
value = irBuilder.irUnit()
|
||||
value = irBuilder.irGetObject(context.ir.symbols.unit)
|
||||
) ?: jump
|
||||
}
|
||||
|
||||
override fun visitContinue(jump: IrContinue): IrExpression {
|
||||
val startOffset = jump.startOffset
|
||||
val endOffset = jump.endOffset
|
||||
val irBuilder = context.createIrBuilder(functionDescriptor, startOffset, endOffset)
|
||||
val irBuilder = context.createIrBuilder(irFunction.symbol, startOffset, endOffset)
|
||||
return performHighLevelJump(
|
||||
targetScopePredicate = { it is LoopScope && it.loop == jump.loop },
|
||||
jump = Continue(jump.loop),
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
value = irBuilder.irUnit()
|
||||
value = irBuilder.irGetObject(context.ir.symbols.unit)
|
||||
) ?: jump
|
||||
}
|
||||
|
||||
@@ -129,7 +130,7 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass
|
||||
|
||||
return performHighLevelJump(
|
||||
targetScopePredicate = { it is ReturnableScope && it.descriptor == expression.returnTarget },
|
||||
jump = Return(expression.returnTarget),
|
||||
jump = Return(expression.returnTargetSymbol),
|
||||
startOffset = expression.startOffset,
|
||||
endOffset = expression.endOffset,
|
||||
value = expression.value
|
||||
@@ -161,10 +162,10 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass
|
||||
|
||||
val currentTryScope = tryScopes[index]
|
||||
currentTryScope.jumps.getOrPut(jump) {
|
||||
val descriptor = getFakeFunctionDescriptor(jump.toString(), value.type)
|
||||
val symbol = getIrReturnableBlockSymbol(jump.toString(), value.type)
|
||||
with(currentTryScope) {
|
||||
irBuilder.run {
|
||||
val inlinedFinally = irInlineFinally(descriptor, expression, finallyExpression)
|
||||
val inlinedFinally = irInlineFinally(symbol, expression, finallyExpression)
|
||||
expression = performHighLevelJump(
|
||||
tryScopes = tryScopes,
|
||||
index = index + 1,
|
||||
@@ -174,12 +175,12 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass
|
||||
value = inlinedFinally)
|
||||
}
|
||||
}
|
||||
descriptor
|
||||
symbol
|
||||
}.let {
|
||||
return IrReturnImpl(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
returnTargetDescriptor = it,
|
||||
returnTargetSymbol = it,
|
||||
value = value)
|
||||
}
|
||||
}
|
||||
@@ -191,7 +192,7 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass
|
||||
|
||||
val startOffset = aTry.startOffset
|
||||
val endOffset = aTry.endOffset
|
||||
val irBuilder = context.createIrBuilder(functionDescriptor, startOffset, endOffset)
|
||||
val irBuilder = context.createIrBuilder(irFunction.symbol, startOffset, endOffset)
|
||||
val transformer = this
|
||||
irBuilder.run {
|
||||
val transformedTry = IrTryImpl(
|
||||
@@ -223,33 +224,33 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass
|
||||
finallyExpression = null
|
||||
)
|
||||
using(TryScope(syntheticTry, transformedFinallyExpression, this)) {
|
||||
val fallThroughDescriptor = getFakeFunctionDescriptor("fallThrough", aTry.type)
|
||||
val fallThroughSymbol = getIrReturnableBlockSymbol("fallThrough", aTry.type)
|
||||
val transformedResult = aTry.tryResult.transform(transformer, null)
|
||||
transformedTry.tryResult = irReturn(fallThroughDescriptor, transformedResult)
|
||||
transformedTry.tryResult = irReturn(fallThroughSymbol, transformedResult)
|
||||
for (aCatch in aTry.catches) {
|
||||
val transformedCatch = aCatch.transform(transformer, null)
|
||||
transformedCatch.result = irReturn(fallThroughDescriptor, transformedCatch.result)
|
||||
transformedCatch.result = irReturn(fallThroughSymbol, transformedCatch.result)
|
||||
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,
|
||||
finallyExpression: IrExpression): IrExpression {
|
||||
val returnType = descriptor.returnType!!
|
||||
val returnType = symbol.descriptor.returnType!!
|
||||
return when {
|
||||
returnType.isUnit() || returnType.isNothing() -> irBlock(value, null, returnType) {
|
||||
+irReturnableBlock(descriptor) {
|
||||
+irReturnableBlock(symbol) {
|
||||
+value
|
||||
}
|
||||
+finallyExpression.copy()
|
||||
}
|
||||
else -> irBlock(value, null, returnType) {
|
||||
val tmp = irTemporary(irReturnableBlock(descriptor) {
|
||||
+irReturn(descriptor, value)
|
||||
val tmp = irTemporary(irReturnableBlock(symbol) {
|
||||
+irReturn(symbol, value)
|
||||
})
|
||||
+finallyExpression.copy()
|
||||
+irGet(tmp.symbol)
|
||||
@@ -268,23 +269,19 @@ internal class FinallyBlocksLowering(val context: Context): FunctionLoweringPass
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun <T: IrElement> T.copy() = this.transform(DeepCopyIrTreeWithDeclarations(), data = null) as T
|
||||
private fun getIrReturnableBlockSymbol(name: String, returnType: KotlinType): IrReturnableBlockSymbol =
|
||||
IrReturnableBlockSymbolImpl(getFakeFunctionDescriptor(name, returnType))
|
||||
|
||||
private inline fun <reified T : IrElement> T.copy() = this.deepCopyWithVariables()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private object DECLARATION_ORIGIN_FINALLY_BLOCK :
|
||||
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) =
|
||||
fun IrBuilderWithScope.irReturn(target: IrFunctionSymbol, value: IrExpression) =
|
||||
IrReturnImpl(startOffset, endOffset, target, value)
|
||||
|
||||
inline fun IrBuilderWithScope.irReturnableBlock(descriptor: FunctionDescriptor, body: IrBlockBuilder.() -> Unit) =
|
||||
IrReturnableBlockImpl(startOffset, endOffset, descriptor.returnType!!, descriptor, null,
|
||||
IrBlockBuilder(context, scope, startOffset, endOffset, null, descriptor.returnType!!)
|
||||
inline fun IrBuilderWithScope.irReturnableBlock(symbol: IrReturnableBlockSymbol, body: IrBlockBuilder.() -> Unit) =
|
||||
IrReturnableBlockImpl(startOffset, endOffset, symbol.descriptor.returnType!!, symbol, null,
|
||||
IrBlockBuilder(context, scope, startOffset, endOffset, null, symbol.descriptor.returnType!!)
|
||||
.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.reportCompilationError
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
|
||||
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.irGet
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
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.IrFunctionReferenceImpl
|
||||
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.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||
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.TypeUtils
|
||||
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.
|
||||
*/
|
||||
internal class InteropLowering(val context: Context) : FileLoweringPass {
|
||||
internal class InteropLoweringPart2(val context: Context) : FileLoweringPass {
|
||||
override fun lower(irFile: IrFile) {
|
||||
val transformer = InteropTransformer(context, irFile)
|
||||
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) {
|
||||
|
||||
val interop = context.interopBuiltIns
|
||||
val konanBuiltins = context.builtIns
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
val symbols = context.ir.symbols
|
||||
|
||||
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)) {
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
@@ -222,34 +115,10 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
||||
return when (descriptor) {
|
||||
interop.cPointerRawValue.getter ->
|
||||
// Replace by the intrinsic call to be handled by code generator:
|
||||
builder.irCall(interop.cPointerGetRawValue).apply {
|
||||
builder.irCall(symbols.interopCPointerGetRawValue).apply {
|
||||
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 -> {
|
||||
val argument = expression.getValueArgument(0)
|
||||
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 -> {
|
||||
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.
|
||||
}
|
||||
|
||||
val target = irCallableReference.descriptor.original
|
||||
val targetSymbol = irCallableReference.symbol
|
||||
val target = targetSymbol.descriptor
|
||||
val signatureTypes = target.allParameters.map { it.type } + target.returnType!!
|
||||
|
||||
signatureTypes.forEachIndexed { index, type ->
|
||||
@@ -312,7 +175,7 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
||||
IrFunctionReferenceImpl(
|
||||
builder.startOffset, builder.endOffset,
|
||||
expression.type,
|
||||
target,
|
||||
targetSymbol, target,
|
||||
typeArguments = null)
|
||||
}
|
||||
|
||||
@@ -352,10 +215,14 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
||||
else -> throw Error()
|
||||
}
|
||||
|
||||
val conversionDescriptor = receiver.type.memberScope.getContributedFunctions(
|
||||
Name.identifier("to$typeOperand"), NoLookupLocation.FROM_BACKEND).single()
|
||||
val receiverClass = symbols.integerClasses.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
|
||||
}
|
||||
}
|
||||
@@ -415,11 +282,11 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
||||
|
||||
return argument.statements.last() as? IrFunctionReference
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrCall.getSingleTypeArgument(): KotlinType {
|
||||
val typeParameter = descriptor.original.typeParameters.single()
|
||||
return getTypeArgument(typeParameter)!!
|
||||
}
|
||||
private fun IrCall.getSingleTypeArgument(): KotlinType {
|
||||
val typeParameter = descriptor.original.typeParameters.single()
|
||||
return getTypeArgument(typeParameter)!!
|
||||
}
|
||||
|
||||
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.lower.createIrBuilder
|
||||
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.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||
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.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.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
@@ -41,22 +38,24 @@ internal class LateinitLowering(val context: Context): FileLoweringPass {
|
||||
irFile.transformChildrenVoid(object: IrElementTransformerVoid() {
|
||||
override fun visitProperty(declaration: IrProperty): IrStatement {
|
||||
if (declaration.descriptor.isLateInit)
|
||||
transformGetter(declaration.descriptor, declaration.getter!!)
|
||||
transformGetter(declaration.backingField!!.symbol, declaration.getter!!)
|
||||
return declaration
|
||||
}
|
||||
|
||||
private fun transformGetter(propertyDescriptor: PropertyDescriptor, getter: IrFunction) {
|
||||
assert (!propertyDescriptor.type.isValueType(), { "'lateinit' modifier is not allowed on value types" })
|
||||
private fun transformGetter(backingFieldSymbol: IrFieldSymbol, getter: IrFunction) {
|
||||
val type = backingFieldSymbol.descriptor.type
|
||||
assert (!type.isValueType(), { "'lateinit' modifier is not allowed on value types" })
|
||||
val startOffset = getter.startOffset
|
||||
val endOffset = getter.endOffset
|
||||
val irBuilder = context.createIrBuilder(getter.descriptor, startOffset, endOffset)
|
||||
val irBuilder = context.createIrBuilder(getter.symbol, startOffset, endOffset)
|
||||
irBuilder.run {
|
||||
val block = irBlock(propertyDescriptor.type)
|
||||
val resultVar = scope.createTemporaryVariable(irGetField(irThis(), propertyDescriptor))
|
||||
val block = irBlock(type)
|
||||
val resultVar = scope.createTemporaryVariable(
|
||||
irGetField(irGet(getter.dispatchReceiverParameter!!.symbol), backingFieldSymbol))
|
||||
block.statements.add(resultVar)
|
||||
val throwIfNull = irIfThenElse(context.builtIns.nothingType,
|
||||
irNotEquals(irGet(resultVar.descriptor), irNull()),
|
||||
irReturn(irGet(resultVar.descriptor)),
|
||||
irNotEquals(irGet(resultVar.symbol), irNull()),
|
||||
irReturn(irGet(resultVar.symbol)),
|
||||
irCall(throwErrorFunction))
|
||||
block.statements.add(throwIfNull)
|
||||
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
|
||||
= 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.*
|
||||
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.isSuspendFunctionInvoke
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||
import org.jetbrains.kotlin.backend.konan.ir.*
|
||||
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.IrSimpleFunctionSymbolImpl
|
||||
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.name.FqName
|
||||
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.makeNotNullable
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
|
||||
internal class SuspendFunctionsLowering(val context: Context): DeclarationContainerLoweringPass {
|
||||
|
||||
@@ -67,7 +63,6 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
else null
|
||||
}
|
||||
transformCallableReferencesToSuspendLambdas(irDeclarationContainer)
|
||||
transformCallsToExtensionSuspendFunctions(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 {
|
||||
NO_SUSPEND_CALLS,
|
||||
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 fun removeReturnIfSuspendedCall(irFunction: IrFunction) {
|
||||
@@ -262,15 +228,15 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
+irReturn(
|
||||
irCall(coroutine.doResumeFunction.symbol).apply {
|
||||
dispatchReceiver = irCall(coroutine.coroutineConstructor.symbol).apply {
|
||||
val functionParameters = irFunction.descriptor.explicitParameters
|
||||
val functionParameters = irFunction.explicitParameters
|
||||
functionParameters.forEachIndexed { index, argument ->
|
||||
putValueArgument(index, irGet(argument))
|
||||
}
|
||||
putValueArgument(functionParameters.size,
|
||||
irCall(getContinuationDescriptor.substitute(descriptor.returnType!!)))
|
||||
irCall(getContinuationSymbol, listOf(descriptor.returnType!!)))
|
||||
}
|
||||
putValueArgument(0, irUnit()) // value
|
||||
putValueArgument(1, irNull()) // exception
|
||||
putValueArgument(0, irGetObject(symbols.unit)) // value
|
||||
putValueArgument(1, irNull()) // exception
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -285,17 +251,13 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
private var coroutineId = 0
|
||||
|
||||
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 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 continuationClassDescriptor = coroutinesScope
|
||||
.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?) {
|
||||
|
||||
@@ -313,12 +275,17 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
private lateinit var coroutineClassThis: IrValueParameterSymbol
|
||||
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
|
||||
.getContributedFunctions(Name.identifier("create"), NoLookupLocation.FROM_BACKEND)
|
||||
.single { it.valueParameters.size == 1 }
|
||||
private val create1CompletionParameter = create1FunctionDescriptor.valueParameters[0]
|
||||
|
||||
private val coroutineImplLabelGetterSymbol = coroutineImplSymbol.getPropertyGetter("label")!!
|
||||
private val coroutineImplLabelSetterSymbol = coroutineImplSymbol.getPropertySetter("label")!!
|
||||
|
||||
fun build(): BuiltCoroutine {
|
||||
val superTypes = mutableListOf<KotlinType>(coroutineImplClassDescriptor.defaultType)
|
||||
var suspendFunctionClassDescriptor: ClassDescriptor? = null
|
||||
@@ -406,6 +373,8 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
).filterNotNull().toList()
|
||||
coroutineClassDescriptor.initialize(SimpleMemberScope(contributedDescriptors), constructors, null)
|
||||
|
||||
coroutineClass.addFakeOverrides()
|
||||
|
||||
coroutineConstructorBuilder.initialize()
|
||||
coroutineClass.declarations.add(coroutineConstructorBuilder.ir)
|
||||
|
||||
@@ -437,8 +406,6 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
private fun createConstructorBuilder()
|
||||
= object : SymbolWithIrBuilder<IrConstructorSymbol, IrConstructor>() {
|
||||
|
||||
private val coroutineImplConstructorDescriptor = coroutineImplClassDescriptor.constructors.single()
|
||||
|
||||
override fun buildSymbol() = IrConstructorSymbolImpl(
|
||||
ClassConstructorDescriptorImpl.create(
|
||||
/* containingDeclaration = */ coroutineClassDescriptor,
|
||||
@@ -452,7 +419,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
val descriptor = symbol.descriptor as ClassConstructorDescriptorImpl
|
||||
val constructorParameters = (
|
||||
functionParameters
|
||||
+ coroutineImplConstructorDescriptor.valueParameters[0] // completion.
|
||||
+ coroutineImplConstructorSymbol.descriptor.valueParameters[0] // completion.
|
||||
).mapIndexed { index, parameter -> parameter.copyAsValueParameter(descriptor, index) }
|
||||
|
||||
descriptor.initialize(constructorParameters, Visibilities.PUBLIC)
|
||||
@@ -478,7 +445,8 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
||||
body = irBuilder.irBlockBody {
|
||||
val completionParameter = valueParameters.last()
|
||||
+IrDelegatingConstructorCallImpl(startOffset, endOffset, coroutineImplConstructorDescriptor).apply {
|
||||
+IrDelegatingConstructorCallImpl(startOffset, endOffset,
|
||||
coroutineImplConstructorSymbol, coroutineImplConstructorSymbol.descriptor).apply {
|
||||
putValueArgument(0, irGet(completionParameter.symbol))
|
||||
}
|
||||
+IrInstanceInitializerCallImpl(startOffset, endOffset, coroutineClass.symbol)
|
||||
@@ -493,8 +461,6 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
private fun createFactoryConstructorBuilder(boundParams: List<ParameterDescriptor>)
|
||||
= object : SymbolWithIrBuilder<IrConstructorSymbol, IrConstructor>() {
|
||||
|
||||
private val coroutineImplConstructorDescriptor = coroutineImplClassDescriptor.constructors.single()
|
||||
|
||||
override fun buildSymbol() = IrConstructorSymbolImpl(
|
||||
ClassConstructorDescriptorImpl.create(
|
||||
/* containingDeclaration = */ coroutineClassDescriptor,
|
||||
@@ -526,7 +492,8 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
|
||||
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
|
||||
body = irBuilder.irBlockBody {
|
||||
+IrDelegatingConstructorCallImpl(startOffset, endOffset, coroutineImplConstructorDescriptor).apply {
|
||||
+IrDelegatingConstructorCallImpl(startOffset, endOffset,
|
||||
coroutineImplConstructorSymbol, coroutineImplConstructorSymbol.descriptor).apply {
|
||||
putValueArgument(0, irNull()) // Completion.
|
||||
}
|
||||
+IrInstanceInitializerCallImpl(startOffset, endOffset, coroutineClass.symbol)
|
||||
@@ -669,9 +636,9 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
putValueArgument(index, irGet(parameter.symbol))
|
||||
}
|
||||
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
|
||||
}
|
||||
)
|
||||
@@ -803,7 +770,10 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
scope.forEach {
|
||||
+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 -> {
|
||||
@@ -828,13 +798,15 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
type = context.builtIns.unitType,
|
||||
suspensionPointId = irGet(irGet(coroutineClassThis), label),
|
||||
suspensionPointId = irCall(coroutineImplLabelGetterSymbol).apply {
|
||||
dispatchReceiver = irGet(coroutineClassThis)
|
||||
},
|
||||
result = irBlock(startOffset, endOffset) {
|
||||
+irThrowIfNotNull(exceptionArgument) // Coroutine might start with an exception.
|
||||
statements.forEach { +it }
|
||||
})
|
||||
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
|
||||
}
|
||||
@@ -1156,7 +1128,7 @@ internal class SuspendFunctionsLowering(val context: Context): DeclarationContai
|
||||
}
|
||||
|
||||
private fun IrBuilderWithScope.irReturnIfSuspended(value: IrValueSymbol) =
|
||||
irIfThen(irEqeqeq(irGet(value), irGet(COROUTINE_SUSPENDED)),
|
||||
irIfThen(irEqeqeq(irGet(value), irCall(symbols.coroutineSuspendedGetter)),
|
||||
irReturn(irGet(value)))
|
||||
|
||||
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.builtins.KotlinBuiltIns
|
||||
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.builders.IrBuilderWithScope
|
||||
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.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.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.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.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
|
||||
class VarargInjectionLowering internal constructor(val context: Context): DeclarationContainerLoweringPass {
|
||||
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
|
||||
irDeclarationContainer.declarations.forEach{
|
||||
when (it) {
|
||||
is IrField -> lower(it.descriptor, it.initializer)
|
||||
is IrFunction -> lower(it.descriptor, it.body)
|
||||
is IrField -> lower(it.symbol, it.initializer)
|
||||
is IrFunction -> lower(it.symbol, it.body)
|
||||
is IrProperty -> {
|
||||
lower(it.descriptor, it.backingField)
|
||||
if (it.getter != null)
|
||||
lower(it.getter!!.descriptor, it.getter)
|
||||
if (it.setter != null)
|
||||
lower(it.setter!!.descriptor, it.setter)
|
||||
it.backingField?.let { field ->
|
||||
lower(field.symbol, field)
|
||||
}
|
||||
it.getter?.let { getter ->
|
||||
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() {
|
||||
val transformer = this
|
||||
|
||||
@@ -107,11 +110,13 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar
|
||||
val type = expression.varargElementType
|
||||
log("$expression: array type:$type, is array of primitives ${!KotlinBuiltIns.isArray(expression.type)}")
|
||||
val arrayHandle = arrayType(expression.type)
|
||||
val arrayConstructor = arrayHandle.arrayDescriptor.constructors.find { it.valueParameters.size == 1 }!!
|
||||
val block = irBlock(arrayHandle.arrayDescriptor.defaultType)
|
||||
val arrayConstructorCall = irCall(
|
||||
descriptor = arrayConstructor,
|
||||
typeArguments = typeArgument(arrayConstructor, type))
|
||||
val arrayConstructor = arrayHandle.arraySymbol.constructors.find { it.owner.valueParameters.size == 1 }!!
|
||||
val block = irBlock(arrayHandle.arraySymbol.owner.defaultType)
|
||||
val arrayConstructorCall = if (arrayConstructor.owner.typeParameters.isEmpty()) {
|
||||
irCall(arrayConstructor)
|
||||
} else {
|
||||
irCall(arrayConstructor, listOf(type))
|
||||
}
|
||||
|
||||
|
||||
val vars = expression.elements.map {
|
||||
@@ -135,10 +140,7 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar
|
||||
log("element:$i> ${ir2string(element)}")
|
||||
val dst = vars[element]!!
|
||||
if (element !is IrSpreadElement) {
|
||||
val setArrayElementCall = irCall(
|
||||
descriptor = arrayHandle.setMethodDescriptor,
|
||||
typeArguments = null
|
||||
)
|
||||
val setArrayElementCall = irCall(arrayHandle.setMethodSymbol)
|
||||
setArrayElementCall.dispatchReceiver = irGet(arrayTmpVariable.symbol)
|
||||
setArrayElementCall.putValueArgument(0, if (hasSpreadElement) irGet(indexTmpVariable.symbol) else irConstInt(i))
|
||||
setArrayElementCall.putValueArgument(1, irGet(dst.symbol))
|
||||
@@ -149,7 +151,7 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar
|
||||
} else {
|
||||
val arraySizeVariable = scope.createTemporaryVariable(irArraySize(arrayHandle, irGet(dst.symbol)), "length".synthesizedString)
|
||||
block.statements.add(arraySizeVariable)
|
||||
val copyCall = irCall(arrayHandle.copyRangeToDescriptor, null).apply {
|
||||
val copyCall = irCall(arrayHandle.copyRangeToSymbol).apply {
|
||||
extensionReceiver = irGet(dst.symbol)
|
||||
putValueArgument(0, irGet(arrayTmpVariable.symbol)) /* destination */
|
||||
putValueArgument(1, kIntZero) /* fromIndex */
|
||||
@@ -170,13 +172,8 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
private fun typeArgument(arrayConstructor: ClassConstructorDescriptor, type: KotlinType):Map<TypeParameterDescriptor, KotlinType>? {
|
||||
return if (!arrayConstructor.typeParameters.isEmpty())
|
||||
mapOf(arrayConstructor.typeParameters.first() to type)
|
||||
else
|
||||
null
|
||||
}
|
||||
private val symbols = context.ir.symbols
|
||||
private val intPlusInt = symbols.intPlusInt
|
||||
|
||||
private fun arrayType(type: KotlinType): ArrayHandle = when {
|
||||
KotlinBuiltIns.isPrimitiveArray(type) -> {
|
||||
@@ -196,7 +193,7 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar
|
||||
else -> kArrayHandler
|
||||
}
|
||||
|
||||
private fun IrBuilderWithScope.intPlus() = irCall(kIntPlusDescriptor, null)
|
||||
private fun IrBuilderWithScope.intPlus() = irCall(intPlusInt)
|
||||
private fun IrBuilderWithScope.increment(expression: IrExpression, value: IrExpression): IrExpression {
|
||||
return intPlus().apply {
|
||||
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? {
|
||||
context.createIrBuilder(scope.scopeOwner, expression.startOffset, expression.endOffset).run {
|
||||
context.createIrBuilder(scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset).run {
|
||||
if (!hasSpreadElement)
|
||||
return irConstInt(expression.elements.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 {
|
||||
val arraySize = irCall((arrayHandle.sizeDescriptor as PropertyDescriptor).getter as FunctionDescriptor, null).apply {
|
||||
val arraySize = irCall(arrayHandle.sizeGetterSymbol).apply {
|
||||
dispatchReceiver = expression
|
||||
}
|
||||
return arraySize
|
||||
@@ -237,48 +234,31 @@ class VarargInjectionLowering internal constructor(val context: Context): Declar
|
||||
context.log{"VARARG-INJECTOR: $msg"}
|
||||
}
|
||||
|
||||
data class ArrayHandle(val arrayDescriptor:ClassDescriptor,
|
||||
val setMethodDescriptor: FunctionDescriptor,
|
||||
val sizeDescriptor:DeclarationDescriptor,
|
||||
val copyRangeToDescriptor:FunctionDescriptor)
|
||||
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)
|
||||
data class ArrayHandle(val arraySymbol: IrClassSymbol,
|
||||
val setMethodSymbol: IrFunctionSymbol,
|
||||
val sizeGetterSymbol: IrFunctionSymbol,
|
||||
val copyRangeToSymbol: IrFunctionSymbol)
|
||||
|
||||
val kInt = context.builtIns.int
|
||||
val kIntType = context.builtIns.intType
|
||||
val kIntPlusDescriptor = DescriptorUtils.getAllDescriptors(kInt.unsubstitutedMemberScope).find {
|
||||
it.name.asString() == "plus"
|
||||
&& (it as FunctionDescriptor).valueParameters[0].type == kIntType} as FunctionDescriptor
|
||||
val kByteArrayHandler = handle(symbols.byteArray)
|
||||
val kCharArrayHandler = handle(symbols.charArray)
|
||||
val kShortArrayHandler = handle(symbols.shortArray)
|
||||
val kIntArrayHandler = handle(symbols.intArray)
|
||||
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(
|
||||
arrayDescriptor = descriptor,
|
||||
setMethodDescriptor = setMethodDescriptor(descriptor),
|
||||
sizeDescriptor = sizeMethodDescriptor(descriptor)!!,
|
||||
copyRangeToDescriptor = copyRangeToFunctionDescriptor(descriptor))
|
||||
private fun handle(symbol: IrClassSymbol) = ArrayHandle(
|
||||
arraySymbol = symbol,
|
||||
setMethodSymbol = symbol.functions.single { it.descriptor.name == OperatorNameConventions.SET },
|
||||
sizeGetterSymbol = symbol.getPropertyGetter("size")!!,
|
||||
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.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.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.impl.*
|
||||
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.serialization.KonanDescriptorSerializer
|
||||
import org.jetbrains.kotlin.serialization.KonanIr
|
||||
@@ -1057,6 +1058,7 @@ internal class IrDeserializer(val context: Context,
|
||||
val clazz = IrClassImpl(start, end, origin, descriptor, members)
|
||||
|
||||
clazz.createParameterDeclarations()
|
||||
clazz.addFakeOverrides()
|
||||
|
||||
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.serialization.MutableTypeTable
|
||||
import org.jetbrains.kotlin.serialization.KonanLinkData
|
||||
import org.jetbrains.kotlin.backend.common.validateIrFunction
|
||||
|
||||
internal class DeserializerDriver(val context: Context) {
|
||||
|
||||
|
||||
+13
-57
@@ -16,33 +16,17 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.builders
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.substitute
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrLoop
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||
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.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
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) =
|
||||
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)
|
||||
|
||||
@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 {
|
||||
return IrCallImpl(this.startOffset, this.endOffset, symbol)
|
||||
}
|
||||
|
||||
@Deprecated("Creates unbound symbol")
|
||||
fun IrBuilderWithScope.irCall(
|
||||
callee: FunctionDescriptor,
|
||||
typeArguments: Map<TypeParameterDescriptor, KotlinType>
|
||||
): IrCallImpl {
|
||||
val substitutionContext = typeArguments.map { (typeParameter, typeArgument) ->
|
||||
typeParameter.typeConstructor to TypeProjectionImpl(typeArgument)
|
||||
}.toMap()
|
||||
fun IrBuilderWithScope.irCall(symbol: IrFunctionSymbol, typeArguments: Map<TypeParameterDescriptor, KotlinType>) =
|
||||
IrCallImpl(this.startOffset, this.endOffset, symbol, symbol.descriptor.substitute(typeArguments), typeArguments)
|
||||
|
||||
val substitutor = TypeSubstitutor.create(substitutionContext)
|
||||
val substitutedCallee = callee.substitute(substitutor)!!
|
||||
fun IrBuilderWithScope.irCall(symbol: IrFunctionSymbol, typeArguments: List<KotlinType>) =
|
||||
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
|
||||
|
||||
import org.jetbrains.kotlin.backend.konan.util.atMostOne
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
|
||||
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
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.IrValueParameterImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
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 =
|
||||
descriptor.startOffset ?: this.startOffset
|
||||
|
||||
@@ -193,6 +221,16 @@ val IrClassSymbol.functions: Sequence<IrSimpleFunctionSymbol>
|
||||
val IrClassSymbol.constructors: Sequence<IrConstructorSymbol>
|
||||
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>
|
||||
get() = (listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters).map { it.symbol }
|
||||
|
||||
@@ -201,68 +239,3 @@ val IrValueParameter.type: KotlinType
|
||||
|
||||
val IrClass.defaultType: KotlinType
|
||||
get() = this.descriptor.defaultType
|
||||
|
||||
class IrSymbolBindingChecker : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitDeclarationReference(expression: IrDeclarationReference) {
|
||||
super.visitDeclarationReference(expression)
|
||||
|
||||
expression.symbol.ensureBound(expression)
|
||||
}
|
||||
|
||||
override fun visitFunctionAccess(expression: IrFunctionAccessExpression) {
|
||||
super.visitFunctionAccess(expression)
|
||||
|
||||
expression.symbol.ensureBound(expression)
|
||||
}
|
||||
|
||||
override fun visitFunctionReference(expression: IrFunctionReference) {
|
||||
super.visitFunctionReference(expression)
|
||||
|
||||
expression.symbol.ensureBound(expression)
|
||||
}
|
||||
|
||||
override fun visitCall(expression: IrCall) {
|
||||
super.visitCall(expression)
|
||||
|
||||
expression.superQualifierSymbol?.ensureBound(expression)
|
||||
}
|
||||
|
||||
override fun visitPropertyReference(expression: IrPropertyReference) {
|
||||
super.visitPropertyReference(expression)
|
||||
|
||||
expression.field?.ensureBound(expression)
|
||||
expression.getter?.ensureBound(expression)
|
||||
expression.setter?.ensureBound(expression)
|
||||
}
|
||||
|
||||
override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference) {
|
||||
super.visitLocalDelegatedPropertyReference(expression)
|
||||
|
||||
expression.delegate.ensureBound(expression)
|
||||
expression.getter.ensureBound(expression)
|
||||
expression.setter?.ensureBound(expression)
|
||||
}
|
||||
|
||||
override fun visitReturn(expression: IrReturn) {
|
||||
super.visitReturn(expression)
|
||||
|
||||
expression.returnTargetSymbol.ensureBound(expression)
|
||||
}
|
||||
|
||||
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall) {
|
||||
super.visitInstanceInitializerCall(expression)
|
||||
|
||||
expression.classSymbol.ensureBound(expression)
|
||||
}
|
||||
|
||||
private fun IrSymbol.ensureBound(expression: IrExpression) {
|
||||
if (!this.isBound) {
|
||||
throw Error("Unbound symbol ${this} found in ${expression.render()}")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -24,5 +24,5 @@ testDataVersion=1067176:id
|
||||
kotlinCompilerRepo=http://dl.bintray.com/jetbrains/kotlin-native-dependencies
|
||||
#kotlinCompilerRepo=http://oss.sonatype.org/content/repositories/snapshots
|
||||
#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
|
||||
|
||||
Reference in New Issue
Block a user