JVM_IR: deal with inline class default values in AddContinuationLowering.
Whenever we want the default 0/null value for a type we need to check if it is a non-nullable inline class type and produce the right value for the underlying type.
This commit is contained in:
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.jvm.codegen.isInlineOnly
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.isJvmInterface
|
||||
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmDeclarationFactory
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.hasMangledParameters
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.unboxInlineClass
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
@@ -20,6 +21,8 @@ import org.jetbrains.kotlin.ir.builders.Scope
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
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.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
@@ -88,6 +91,25 @@ val IrType.erasedUpperBound: IrClass
|
||||
else -> throw IllegalStateException()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default null/0 value for the type.
|
||||
*
|
||||
* This handles unboxing of non-nullable inline class types to their underlying types and produces
|
||||
* a null/0 default value for the resulting type. When such unboxing takes place it ensures that
|
||||
* the value is not reboxed and reunboxed by the codegen by using the unsafeCoerceIntrinsic.
|
||||
*/
|
||||
fun IrType.defaultValue(startOffset: Int, endOffset: Int, context: JvmBackendContext): IrExpression {
|
||||
if (this !is IrSimpleType || hasQuestionMark || classOrNull?.owner?.isInline != true)
|
||||
return IrConstImpl.defaultValueForType(startOffset, endOffset, this)
|
||||
|
||||
val underlyingType = unboxInlineClass()
|
||||
val defaultValueForUnderlyingType = IrConstImpl.defaultValueForType(startOffset, endOffset, underlyingType)
|
||||
return IrCallImpl(startOffset, endOffset, this, context.ir.symbols.unsafeCoerceIntrinsic).also {
|
||||
it.putTypeArgument(0, underlyingType) // from
|
||||
it.putTypeArgument(1, this) // to
|
||||
it.putValueArgument(0, defaultValueForUnderlyingType)
|
||||
}
|
||||
}
|
||||
|
||||
fun IrDeclaration.getJvmNameFromAnnotation(): String? {
|
||||
// TODO lower @JvmName?
|
||||
|
||||
+12
-11
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.IrInlineReferenceLocator
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.defaultValue
|
||||
import org.jetbrains.kotlin.codegen.coroutines.*
|
||||
import org.jetbrains.kotlin.codegen.inline.coroutines.FOR_INLINE_SUFFIX
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
@@ -23,7 +24,6 @@ import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
|
||||
@@ -446,6 +446,7 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
||||
capturedThisField: IrField?,
|
||||
isStaticSuspendImpl: Boolean
|
||||
) {
|
||||
val backendContext = context
|
||||
val invokeSuspend = context.ir.symbols.continuationImplClass.owner.functions
|
||||
.single { it.name == Name.identifier(INVOKE_SUSPEND_METHOD_NAME) }
|
||||
addFunctionOverride(invokeSuspend).also { function ->
|
||||
@@ -481,15 +482,12 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
||||
it.dispatchReceiver = capturedThisValue
|
||||
}
|
||||
irFunction.extensionReceiverParameter?.let { extensionReceiverParameter ->
|
||||
it.extensionReceiver = IrConstImpl.defaultValueForType(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, extensionReceiverParameter.type
|
||||
it.extensionReceiver = extensionReceiverParameter.type.defaultValue(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, backendContext
|
||||
)
|
||||
}
|
||||
for ((i, parameter) in irFunction.valueParameters.withIndex()) {
|
||||
val defaultValueForParameter = IrConstImpl.defaultValueForType(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, parameter.type
|
||||
)
|
||||
it.putValueArgument(i, defaultValueForParameter)
|
||||
it.putValueArgument(i, parameter.type.defaultValue(UNDEFINED_OFFSET, UNDEFINED_OFFSET, backendContext))
|
||||
}
|
||||
if (isStaticSuspendImpl) {
|
||||
it.putValueArgument(0, capturedThisValue)
|
||||
@@ -501,6 +499,7 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
||||
|
||||
private fun createStaticSuspendImpl(irFunction: IrSimpleFunction): IrSimpleFunction {
|
||||
// Create static suspend impl method.
|
||||
val backendContext = context
|
||||
val static = createStaticFunctionWithReceivers(
|
||||
irFunction.parent,
|
||||
irFunction.name.toSuspendImplementationName(),
|
||||
@@ -520,12 +519,14 @@ private class AddContinuationLowering(private val context: JvmBackendContext) :
|
||||
it.putValueArgument(i++, irGet(irFunction.dispatchReceiverParameter!!))
|
||||
}
|
||||
if (irFunction.extensionReceiverParameter != null) {
|
||||
it.putValueArgument(i++, irNull())
|
||||
val defaultValueForParameter = irFunction.extensionReceiverParameter!!.type.defaultValue(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, backendContext
|
||||
)
|
||||
it.putValueArgument(i++, defaultValueForParameter)
|
||||
|
||||
}
|
||||
for (parameter in irFunction.valueParameters) {
|
||||
val defaultValueForParameter = IrConstImpl.defaultValueForType(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, parameter.type
|
||||
)
|
||||
val defaultValueForParameter = parameter.type.defaultValue(UNDEFINED_OFFSET, UNDEFINED_OFFSET, backendContext)
|
||||
it.putValueArgument(i++, defaultValueForParameter)
|
||||
}
|
||||
})
|
||||
|
||||
+2
-13
@@ -7,15 +7,12 @@ package org.jetbrains.kotlin.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.lower.DefaultParameterInjector
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.defaultValue
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.getJvmVisibilityOfDefaultArgumentStub
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.unboxInlineClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||
|
||||
class JvmDefaultParameterInjector(context: JvmBackendContext) :
|
||||
DefaultParameterInjector(context, skipInline = false, skipExternalMethods = false) {
|
||||
@@ -26,15 +23,7 @@ class JvmDefaultParameterInjector(context: JvmBackendContext) :
|
||||
nullConst(startOffset, endOffset, irParameter.type)
|
||||
|
||||
override fun nullConst(startOffset: Int, endOffset: Int, type: IrType): IrExpression {
|
||||
if (type !is IrSimpleType || type.hasQuestionMark || type.classOrNull?.owner?.isInline != true)
|
||||
return super.nullConst(startOffset, endOffset, type)
|
||||
|
||||
val underlyingType = type.unboxInlineClass()
|
||||
return IrCallImpl(startOffset, endOffset, type, context.ir.symbols.unsafeCoerceIntrinsic).apply {
|
||||
putTypeArgument(0, underlyingType) // from
|
||||
putTypeArgument(1, type) // to
|
||||
putValueArgument(0, super.nullConst(startOffset, endOffset, underlyingType))
|
||||
}
|
||||
return type.defaultValue(startOffset, endOffset, context)
|
||||
}
|
||||
|
||||
override fun defaultArgumentStubVisibility(function: IrFunction) = function.getJvmVisibilityOfDefaultArgumentStub()
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// WITH_COROUTINES
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_BACKEND: JVM_IR, JS_IR
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
|
||||
import helpers.*
|
||||
import kotlin.coroutines.*
|
||||
|
||||
Reference in New Issue
Block a user