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:
SvyatoslavScherbina
2017-05-24 11:30:28 +03:00
committed by GitHub
parent 9d6846947e
commit d08438da5f
30 changed files with 711 additions and 1117 deletions
@@ -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)
}
}
@@ -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,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 =
@@ -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),
@@ -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)
}
}
@@ -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
@@ -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)
}
}
@@ -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) {
@@ -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)
@@ -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(
@@ -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())
}
}
}
@@ -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),
@@ -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)
@@ -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)
@@ -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)
}
}
}
@@ -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.
}
@@ -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 }
}
@@ -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)
}
@@ -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
@@ -282,6 +282,8 @@ internal class EnumClassLowering(val context: Context) : ClassLoweringPass {
.toList()
defaultClassDescriptor.initialize(SimpleMemberScope(contributedDescriptors), constructors, null)
defaultClass.addFakeOverrides()
return defaultClass
}
@@ -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)
}
@@ -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) =
@@ -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)
}
@@ -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) =
@@ -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)
@@ -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
@@ -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) {
@@ -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)
@@ -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
View File
@@ -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