[IR BE] Use pure IrType instead of KotlinType

* clean up code
This commit is contained in:
Roman Artemev
2019-03-18 19:17:56 +03:00
committed by romanart
parent 1823ba1c48
commit 2ed29d8869
39 changed files with 249 additions and 695 deletions
@@ -16,11 +16,11 @@
package org.jetbrains.kotlin.backend.common
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.*
@@ -28,12 +28,11 @@ import org.jetbrains.kotlin.ir.util.isAnnotationClass
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
import org.jetbrains.kotlin.types.KotlinType
typealias ReportError = (element: IrElement, message: String) -> Unit
class CheckIrElementVisitor(
val builtIns: KotlinBuiltIns,
val irBuiltIns: IrBuiltIns,
val reportError: ReportError,
val config: IrValidatorConfig
) : IrElementVisitorVoid {
@@ -50,13 +49,13 @@ class CheckIrElementVisitor(
// Nothing to do.
}
private fun IrExpression.ensureTypeIs(expectedType: KotlinType) {
private fun IrExpression.ensureTypeIs(expectedType: IrType) {
if (!config.checkTypes)
return
// TODO: compare IR types instead.
if (expectedType != type.toKotlinType()) {
reportError(this, "unexpected expression.type: expected $expectedType, got ${type.toKotlinType()}")
if (expectedType.isEqualTo(type)) {
reportError(this, "unexpected expression.type: expected $expectedType, got ${type.render()}")
}
}
@@ -70,16 +69,16 @@ class CheckIrElementVisitor(
super.visitConst(expression)
val naturalType = when (expression.kind) {
IrConstKind.Null -> builtIns.nullableNothingType
IrConstKind.Boolean -> builtIns.booleanType
IrConstKind.Char -> builtIns.charType
IrConstKind.Byte -> builtIns.byteType
IrConstKind.Short -> builtIns.shortType
IrConstKind.Int -> builtIns.intType
IrConstKind.Long -> builtIns.longType
IrConstKind.String -> builtIns.stringType
IrConstKind.Float -> builtIns.floatType
IrConstKind.Double -> builtIns.doubleType
IrConstKind.Null -> irBuiltIns.nothingNType
IrConstKind.Boolean -> irBuiltIns.booleanType
IrConstKind.Char -> irBuiltIns.charType
IrConstKind.Byte -> irBuiltIns.byteType
IrConstKind.Short -> irBuiltIns.shortType
IrConstKind.Int -> irBuiltIns.intType
IrConstKind.Long -> irBuiltIns.longType
IrConstKind.String -> irBuiltIns.stringType
IrConstKind.Float -> irBuiltIns.floatType
IrConstKind.Double -> irBuiltIns.doubleType
}
expression.ensureTypeIs(naturalType)
@@ -88,13 +87,13 @@ class CheckIrElementVisitor(
override fun visitStringConcatenation(expression: IrStringConcatenation) {
super.visitStringConcatenation(expression)
expression.ensureTypeIs(builtIns.stringType)
expression.ensureTypeIs(irBuiltIns.stringType)
}
override fun visitGetObjectValue(expression: IrGetObjectValue) {
super.visitGetObjectValue(expression)
expression.ensureTypeIs(expression.descriptor.defaultType)
expression.ensureTypeIs(expression.symbol.createType(false, emptyList()))
}
// TODO: visitGetEnumValue
@@ -102,25 +101,25 @@ class CheckIrElementVisitor(
override fun visitGetValue(expression: IrGetValue) {
super.visitGetValue(expression)
expression.ensureTypeIs(expression.descriptor.type)
expression.ensureTypeIs(expression.symbol.owner.type)
}
override fun visitSetVariable(expression: IrSetVariable) {
super.visitSetVariable(expression)
expression.ensureTypeIs(builtIns.unitType)
expression.ensureTypeIs(irBuiltIns.unitType)
}
override fun visitGetField(expression: IrGetField) {
super.visitGetField(expression)
expression.ensureTypeIs(expression.descriptor.type)
expression.ensureTypeIs(expression.symbol.owner.type)
}
override fun visitSetField(expression: IrSetField) {
super.visitSetField(expression)
expression.ensureTypeIs(builtIns.unitType)
expression.ensureTypeIs(irBuiltIns.unitType)
}
override fun visitCall(expression: IrCall) {
@@ -132,12 +131,8 @@ class CheckIrElementVisitor(
reportError(expression, "Dispatch receivers with 'dynamic' type are not allowed")
}
val returnType = expression.descriptor.returnType
if (returnType == null) {
reportError(expression, "${expression.descriptor} return type is null")
} else {
expression.ensureTypeIs(returnType)
}
val returnType = expression.symbol.owner.returnType
expression.ensureTypeIs(returnType)
expression.superQualifierSymbol?.ensureBound(expression)
}
@@ -145,19 +140,19 @@ class CheckIrElementVisitor(
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) {
super.visitDelegatingConstructorCall(expression)
expression.ensureTypeIs(builtIns.unitType)
expression.ensureTypeIs(irBuiltIns.unitType)
}
override fun visitEnumConstructorCall(expression: IrEnumConstructorCall) {
super.visitEnumConstructorCall(expression)
expression.ensureTypeIs(builtIns.unitType)
expression.ensureTypeIs(irBuiltIns.unitType)
}
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall) {
super.visitInstanceInitializerCall(expression)
expression.ensureTypeIs(builtIns.unitType)
expression.ensureTypeIs(irBuiltIns.unitType)
expression.classSymbol.ensureBound(expression)
}
@@ -173,11 +168,11 @@ class CheckIrElementVisitor(
IrTypeOperator.IMPLICIT_NOTNULL,
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT,
IrTypeOperator.IMPLICIT_INTEGER_COERCION,
IrTypeOperator.SAM_CONVERSION -> typeOperand.toKotlinType()
IrTypeOperator.SAM_CONVERSION -> typeOperand
IrTypeOperator.SAFE_CAST -> typeOperand.makeNullable().toKotlinType()
IrTypeOperator.SAFE_CAST -> typeOperand.makeNullable()
IrTypeOperator.INSTANCEOF, IrTypeOperator.NOT_INSTANCEOF -> builtIns.booleanType
IrTypeOperator.INSTANCEOF, IrTypeOperator.NOT_INSTANCEOF -> irBuiltIns.booleanType
}
if (operator == IrTypeOperator.IMPLICIT_COERCION_TO_UNIT && !typeOperand.isUnit()) {
@@ -192,26 +187,26 @@ class CheckIrElementVisitor(
override fun visitLoop(loop: IrLoop) {
super.visitLoop(loop)
loop.ensureTypeIs(builtIns.unitType)
loop.ensureTypeIs(irBuiltIns.unitType)
}
override fun visitBreakContinue(jump: IrBreakContinue) {
super.visitBreakContinue(jump)
jump.ensureTypeIs(builtIns.nothingType)
jump.ensureTypeIs(irBuiltIns.nothingType)
}
override fun visitReturn(expression: IrReturn) {
super.visitReturn(expression)
expression.ensureTypeIs(builtIns.nothingType)
expression.ensureTypeIs(irBuiltIns.nothingType)
expression.returnTargetSymbol.ensureBound(expression)
}
override fun visitThrow(expression: IrThrow) {
super.visitThrow(expression)
expression.ensureTypeIs(builtIns.nothingType)
expression.ensureTypeIs(irBuiltIns.nothingType)
}
override fun visitClass(declaration: IrClass) {
@@ -16,9 +16,11 @@
package org.jetbrains.kotlin.backend.common
import org.jetbrains.kotlin.backend.common.descriptors.WrappedVariableDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.IrLoop
import org.jetbrains.kotlin.ir.util.DeepCopyIrTreeWithSymbols
import org.jetbrains.kotlin.ir.util.DeepCopySymbolRemapper
@@ -29,15 +31,7 @@ import org.jetbrains.kotlin.ir.visitors.acceptVoid
@Suppress("UNCHECKED_CAST")
fun <T : IrElement> T.deepCopyWithVariables(): T {
val descriptorsRemapper = object : DescriptorsRemapper {
override fun remapDeclaredVariable(descriptor: VariableDescriptor) = LocalVariableDescriptor(
/* containingDeclaration = */ descriptor.containingDeclaration,
/* annotations = */ descriptor.annotations,
/* name = */ descriptor.name,
/* type = */ descriptor.type,
/* mutable = */ descriptor.isVar,
/* isDelegated = */ false,
/* source = */ descriptor.source
)
override fun remapDeclaredVariable(descriptor: VariableDescriptor) = WrappedVariableDescriptor()
}
val symbolsRemapper = DeepCopySymbolRemapper(descriptorsRemapper)
@@ -50,6 +44,12 @@ fun <T : IrElement> T.deepCopyWithVariables(): T {
override fun getNonTransformedLoop(irLoop: IrLoop): IrLoop {
return irLoop
}
override fun visitVariable(declaration: IrVariable): IrVariable {
val variable = super.visitVariable(declaration)
variable.descriptor.let { if (it is WrappedVariableDescriptor) it.bind(variable) }
return variable
}
},
null
) as T
@@ -58,7 +58,7 @@ data class IrValidatorConfig(
class IrValidator(val context: CommonBackendContext, val config: IrValidatorConfig) : IrElementVisitorVoid {
val builtIns = context.builtIns
val irBuiltIns = context.irBuiltIns
var currentFile: IrFile? = null
override fun visitFile(declaration: IrFile) {
@@ -79,7 +79,7 @@ class IrValidator(val context: CommonBackendContext, val config: IrValidatorConf
}
}
private val elementChecker = CheckIrElementVisitor(builtIns, this::error, config)
private val elementChecker = CheckIrElementVisitor(irBuiltIns, this::error, config)
override fun visitElement(element: IrElement) {
element.acceptVoid(elementChecker)
@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
import org.jetbrains.kotlin.backend.common.descriptors.*
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.builders.IrStatementsBuilder
import org.jetbrains.kotlin.ir.builders.Scope
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
@@ -61,34 +60,6 @@ fun ir2stringWhole(ir: IrElement?, withDescriptors: Boolean = false): String {
return strWriter.toString()
}
fun DeclarationDescriptor.createFakeOverrideDescriptor(owner: ClassDescriptor): DeclarationDescriptor? {
// We need to copy descriptors for vtable building, thus take only functions and properties.
return when (this) {
is CallableMemberDescriptor ->
copy(
/* newOwner = */ owner,
/* modality = */ modality,
/* visibility = */ visibility,
/* kind = */ CallableMemberDescriptor.Kind.FAKE_OVERRIDE,
/* copyOverrides = */ true
).apply {
overriddenDescriptors += this@createFakeOverrideDescriptor
}
else -> null
}
}
fun FunctionDescriptor.createOverriddenDescriptor(owner: ClassDescriptor, final: Boolean = true): FunctionDescriptor {
return this.newCopyBuilder()
.setOwner(owner)
.setCopyOverrides(true)
.setModality(if (final) Modality.FINAL else Modality.OPEN)
.setDispatchReceiverParameter(owner.thisAsReceiverParameter)
.build()!!.apply {
overriddenDescriptors += this@createOverriddenDescriptor
}
}
fun IrClass.addSimpleDelegatingConstructor(
superConstructor: IrConstructor,
irBuiltIns: IrBuiltIns,
@@ -311,11 +282,6 @@ fun IrDeclarationContainer.addChild(declaration: IrDeclaration) {
declaration.accept(SetDeclarationsParentVisitor, this)
}
fun <T: IrElement> T.setDeclarationsParent(parent: IrDeclarationParent): T {
accept(SetDeclarationsParentVisitor, parent)
return this
}
object SetDeclarationsParentVisitor : IrElementVisitor<Unit, IrDeclarationParent> {
override fun visitElement(element: IrElement, data: IrDeclarationParent) {
if (element !is IrDeclarationParent) {
@@ -336,14 +302,6 @@ val IrFunction.isStatic: Boolean
val IrDeclaration.isTopLevel: Boolean
get() = parent is IrPackageFragment
fun <T : IrElement> IrStatementsBuilder<T>.irTemporaryWithWrappedDescriptor(
value: IrExpression,
nameHint: String? = null): IrVariable {
val temporary = scope.createTemporaryVariableWithWrappedDescriptor(value, nameHint)
+temporary
return temporary
}
fun Scope.createTemporaryVariableWithWrappedDescriptor(
irExpression: IrExpression,
@@ -357,8 +315,6 @@ fun Scope.createTemporaryVariableWithWrappedDescriptor(
).apply { descriptor.bind(this) }
}
val IrFunction.isOverridable: Boolean get() = this is IrSimpleFunction && this.isOverridable
fun IrClass.createImplicitParameterDeclarationWithWrappedDescriptor() {
val thisReceiverDescriptor = WrappedReceiverParameterDescriptor()
thisReceiver = IrValueParameterImpl(
@@ -122,7 +122,7 @@ open class DefaultArgumentStubGenerator(
irGet(parameter)
}
val temporaryVariable = irTemporary(argument, nameHint = parameter.name.asString())
val temporaryVariable = createTmpVariable(argument, nameHint = parameter.name.asString())
temporaryVariable.parent = newIrFunction
params.add(temporaryVariable)
@@ -6,28 +6,23 @@
package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.backend.common.descriptors.synthesizedName
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
import org.jetbrains.kotlin.backend.common.descriptors.WrappedVariableDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
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.descriptors.IrTemporaryVariableDescriptorImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrReturnTargetSymbol
import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.isNothing
import org.jetbrains.kotlin.types.typeUtil.isUnit
class FinallyBlocksLowering(val context: CommonBackendContext, private val throwableType: IrType): FileLoweringPass, IrElementTransformerVoidWithContext() {
@@ -65,7 +60,7 @@ class FinallyBlocksLowering(val context: CommonBackendContext, private val throw
private abstract class Scope
private class ReturnableScope(val descriptor: CallableDescriptor): Scope()
private class ReturnableScope(val symbol: IrReturnTargetSymbol) : Scope()
private class LoopScope(val loop: IrLoop): Scope()
@@ -92,7 +87,7 @@ class FinallyBlocksLowering(val context: CommonBackendContext, private val throw
}
override fun visitFunctionNew(declaration: IrFunction): IrStatement {
using(ReturnableScope(declaration.descriptor)) {
using(ReturnableScope(declaration.symbol)) {
return super.visitFunctionNew(declaration)
}
}
@@ -101,7 +96,7 @@ class FinallyBlocksLowering(val context: CommonBackendContext, private val throw
if (expression !is IrReturnableBlockImpl)
return super.visitContainerExpression(expression)
using(ReturnableScope(expression.descriptor)) {
using(ReturnableScope(expression.symbol)) {
return super.visitContainerExpression(expression)
}
}
@@ -121,7 +116,7 @@ class FinallyBlocksLowering(val context: CommonBackendContext, private val throw
jump = Break(jump.loop),
startOffset = startOffset,
endOffset = endOffset,
value = irBuilder.irGetObject(context.ir.symbols.unit)
value = irBuilder.irGetObject(context.irBuiltIns.unitClass)
) ?: jump
}
@@ -134,7 +129,7 @@ class FinallyBlocksLowering(val context: CommonBackendContext, private val throw
jump = Continue(jump.loop),
startOffset = startOffset,
endOffset = endOffset,
value = irBuilder.irGetObject(context.ir.symbols.unit)
value = irBuilder.irGetObject(context.irBuiltIns.unitClass)
) ?: jump
}
@@ -142,7 +137,7 @@ class FinallyBlocksLowering(val context: CommonBackendContext, private val throw
expression.transformChildrenVoid(this)
return performHighLevelJump(
targetScopePredicate = { it is ReturnableScope && it.descriptor == expression.returnTarget },
targetScopePredicate = { it is ReturnableScope && it.symbol == expression.returnTargetSymbol },
jump = Return(expression.returnTargetSymbol),
startOffset = expression.startOffset,
endOffset = expression.endOffset,
@@ -186,7 +181,8 @@ class FinallyBlocksLowering(val context: CommonBackendContext, private val throw
val currentTryScope = tryScopes[index]
currentTryScope.jumps.getOrPut(jump) {
val type = (jump as? Return)?.target?.owner?.returnType ?: value.type
val symbol = getIrReturnableBlockSymbol(jump.toString(), type)
jump.toString()
val symbol = IrReturnableBlockSymbolImpl(WrappedSimpleFunctionDescriptor())
with(currentTryScope) {
irBuilder.run {
val inlinedFinally = irInlineFinally(symbol, type, expression, finallyExpression)
@@ -226,15 +222,13 @@ class FinallyBlocksLowering(val context: CommonBackendContext, private val throw
type = context.irBuiltIns.unitType
)
val transformedFinallyExpression = finallyExpression.transform(transformer, null)
val parameter = IrTemporaryVariableDescriptorImpl(
containingDeclaration = currentScope!!.scope.scopeOwner,
name = Name.identifier("t"),
outType = throwableType.toKotlinType()
)
val parameter = WrappedVariableDescriptor()
val catchParameter = IrVariableImpl(
startOffset, endOffset, IrDeclarationOrigin.CATCH_PARAMETER, parameter,
throwableType
)
startOffset, endOffset, IrDeclarationOrigin.CATCH_PARAMETER, IrVariableSymbolImpl(parameter),
Name.identifier("t"), throwableType, isVar = false, isConst = false, isLateinit = false
).also { parameter.bind(it) }
catchParameter.parent = scope.getLocalDeclarationParent()
val syntheticTry = IrTryImpl(
startOffset = startOffset,
@@ -252,7 +246,7 @@ class FinallyBlocksLowering(val context: CommonBackendContext, private val throw
)
using(TryScope(syntheticTry, transformedFinallyExpression, this)) {
val fallThroughType = aTry.type
val fallThroughSymbol = getIrReturnableBlockSymbol("fallThrough", fallThroughType)
val fallThroughSymbol = IrReturnableBlockSymbolImpl(WrappedSimpleFunctionDescriptor())
val transformedResult = aTry.tryResult.transform(transformer, null)
transformedTry.tryResult = irReturn(fallThroughSymbol, transformedResult)
for (aCatch in aTry.catches) {
@@ -269,16 +263,16 @@ class FinallyBlocksLowering(val context: CommonBackendContext, private val throw
value: IrExpression,
finallyExpression: IrExpression
): IrExpression {
val returnType = symbol.descriptor.returnType!!
return when {
returnType.isUnit() || returnType.isNothing() -> irBlock(value, null, type) {
val returnTypeClassifier = (type as? IrSimpleType)?.classifier
return when (returnTypeClassifier) {
context.irBuiltIns.unitClass, context.irBuiltIns.nothingClass -> irBlock(value, null, type) {
+irReturnableBlock(symbol, type) {
+value
}
+finallyExpression.copy()
}
else -> irComposite(value, null, type) {
val tmp = irTemporary(irReturnableBlock(symbol, type) {
else -> irBlock(value, null, type) {
val tmp = createTmpVariable(irReturnableBlock(symbol, type) {
+irReturn(symbol, value)
})
+finallyExpression.copy()
@@ -287,29 +281,12 @@ class FinallyBlocksLowering(val context: CommonBackendContext, private val throw
}
}
private fun getFakeFunctionDescriptor(name: String, returnType: KotlinType) =
SimpleFunctionDescriptorImpl.create(
currentScope!!.scope.scopeOwner,
Annotations.EMPTY,
name.synthesizedName,
CallableMemberDescriptor.Kind.SYNTHESIZED,
SourceElement.NO_SOURCE
).apply {
initialize(null, null, emptyList(), emptyList(), returnType,
Modality.ABSTRACT,
Visibilities.PRIVATE
)
}
private fun getIrReturnableBlockSymbol(name: String, returnType: IrType): IrReturnableBlockSymbol =
IrReturnableBlockSymbolImpl(getFakeFunctionDescriptor(name, returnType.toKotlinType()))
private inline fun <reified T : IrElement> T.copy() = this.deepCopyWithVariables()
fun IrBuilderWithScope.irReturn(target: IrReturnTargetSymbol, value: IrExpression) =
IrReturnImpl(startOffset, endOffset, context.irBuiltIns.nothingType, target, value)
inline fun IrBuilderWithScope.irReturnableBlock(symbol: IrReturnableBlockSymbol, type: IrType, body: IrBlockBuilder.() -> Unit) =
private inline fun IrBuilderWithScope.irReturnableBlock(symbol: IrReturnableBlockSymbol, type: IrType, body: IrBlockBuilder.() -> Unit) =
IrReturnableBlockImpl(
startOffset, endOffset, type, symbol, null,
IrBlockBuilder(context, scope, startOffset, endOffset, null, type, true)
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -61,7 +60,7 @@ class InlineClassLowering(val context: BackendContext) {
// Secondary ctors of inline class must delegate to some other constructors.
// Use these delegating call later to initialize this variable.
lateinit var thisVar: IrVariable
val parameterMapping = result.valueParameters.associateBy { it ->
val parameterMapping = result.valueParameters.associateBy {
irConstructor.valueParameters[it.index].symbol
}
@@ -70,9 +69,8 @@ class InlineClassLowering(val context: BackendContext) {
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
expression.transformChildrenVoid()
return irBlock(expression) {
thisVar = irTemporary(
thisVar = createTmpVariable(
expression,
typeHint = irClass.defaultType.toKotlinType(),
irType = irClass.defaultType
)
thisVar.parent = result
@@ -19,28 +19,20 @@ package org.jetbrains.kotlin.backend.common.lower
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.atMostOne
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.ir.IrStatement
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.builders.irTemporary
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.IrSymbolDeclaration
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrStringConcatenation
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.isNullableAny
import org.jetbrains.kotlin.ir.types.toIrType
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType
/**
@@ -56,11 +48,9 @@ private class StringConcatenationTransformer(val lower: StringConcatenationLower
private val buildersStack = mutableListOf<IrBuilderWithScope>()
private val context = lower.context
private val builtIns = context.builtIns
private val irBuiltIns = context.irBuiltIns
private val typesWithSpecialAppendFunction =
PrimitiveType.values().map { builtIns.getPrimitiveKotlinType(it).toIrType()!! } + irBuiltIns.stringType
private val typesWithSpecialAppendFunction = irBuiltIns.primitiveIrTypes + irBuiltIns.stringType
private val nameToString = Name.identifier("toString")
private val nameAppend = Name.identifier("append")
@@ -87,7 +77,7 @@ private class StringConcatenationTransformer(val lower: StringConcatenationLower
type to stringBuilder.functions.toList().atMostOne {
it.name == nameAppend &&
it.valueParameters.size == 1 &&
it.valueParameters.single().type.toKotlinType() == type
it.valueParameters.single().type.isEqualTo(type)
}
}.toMap()
@@ -101,7 +91,7 @@ private class StringConcatenationTransformer(val lower: StringConcatenationLower
expression.transformChildrenVoid(this)
val blockBuilder = buildersStack.last()
return blockBuilder.irBlock(expression) {
val stringBuilderImpl = irTemporary(irCall(constructor))
val stringBuilderImpl = createTmpVariable(irCall(constructor))
expression.arguments.forEach { arg ->
val appendFunction = typeToAppendFunction(arg.type)
+irCall(appendFunction).apply {
@@ -60,7 +60,7 @@ private fun lowerTailRecursionCalls(context: BackendContext, irFunction: IrFunct
irFunction.body = builder.irBlockBody {
// Define variables containing current values of parameters:
val parameterToVariable = parameters.associate {
it to irTemporaryVar(irGet(it), nameHint = it.symbol.suggestVariableName())
it to createTmpVariable(irGet(it), nameHint = it.symbol.suggestVariableName(), isMutable = true)
}
// (these variables are to be updated on any tail call).
@@ -72,7 +72,7 @@ private fun lowerTailRecursionCalls(context: BackendContext, irFunction: IrFunct
// Read variables containing current values of parameters:
val parameterToNew = parameters.associate {
val variable = parameterToVariable[it]!!
it to irTemporary(irGet(variable), nameHint = it.symbol.suggestVariableName())
it to createTmpVariable(irGet(variable), nameHint = it.symbol.suggestVariableName())
}
val transformer = BodyTransformer(
@@ -1,15 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.utils
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.toKotlinType
// TODO: implement pure Ir-based function (see IrTypeUtils.kt)
@Deprecated("Use pure Ir helper")
fun IrType.getPrimitiveArrayElementType() = KotlinBuiltIns.getPrimitiveArrayElementType(toKotlinType())
@@ -16,11 +16,20 @@
package org.jetbrains.kotlin.ir.builders
import org.jetbrains.kotlin.backend.common.descriptors.WrappedVariableDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
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.impl.IrVariableSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.name.Name
fun IrBuilderWithScope.irWhile(origin: IrStatementOrigin? = null) =
IrWhileLoopImpl(startOffset, endOffset, context.irBuiltIns.unitType, origin)
@@ -33,3 +42,43 @@ fun IrBuilderWithScope.irContinue(loop: IrLoop) =
fun IrBuilderWithScope.irGetObject(classSymbol: IrClassSymbol) =
IrGetObjectValueImpl(startOffset, endOffset, IrSimpleTypeImpl(classSymbol, false, emptyList(), emptyList()), classSymbol)
// Also adds created variable into building block
fun <T : IrElement> IrStatementsBuilder<T>.createTmpVariable(
irExpression: IrExpression,
nameHint: String? = null,
isMutable: Boolean = false,
origin: IrDeclarationOrigin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
irType: IrType? = null
): IrVariable {
val variable = scope.createTmpVariable(irExpression, nameHint, isMutable, origin, irType)
+variable
return variable
}
fun Scope.createTmpVariable(
irExpression: IrExpression,
nameHint: String? = null,
isMutable: Boolean = false,
origin: IrDeclarationOrigin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
irType: IrType? = null
): IrVariable {
val varType = irType ?: irExpression.type
val descriptor = WrappedVariableDescriptor()
val symbol = IrVariableSymbolImpl(descriptor)
return IrVariableImpl(
irExpression.startOffset,
irExpression.endOffset,
origin,
symbol,
Name.identifier(nameHint ?: "tmp"),
varType,
isMutable,
false,
false
).apply {
initializer = irExpression
parent = getLocalDeclarationParent()
descriptor.bind(this)
}
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.ir.util
import org.jetbrains.kotlin.backend.common.ir.fqName
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES
import org.jetbrains.kotlin.builtins.UnsignedTypes
import org.jetbrains.kotlin.descriptors.ClassKind
@@ -81,3 +82,7 @@ private inline fun IrType.isTypeFromKotlinPackage(namePredicate: (Name) -> Boole
}
fun IrType.isPrimitiveArray() = isTypeFromKotlinPackage { it in FQ_NAMES.primitiveArrayTypeShortNames }
fun IrType.getPrimitiveArrayElementType() = (this as? IrSimpleType)?.let {
(it.classifier.owner as? IrClass)?.fqName?.toUnsafe()?.let { fqn -> FQ_NAMES.arrayClassFqNameToPrimitiveType[fqn] }
}
@@ -29,26 +29,22 @@ import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.types.impl.IrDynamicTypeImpl
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
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.createDynamicType
class JsIrBackendContext(
val module: ModuleDescriptorImpl,
override val irBuiltIns: IrBuiltIns,
val symbolTable: SymbolTable,
irModuleFragment: IrModuleFragment,
override val configuration: CompilerConfiguration,
val compilationMode: CompilationMode
override val configuration: CompilerConfiguration
) : CommonBackendContext {
override val builtIns = module.builtIns
@@ -142,9 +138,9 @@ class JsIrBackendContext(
return numbers + listOf(Name.identifier("String"))
}
val dynamicType = IrDynamicTypeImpl(createDynamicType(builtIns), emptyList(), Variance.INVARIANT)
val dynamicType = IrDynamicTypeImpl(null, emptyList(), Variance.INVARIANT)
fun getOperatorByName(name: Name, type: KotlinType) = operatorMap[name]?.get(type)
fun getOperatorByName(name: Name, type: IrSimpleType) = operatorMap[name]?.get(type.classifier)
override val ir = object : Ir<JsIrBackendContext>(this, irModuleFragment) {
override val symbols = object : Symbols<JsIrBackendContext>(this@JsIrBackendContext, symbolTable.lazyWrapper) {
@@ -254,14 +250,18 @@ class JsIrBackendContext(
val throwableConstructors by lazy { throwableClass.owner.declarations.filterIsInstance<IrConstructor>().map { it.symbol } }
val defaultThrowableCtor by lazy { throwableConstructors.single { it.owner.valueParameters.size == 0 } }
private fun referenceOperators() = OperatorNames.ALL.map { name ->
// TODO to replace KotlinType with IrType we need right equals on IrType
name to irBuiltIns.primitiveTypes.fold(mutableMapOf<KotlinType, IrFunctionSymbol>()) { m, t ->
val function = t.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND).singleOrNull()
function?.let { m.put(t, symbolTable.referenceSimpleFunction(it)) }
m
}
}.toMap()
private fun referenceOperators(): Map<Name, MutableMap<IrClassifierSymbol, IrSimpleFunctionSymbol>> {
val primitiveIrSymbols = irBuiltIns.primitiveIrTypes.map { it.classifierOrFail as IrClassSymbol }
return OperatorNames.ALL.map { name ->
// TODO to replace KotlinType with IrType we need right equals on IrType
name to primitiveIrSymbols.fold(mutableMapOf<IrClassifierSymbol, IrSimpleFunctionSymbol>()) { m, s ->
val function = s.owner.declarations.filterIsInstance<IrSimpleFunction>().singleOrNull { it.name == name }
function?.let { m.put(s, it.symbol) }
m
}
}.toMap()
}
private fun findClass(memberScope: MemberScope, name: Name): ClassDescriptor =
memberScope.getContributedClassifier(name, NoLookupLocation.FROM_BACKEND) as ClassDescriptor
@@ -19,7 +19,6 @@ import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.backend.common.serialization.DescriptorTable
import org.jetbrains.kotlin.ir.backend.js.lower.inline.replaceUnboundSymbols
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsDeclarationTable
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrModuleSerializer
@@ -28,7 +27,6 @@ import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.JsKlibMet
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.JsKlibMetadataSerializationUtil
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.JsKlibMetadataVersion
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.createJsKlibMetadataPackageFragmentProvider
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.*
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.*
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
@@ -169,7 +167,7 @@ fun compile(
return TranslationResult.CompiledKlib
}
val context = JsIrBackendContext(moduleDescriptor, irBuiltIns, symbolTable, moduleFragment, configuration, compileMode)
val context = JsIrBackendContext(moduleDescriptor, irBuiltIns, symbolTable, moduleFragment, configuration)
deserializedModuleFragments.forEach {
ExternalDependenciesGenerator(
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.ir.backend.js.ir
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.name.Name
class JsIrArithBuilder(val context: JsIrBackendContext) {
@@ -16,7 +16,7 @@ class JsIrArithBuilder(val context: JsIrBackendContext) {
val symbols = context.ir.symbols
private fun buildBinaryOperator(name: Name, l: IrExpression, r: IrExpression): IrExpression {
val symbol = context.getOperatorByName(name, l.type.toKotlinType())
val symbol = context.getOperatorByName(name, l.type as IrSimpleType)
return JsIrBuilder.buildCall(symbol!!).apply {
dispatchReceiver = l
putValueArgument(0, r)
@@ -24,7 +24,7 @@ class JsIrArithBuilder(val context: JsIrBackendContext) {
}
private fun buildUnaryOperator(name: Name, v: IrExpression): IrExpression {
val symbol = context.getOperatorByName(name, v.type.toKotlinType())!!
val symbol = context.getOperatorByName(name, v.type as IrSimpleType)!!
return JsIrBuilder.buildCall(symbol).apply { dispatchReceiver = v }
}
@@ -12,10 +12,8 @@ import org.jetbrains.kotlin.backend.common.descriptors.WrappedVariableDescriptor
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.Scope
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
@@ -30,7 +28,6 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.Variance
@@ -73,8 +70,8 @@ object JsIrBuilder {
index,
type,
null,
false,
false
isCrossinline = false,
isNoinline = false
).also {
descriptor.bind(it)
}
@@ -107,7 +104,7 @@ object JsIrBuilder {
isTailrec: Boolean = false,
isSuspend: Boolean = false,
origin: IrDeclarationOrigin = SYNTHESIZED_DECLARATION
) = JsIrBuilder.buildFunction(
) = buildFunction(
Name.identifier(name),
returnType,
parent,
@@ -155,8 +152,6 @@ object JsIrBuilder {
fun buildGetObjectValue(type: IrType, classSymbol: IrClassSymbol) =
IrGetObjectValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, classSymbol)
fun buildGetClass(expression: IrExpression, type: IrType) = IrGetClassImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, expression)
fun buildGetValue(symbol: IrValueSymbol) =
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol.owner.type, symbol, SYNTHESIZED_STATEMENT)
@@ -255,7 +250,7 @@ object JsIrBuilder {
IrTypeOperatorCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, operator, toType, symbol, argument)
fun buildImplicitCast(value: IrExpression, toType: IrType) =
JsIrBuilder.buildTypeOperator(toType, IrTypeOperator.IMPLICIT_CAST, value, toType, toType.classifierOrFail)
buildTypeOperator(toType, IrTypeOperator.IMPLICIT_CAST, value, toType, toType.classifierOrFail)
fun buildNull(type: IrType) = IrConstImpl.constNull(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type)
@@ -265,55 +260,10 @@ object JsIrBuilder {
fun buildCatch(ex: IrVariable, block: IrBlockImpl) = IrCatchImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, ex, block)
}
object SetDeclarationsParentVisitor : IrElementVisitor<Unit, IrDeclarationParent> {
override fun visitElement(element: IrElement, data: IrDeclarationParent) {
if (element !is IrDeclarationParent) {
element.acceptChildren(this, data)
}
}
override fun visitDeclaration(declaration: IrDeclaration, data: IrDeclarationParent) {
declaration.parent = data
super.visitDeclaration(declaration, data)
}
}
fun IrDeclarationContainer.addChild(declaration: IrDeclaration) {
this.declarations += declaration
declaration.accept(SetDeclarationsParentVisitor, this)
}
fun IrClass.simpleFunctions(): List<IrSimpleFunction> = this.declarations.flatMap {
when (it) {
is IrSimpleFunction -> listOf(it)
is IrProperty -> listOfNotNull(it.getter, it.setter)
else -> emptyList()
}
}
fun Scope.createTmpVariable(
irExpression: IrExpression,
nameHint: String? = null,
isMutable: Boolean = false,
origin: IrDeclarationOrigin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE,
irType: IrType? = null
): IrVariable {
val varType = irType ?: irExpression.type
val descriptor = WrappedVariableDescriptor()
val symbol = IrVariableSymbolImpl(descriptor)
return IrVariableImpl(
irExpression.startOffset,
irExpression.endOffset,
origin,
symbol,
Name.identifier(nameHint ?: "tmp"),
varType,
isMutable,
false,
false
).apply {
initializer = irExpression
parent = getLocalDeclarationParent()
descriptor.bind(this)
}
}
@@ -62,7 +62,7 @@ class AutoboxingTransformer(val context: JsIrBackendContext) : AbstractValueUsag
}
// // TODO: Default parameters are passed as nulls and they need not to be unboxed. Fix this
if (actualType.makeNotNull(false).isNothing())
if (actualType.makeNotNull().isNothing())
return this
val expectedType = type
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.backend.common.bridges.findInterfaceImplementation
import org.jetbrains.kotlin.backend.common.bridges.generateBridges
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny
import org.jetbrains.kotlin.backend.common.ir.isSuspend
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irBlockBody
@@ -62,7 +63,7 @@ class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass {
private fun generateBridges(function: IrSimpleFunction, irClass: IrClass) {
// equals(Any?), hashCode(), toString() never need bridges
if (DescriptorUtils.isMethodOfAny(function.descriptor))
if (function.isMethodOfAny())
return
val bridgesToGenerate = generateBridges(
@@ -167,8 +168,7 @@ class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass {
// Handle for common.bridges
data class IrBasedFunctionHandle(val function: IrSimpleFunction) : FunctionHandle {
override val isDeclaration: Boolean = function.isReal || findInterfaceImplementation(function.descriptor) != null
override val isDeclaration = function.run { isReal || findInterfaceImplementation() != null }
override val isAbstract: Boolean =
function.modality == Modality.ABSTRACT
@@ -136,7 +136,7 @@ class ClassReferenceLowering(val context: JsIrBackendContext) : FileLoweringPass
override fun visitClassReference(expression: IrClassReference) =
callGetKClass(
returnType = expression.type,
typeArgument = expression.classType.makeNotNull(false)
typeArgument = expression.classType.makeNotNull()
)
})
}
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.backend.js.ir.createTmpVariable
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
@@ -413,7 +412,7 @@ class EnumClassTransformer(val context: JsIrBackendContext, private val irClass:
}
private fun createEnumEntryInstanceVariables() = enumEntries.map { enumEntry ->
val type = enumEntry.getType(irClass).makeNullable(false)
val type = enumEntry.getType(irClass).makeNullable()
val name = "${enumName}_${enumEntry.name.identifier}_instance"
val result = builder.run {
scope.createTmpVariable(irImplicitCast(irNull(), type), name)
@@ -5,9 +5,9 @@
package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.ir.addChild
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.lower.inline.addChild
import org.jetbrains.kotlin.ir.backend.js.utils.getJsModule
import org.jetbrains.kotlin.ir.backend.js.utils.getJsQualifier
import org.jetbrains.kotlin.ir.declarations.*
@@ -131,7 +131,7 @@ class ThrowableSuccessorsLowering(val context: JsIrBackendContext) : FileLowerin
else -> {
val arg = expression.getValueArgument(0)!!
when {
arg.type.makeNotNull(false).isThrowable() -> Pair(nullValue(), arg)
arg.type.makeNotNull().isThrowable() -> Pair(nullValue(), arg)
else -> Pair(arg, nullValue())
}
}
@@ -307,7 +307,7 @@ class ThrowableSuccessorsLowering(val context: JsIrBackendContext) : FileLowerin
val irVal = JsIrBuilder.buildVar(arg.type, parent, initializer = arg)
val argValue = JsIrBuilder.buildGetValue(irVal.symbol)
when {
arg.type.makeNotNull(false).isThrowable() -> Triple(safeCallToString(irVal), argValue, listOf(irVal))
arg.type.makeNotNull().isThrowable() -> Triple(safeCallToString(irVal), argValue, listOf(irVal))
else -> Triple(argValue, nullValue(), listOf(irVal))
}
}
@@ -6,7 +6,6 @@
package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.utils.getPrimitiveArrayElementType
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrArithBuilder
@@ -186,7 +185,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
}
}
val toNotNullable = toType.makeNotNull(false)
val toNotNullable = toType.makeNotNull()
val argumentInstance = argument()
val instanceCheck = generateTypeCheckNonNull(argumentInstance, toNotNullable)
val isFromNullable = argumentInstance.type.isNullable()
@@ -247,7 +246,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
// TODO either remove functions with reified type parameters or support this case
// assert(!typeParameter.isReified) { "reified parameters have to be lowered before" }
return typeParameter.superTypes.fold(litTrue) { r, t ->
val check = generateTypeCheckNonNull(argument.copy(), t.makeNotNull(false))
val check = generateTypeCheckNonNull(argument.copy(), t.makeNotNull())
calculator.and(r, check)
}
}
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.SimpleType
@@ -68,16 +67,11 @@ internal class SimpleMemberKey(val klass: IrType, val name: Name) {
other as SimpleMemberKey
if (name != other.name) return false
if (klass.originalKotlinType != other.klass.originalKotlinType) return false
return true
return klass.isEqualTo(other.klass)
}
override fun hashCode(): Int {
var result = klass.originalKotlinType?.hashCode() ?: 0
result = 31 * result + name.hashCode()
return result
}
override fun hashCode() = 31 * klass.toHashCode() + name.hashCode()
}
enum class PrimitiveType {
@@ -88,7 +82,7 @@ enum class PrimitiveType {
OTHER
}
fun IrType.getPrimitiveType() = makeNotNull(false).run {
fun IrType.getPrimitiveType() = makeNotNull().run {
when {
isBoolean() -> PrimitiveType.BOOLEAN
isByte() || isShort() || isInt() -> PrimitiveType.INTEGER_NUMBER
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.*
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.backend.js.lower.coroutines
import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.backend.common.descriptors.*
import org.jetbrains.kotlin.backend.common.ir.addChild
import org.jetbrains.kotlin.backend.common.ir.copyParameterDeclarationsFrom
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.isSuspend
@@ -19,7 +20,6 @@ import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.backend.js.ir.addChild
import org.jetbrains.kotlin.ir.backend.js.ir.simpleFunctions
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.*
@@ -5,53 +5,20 @@
package org.jetbrains.kotlin.ir.backend.js.lower.inline
import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.backend.common.IrElementVisitorVoidWithContext
import org.jetbrains.kotlin.backend.common.descriptors.*
import org.jetbrains.kotlin.backend.common.lower.SimpleMemberScope
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.*
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.*
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.expressions.IrCall
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.*
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.resolve.DescriptorFactory
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperInterfaces
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
internal fun KotlinType?.createExtensionReceiver(owner: CallableDescriptor): ReceiverParameterDescriptor? =
DescriptorFactory.createExtensionReceiverParameterForCallable(
owner,
this,
Annotations.EMPTY
)
fun ReferenceSymbolTable.translateErased(type: KotlinType): IrSimpleType {
val descriptor = TypeUtils.getClassDescriptor(type) ?: return translateErased(type.immediateSupertypes().first())
val classSymbol = this.referenceClass(descriptor)
val nullable = type.isMarkedNullable
val arguments = type.arguments.map { IrStarProjectionImpl }
return classSymbol.createType(nullable, arguments)
}
internal class DeepCopyIrTreeWithSymbolsForInliner(val context: Context,
val typeArguments: Map<IrTypeParameterSymbol, IrType?>?,
@@ -32,7 +32,6 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
import org.jetbrains.kotlin.ir.types.irTypeKotlinBuiltIns
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
@@ -46,7 +45,6 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
//-------------------------------------------------------------------------//
fun inline(irModule: IrModuleFragment): IrElement {
irTypeKotlinBuiltIns = irModule.irBuiltins.builtIns
return irModule.accept(this, data = null)
}
@@ -1,53 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.backend.js.lower.inline
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer
import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
// backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/ir/util/IrUtils2.kt
fun IrSimpleFunction.setOverrides(symbolTable: SymbolTable) {
assert(this.overriddenSymbols.isEmpty())
this.descriptor.overriddenDescriptors.mapTo(this.overriddenSymbols) {
symbolTable.referenceSimpleFunction(it.original)
}
}
fun IrDeclarationContainer.addChildren(declarations: List<IrDeclaration>) {
declarations.forEach { this.addChild(it) }
}
fun IrDeclarationContainer.addChild(declaration: IrDeclaration) {
this.declarations += declaration
declaration.accept(SetDeclarationsParentVisitor, this)
}
object SetDeclarationsParentVisitor : IrElementVisitor<Unit, IrDeclarationParent> {
override fun visitElement(element: IrElement, data: IrDeclarationParent) {
if (element !is IrDeclarationParent) {
element.acceptChildren(this, data)
}
}
override fun visitDeclaration(declaration: IrDeclaration, data: IrDeclarationParent) {
declaration.parent = data
super.visitDeclaration(declaration, data)
}
}
@Deprecated("Do not use descriptor-based utils")
val CallableMemberDescriptor.propertyIfAccessor
get() = if (this is PropertyAccessorDescriptor)
this.correspondingProperty
else this
@@ -1,78 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.backend.js.lower.inline
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
import org.jetbrains.kotlin.builtins.getFunctionalClassKind
import org.jetbrains.kotlin.builtins.isFunctionType
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.util.isFunctionOrKFunction
import org.jetbrains.kotlin.ir.util.isFunctionTypeOrSubtype
import org.jetbrains.kotlin.ir.util.isKFunction
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.OverridingUtil
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.util.OperatorNameConventions
// backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/LegacyDescriptorUtils.kt
/**
* Implementation of given method.
*
* TODO: this method is actually a part of resolve and probably duplicates another one
*/
internal fun <T : CallableMemberDescriptor> T.resolveFakeOverride(): T {
if (this.kind.isReal) {
return this
} else {
val overridden = OverridingUtil.getOverriddenDeclarations(this)
val filtered = OverridingUtil.filterOutOverridden(overridden)
// TODO: is it correct to take first?
@Suppress("UNCHECKED_CAST")
return filtered.first { it.modality != Modality.ABSTRACT } as T
}
}
internal val KotlinType.isKFunctionType: Boolean
get() {
val kind = constructor.declarationDescriptor?.getFunctionalClassKind()
return kind == FunctionClassDescriptor.Kind.KFunction
}
internal val FunctionDescriptor.isFunctionInvoke: Boolean
get() {
val dispatchReceiver = dispatchReceiverParameter ?: return false
assert(!dispatchReceiver.type.isKFunctionType)
return dispatchReceiver.type.isFunctionType &&
this.isOperator && this.name == OperatorNameConventions.INVOKE
}
internal val IrFunction.isFunctionInvoke: Boolean
get() {
// val dispatchReceiver = dispatchReceiverParameter ?: return false
// assert(!dispatchReceiver.type.isKFunction())
//
// return dispatchReceiver.type.isFunctionTypeOrSubtype() &&
// /*this.isOperator &&*/ this.name == OperatorNameConventions.INVOKE
return descriptor is FunctionInvokeDescriptor
}
// It is possible to declare "external inline fun",
// but it doesn't have much sense for native,
// since externals don't have IR bodies.
// Enforce inlining of constructors annotated with @InlineConstructor.
// TODO: should we keep this?
private val inlineConstructor = FqName("konan.internal.InlineConstructor")
internal val FunctionDescriptor.needsInlining: Boolean
get() {
val inlineConstructor = annotations.hasAnnotation(inlineConstructor)
if (inlineConstructor) return true
return (this.isInline && !this.isExternal)
}
@@ -1,67 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.backend.js.lower.inline
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
// backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ir/ModuleIndex.kt
class ModuleIndex(val module: IrModuleFragment) {
var currentFile: IrFile? = null
/**
* Contains all classes declared in [module]
*/
val classes = mutableMapOf<ClassDescriptor, IrClass>()
val enumEntries = mutableMapOf<ClassDescriptor, IrEnumEntry>()
/**
* Contains all functions declared in [module]
*/
val functions = mutableMapOf<FunctionDescriptor, IrFunction>()
init {
addModule(module)
}
fun addModule(module: IrModuleFragment) {
module.acceptVoid(object : IrElementVisitorVoid {
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
override fun visitFile(declaration: IrFile) {
currentFile = declaration
super.visitFile(declaration)
}
override fun visitClass(declaration: IrClass) {
super.visitClass(declaration)
classes[declaration.descriptor] = declaration
}
override fun visitEnumEntry(declaration: IrEnumEntry) {
super.visitEnumEntry(declaration)
enumEntries[declaration.descriptor] = declaration
}
override fun visitFunction(declaration: IrFunction) {
super.visitFunction(declaration)
functions[declaration.descriptor] = declaration
}
})
}
}
@@ -100,7 +100,7 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
val vararg = IrVarargImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
context.ir.symbols.array.typeWith(),
context.ir.symbols.any.typeWith(),
context.irBuiltIns.anyClass.typeWith(),
(0 until argumentsCount).map { i -> expression.getValueArgument(i)!! }
)
val invokeFun = context.getIrClass(FqName("kotlin.jvm.functions.FunctionN")).owner.declarations.single {
@@ -170,6 +170,8 @@ class IrBuiltIns(
val throwableType by lazy { builtIns.throwable.defaultType.toIrType() }
val throwableClass by lazy { builtIns.throwable.toIrSymbol() }
val primitiveIrTypes by lazy { listOf(booleanType, charType, byteType, shortType, intType, floatType, longType, doubleType) }
val kCallableClass = builtIns.getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.kCallable.toSafe()).toIrSymbol()
val kPropertyClass = builtIns.getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.kPropertyFqName.toSafe()).toIrSymbol()
@@ -43,6 +43,24 @@ fun IrType.isEqualTo(that: IrType): Boolean {
return false
}
fun IrTypeArgument.toHashCode(): Int = when (this) {
is IrTypeProjection -> 31 * type.toHashCode() + variance.hashCode()
is IrStarProjection -> hashCode()
else -> 0
}
fun IrType.toHashCode(): Int {
if (this is IrDynamicType) return -1
if (this is IrErrorType) return 0
require(this is IrSimpleType)
var result = classifier.hashCode()
result = 31 * result + arguments.fold(0) { a, t -> 31 * a + t.toHashCode() }
return 31 * result + if (hasQuestionMark) 1 else 0
}
fun Collection<IrClassifierSymbol>.commonSuperclass(): IrClassifierSymbol {
var superClassifiers: MutableSet<IrClassifierSymbol>? = null
@@ -56,7 +56,7 @@ fun makeTypeProjection(type: IrType, variance: Variance): IrTypeProjection =
when {
type is IrTypeProjection && type.variance == variance -> type
type is IrSimpleType -> IrSimpleTypeImpl(type, variance)
type is IrDynamicType -> IrDynamicTypeImpl(type.originalKotlinType, type.annotations, variance)
type is IrErrorType -> IrErrorTypeImpl(type.originalKotlinType, type.annotations, variance)
type is IrDynamicType -> IrDynamicTypeImpl(null, type.annotations, variance)
type is IrErrorType -> IrErrorTypeImpl(null, type.annotations, variance)
else -> IrTypeProjectionImpl(type, variance)
}
@@ -7,17 +7,12 @@ package org.jetbrains.kotlin.ir.types
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.util.getFqName
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.resolve.DescriptorUtils.getFqName
private fun IrType.isBuiltInClassType(descriptorPredicate: (ClassDescriptor) -> Boolean, hasQuestionMark: Boolean): Boolean {
if (this !is IrSimpleType) return false
if (this.hasQuestionMark != hasQuestionMark) return false
val classSymbol = this.classifier as? IrClassSymbol ?: return false
return descriptorPredicate(classSymbol.descriptor)
}
private fun IrType.isNotNullClassType(fqName: FqNameUnsafe) = isClassType(fqName, hasQuestionMark = false)
private fun IrType.isNullableClassType(fqName: FqNameUnsafe) = isClassType(fqName, hasQuestionMark = true)
@@ -25,25 +20,29 @@ private fun IrType.isClassType(fqName: FqNameUnsafe, hasQuestionMark: Boolean):
if (this !is IrSimpleType) return false
if (this.hasQuestionMark != hasQuestionMark) return false
val classSymbol = this.classifier as? IrClassSymbol ?: return false
return classFqNameEquals(classSymbol.descriptor, fqName)
return classFqNameEquals(classSymbol, fqName)
}
private fun classFqNameEquals(symbol: IrClassSymbol, fqName: FqNameUnsafe): Boolean =
if (symbol.isBound) classFqNameEquals(symbol.owner, fqName) else classFqNameEquals(symbol.descriptor, fqName)
private fun classFqNameEquals(declaration: IrClass, fqName: FqNameUnsafe): Boolean =
declaration.name == fqName.shortName() && fqName == declaration.getFqName()?.toUnsafe()
private fun classFqNameEquals(descriptor: ClassDescriptor, fqName: FqNameUnsafe): Boolean =
descriptor.name == fqName.shortName() && fqName == getFqName(descriptor)
fun IrType.isAny(): Boolean = isBuiltInClassType(KotlinBuiltIns::isAny, hasQuestionMark = false)
fun IrType.isNullableAny(): Boolean = isBuiltInClassType(KotlinBuiltIns::isAny, hasQuestionMark = true)
fun IrType.isAny(): Boolean = isNotNullClassType(KotlinBuiltIns.FQ_NAMES.any)
fun IrType.isNullableAny(): Boolean = isNullableClassType(KotlinBuiltIns.FQ_NAMES.any)
fun IrType.isString(): Boolean = isNotNullClassType(KotlinBuiltIns.FQ_NAMES.string)
fun IrType.isNullableString(): Boolean = isNullableClassType(KotlinBuiltIns.FQ_NAMES.string)
fun IrType.isArray(): Boolean = isNotNullClassType(KotlinBuiltIns.FQ_NAMES.array)
fun IrType.isCollection(): Boolean = isNotNullClassType(KotlinBuiltIns.FQ_NAMES.collection.toUnsafe())
fun IrType.isNothing(): Boolean = isNotNullClassType(KotlinBuiltIns.FQ_NAMES.nothing)
fun IrType.isPrimitiveType(): Boolean =
isBuiltInClassType(KotlinBuiltIns::isPrimitiveClass, hasQuestionMark = false)
fun IrType.isNullablePrimitiveType(): Boolean =
isBuiltInClassType(KotlinBuiltIns::isPrimitiveClass, hasQuestionMark = true)
fun IrType.isPrimitiveType(): Boolean = KotlinBuiltIns.FQ_NAMES.fqNameToPrimitiveType.keys.any { isNotNullClassType(it) }
fun IrType.isNullablePrimitiveType(): Boolean = KotlinBuiltIns.FQ_NAMES.fqNameToPrimitiveType.keys.any { isNullableClassType(it) }
fun IrType.isMarkedNullable() = (this as? IrSimpleType)?.hasQuestionMark ?: false
@@ -5,11 +5,9 @@
package org.jetbrains.kotlin.ir.types
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
@@ -19,6 +17,8 @@ import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.impl.*
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
import org.jetbrains.kotlin.types.typeUtil.makeNullable
import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -29,7 +29,7 @@ fun IrType.withHasQuestionMark(hasQuestionMark: Boolean): IrType =
this
else
IrSimpleTypeImpl(
makeKotlinType(classifier, arguments, hasQuestionMark),
originalKotlinType?.run { if (hasQuestionMark) makeNullable() else makeNotNullable() },
classifier,
hasQuestionMark,
arguments,
@@ -44,23 +44,23 @@ val IrType.classifierOrFail: IrClassifierSymbol
val IrType.classifierOrNull: IrClassifierSymbol?
get() = safeAs<IrSimpleType>()?.classifier
fun IrType.makeNotNull(addKotlinType:Boolean = true) =
if (this is IrSimpleType && this.hasQuestionMark)
fun IrType.makeNotNull() =
if (this is IrSimpleType && this.hasQuestionMark) {
IrSimpleTypeImpl(
if (addKotlinType) makeKotlinType(classifier, arguments, false) else null,
originalKotlinType?.makeNotNullable(),
classifier,
false,
arguments,
annotations,
Variance.INVARIANT
)
else
} else
this
fun IrType.makeNullable(addKotlinType:Boolean = true) =
fun IrType.makeNullable() =
if (this is IrSimpleType && !this.hasQuestionMark)
IrSimpleTypeImpl(
if (addKotlinType) makeKotlinType(classifier, arguments, true) else null,
originalKotlinType?.makeNullable(),
classifier,
true,
arguments,
@@ -70,9 +70,6 @@ fun IrType.makeNullable(addKotlinType:Boolean = true) =
else
this
// TODO: get rid of this
var irTypeKotlinBuiltIns: KotlinBuiltIns? = null
fun IrType.toKotlinType(): KotlinType {
originalKotlinType?.let {
return it
@@ -80,7 +77,6 @@ fun IrType.toKotlinType(): KotlinType {
return when (this) {
is IrSimpleType -> makeKotlinType(classifier, arguments, hasQuestionMark)
is IrDynamicType -> createDynamicType(irTypeKotlinBuiltIns!!)
else -> TODO(toString())
}
}
@@ -137,7 +133,7 @@ fun IrClassifierSymbol.typeWith(arguments: List<IrType>): IrSimpleType =
fun IrClass.typeWith(arguments: List<IrType>) = this.symbol.typeWith(arguments)
fun KotlinType.toIrType(symbolTable: SymbolTable? = null): IrType? {
if (isDynamic()) return IrDynamicTypeImpl(this, listOf(), Variance.INVARIANT)
if (isDynamic()) return IrDynamicTypeImpl(null, listOf(), Variance.INVARIANT)
val symbol = constructor.declarationDescriptor?.getSymbol(symbolTable) ?: return null
@@ -151,7 +147,7 @@ fun KotlinType.toIrType(symbolTable: SymbolTable? = null): IrType? {
// TODO
val annotations = listOf()
return IrSimpleTypeImpl(this, symbol, isMarkedNullable, arguments, annotations)
return IrSimpleTypeImpl(null, symbol, isMarkedNullable, arguments, annotations)
}
// TODO: this function creates unbound symbol which is the great source of problems
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.IrTypeProjection
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.IrTypeProjectionImpl
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
class DeepCopyTypeRemapper(
private val symbolRemapper: SymbolRemapper
@@ -43,7 +42,7 @@ class DeepCopyTypeRemapper(
val annotations = type.annotations.map { it.transform(deepCopy, null) as IrCall }
return IrSimpleTypeImpl(
type.originalKotlinType,
null,
symbolRemapper.getReferencedClassifier(type.classifier),
type.hasQuestionMark,
arguments,
@@ -6,22 +6,19 @@
package org.jetbrains.kotlin.ir.util
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
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.IrFieldImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
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.symbols.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.types.isAny
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.name.FqName
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.descriptorUtil.fqNameSafe
@@ -164,110 +161,9 @@ fun IrExpression.coerceToUnitIfNeeded(valueType: KotlinType, irBuiltIns: IrBuilt
fun IrMemberAccessExpression.usesDefaultArguments(): Boolean =
this.descriptor.valueParameters.any { this.getValueArgument(it) == null }
fun IrFunction.createParameterDeclarations(symbolTable: SymbolTable? = null) {
fun ParameterDescriptor.irValueParameter() = IrValueParameterImpl(
innerStartOffset(this), innerEndOffset(this),
IrDeclarationOrigin.DEFINED,
this,
type.toIrType(symbolTable)!!,
(this as? ValueParameterDescriptor)?.varargElementType?.toIrType(symbolTable)
).also {
it.parent = this@createParameterDeclarations
}
dispatchReceiverParameter = descriptor.dispatchReceiverParameter?.irValueParameter()
extensionReceiverParameter = descriptor.extensionReceiverParameter?.irValueParameter()
assert(valueParameters.isEmpty())
descriptor.valueParameters.mapTo(valueParameters) { it.irValueParameter() }
assert(typeParameters.isEmpty())
descriptor.typeParameters.mapTo(typeParameters) {
IrTypeParameterImpl(
innerStartOffset(it), innerEndOffset(it),
IrDeclarationOrigin.DEFINED,
it
).also { typeParameter ->
typeParameter.parent = this
}
}
}
fun IrClass.createParameterDeclarations() {
thisReceiver = IrValueParameterImpl(
startOffset, endOffset,
IrDeclarationOrigin.INSTANCE_RECEIVER,
descriptor.thisAsReceiverParameter,
this.symbol.typeWith(this.typeParameters.map { it.defaultType }),
null
).also { valueParameter ->
valueParameter.parent = this
}
assert(typeParameters.isEmpty())
assert(descriptor.declaredTypeParameters.isEmpty())
}
//fun IrClass.createParameterDeclarations() {
// descriptor.thisAsReceiverParameter.let {
// thisReceiver = IrValueParameterImpl(
// innerStartOffset(it), innerEndOffset(it),
// IrDeclarationOrigin.INSTANCE_RECEIVER,
// it
// )
// }
//
// assert(typeParameters.isEmpty())
// descriptor.declaredTypeParameters.mapTo(typeParameters) {
// IrTypeParameterImpl(
// innerStartOffset(it), innerEndOffset(it),
// IrDeclarationOrigin.DEFINED,
// it
// )
// }
//}
//
//fun IrClass.addFakeOverrides() {
//
// val startOffset = this.startOffset
// val endOffset = this.endOffset
//
// fun FunctionDescriptor.createFunction(): IrSimpleFunction = 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
private fun IrElement.innerEndOffset(descriptor: DeclarationDescriptorWithSource): Int =
descriptor.endOffset ?: this.endOffset
val DeclarationDescriptorWithSource.startOffset: Int? get() = (this.source as? PsiSourceElement)?.psi?.startOffset
val DeclarationDescriptorWithSource.endOffset: Int? get() = (this.source as? PsiSourceElement)?.psi?.endOffset
val DeclarationDescriptorWithSource.startOffsetOrUndefined: Int get() = startOffset ?: UNDEFINED_OFFSET
val DeclarationDescriptorWithSource.endOffsetOrUndefined: Int get() = endOffset ?: UNDEFINED_OFFSET
val IrClassSymbol.functions: Sequence<IrSimpleFunctionSymbol>
get() = this.owner.declarations.asSequence().filterIsInstance<IrSimpleFunction>().map { it.symbol }
@@ -291,9 +187,9 @@ val IrClass.defaultType: IrSimpleType
val IrSimpleFunction.isReal: Boolean get() = descriptor.kind.isReal
fun IrClass.isImmediateSubClassOf(ancestor: IrClass) = ancestor.symbol in superTypes.mapNotNull {
(it as? IrSimpleType)?.classifier
}
val IrSimpleFunction.isSynthesized: Boolean get() = descriptor.kind == CallableMemberDescriptor.Kind.SYNTHESIZED
val IrSimpleFunction.isFakeOverride: Boolean get() = origin == IrDeclarationOrigin.FAKE_OVERRIDE
fun IrClass.isSubclassOf(ancestor: IrClass): Boolean {
@@ -350,6 +246,22 @@ fun IrSimpleFunction.resolveFakeOverride(): IrSimpleFunction? {
return collectRealOverrides().singleOrNull { it.modality != Modality.ABSTRACT }
}
fun IrSimpleFunction.isOrOverridesSynthesized(): Boolean {
if (isSynthesized) return true
if (isFakeOverride) return overriddenSymbols.all { it.owner.isOrOverridesSynthesized() }
return false
}
fun IrSimpleFunction.findInterfaceImplementation(): IrSimpleFunction? {
if (isReal) return null
if (isOrOverridesSynthesized()) return null
return resolveFakeOverride()?.run { if (parentAsClass.isInterface) this else null }
}
fun IrField.resolveFakeOverride(): IrField? {
var toVisit = setOf(this)
val nonOverridden = mutableSetOf<IrField>()
@@ -443,39 +355,6 @@ fun IrValueParameter.copy(newDescriptor: ParameterDescriptor): IrValueParameter
)
}
fun createField(
startOffset: Int,
endOffset: Int,
type: IrType,
name: Name,
isMutable: Boolean,
origin: IrDeclarationOrigin,
owner: ClassDescriptor
): IrField {
val descriptor = PropertyDescriptorImpl.create(
/* containingDeclaration = */ owner,
/* annotations = */ Annotations.EMPTY,
/* modality = */ Modality.FINAL,
/* visibility = */ Visibilities.PRIVATE,
/* isVar = */ isMutable,
/* name = */ name,
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
/* source = */ SourceElement.NO_SOURCE,
/* lateInit = */ false,
/* isConst = */ false,
/* isExpect = */ false,
/* isActual = */ false,
/* isExternal = */ false,
/* isDelegated = */ false
).apply {
initialize(null, null)
setType(type.toKotlinType(), emptyList(), owner.thisAsReceiverParameter, null)
}
return IrFieldImpl(startOffset, endOffset, origin, descriptor, type)
}
// In presence of `IrBlock`s, return the expression that actually serves as the value (the last one).
tailrec fun IrExpression.removeBlocks(): IrExpression? = when (this) {
is IrBlock -> (statements.last() as? IrExpression)?.removeBlocks()