KNVE: support in JVM_IR and JS_IR
This commit is contained in:
@@ -232,6 +232,9 @@ abstract class Symbols<out T : CommonBackendContext>(val context: T, symbolTable
|
||||
|
||||
abstract val ThrowUninitializedPropertyAccessException: IrSimpleFunctionSymbol
|
||||
|
||||
open val ThrowKotlinNothingValueException: IrSimpleFunctionSymbol
|
||||
get() = TODO("Support KotlinNothingValueException in Kotlin/Native and make this val abstract")
|
||||
|
||||
abstract val stringBuilder: IrClassSymbol
|
||||
|
||||
abstract val defaultConstructorMarker: IrClassSymbol
|
||||
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||
import org.jetbrains.kotlin.ir.builders.irCall
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSymbolDeclaration
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.types.isNothing
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
|
||||
class KotlinNothingValueExceptionLowering(val backendContext: CommonBackendContext) : BodyLoweringPass {
|
||||
override fun lower(irBody: IrBody, container: IrDeclaration) {
|
||||
irBody.transformChildrenVoid(
|
||||
Transformer((container as IrSymbolDeclaration<*>).symbol)
|
||||
)
|
||||
}
|
||||
|
||||
private inner class Transformer(val parent: IrSymbol) : IrElementTransformerVoid() {
|
||||
override fun visitCall(expression: IrCall): IrExpression =
|
||||
if (expression.type.isNothing()) {
|
||||
// Replace call 'foo' of type 'kotlin.Nothing' with a block:
|
||||
//
|
||||
// {
|
||||
// [ call 'foo' with type: 'kotlin.Unit' ]
|
||||
// call ThrowKotlinNothingValueException(): Nothing
|
||||
// }: Nothing
|
||||
//
|
||||
// Changing type of 'foo' to 'kotlin.Unit' is requires so that the 'ThrowKotlinNothingValueException(): Nothing'
|
||||
// is not considered dead code and is not removed.
|
||||
// Note that type 'kotlin.Nothing' might be inferred in some cases of projected types.
|
||||
// See KT-30330 for an example of such code where call of type 'kotlin.Nothing' terminates and produces some value
|
||||
// (although doing so by subverting the type system).
|
||||
backendContext.createIrBuilder(parent, expression.startOffset, expression.endOffset).run {
|
||||
irBlock(expression, null, context.irBuiltIns.nothingType) {
|
||||
+changeTypeToUnit(expression)
|
||||
+irCall(backendContext.ir.symbols.ThrowKotlinNothingValueException)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
expression
|
||||
}
|
||||
|
||||
private fun changeTypeToUnit(call: IrCall): IrCall =
|
||||
IrCallImpl(
|
||||
call.startOffset, call.endOffset,
|
||||
backendContext.irBuiltIns.unitType,
|
||||
call.symbol,
|
||||
call.typeArgumentsCount, call.valueArgumentsCount, call.origin, call.superQualifierSymbol
|
||||
).also { newCall ->
|
||||
for (i in 0 until call.typeArgumentsCount) {
|
||||
newCall.putTypeArgument(i, call.getTypeArgument(i))
|
||||
}
|
||||
newCall.dispatchReceiver = call.dispatchReceiver
|
||||
newCall.extensionReceiver = call.extensionReceiver
|
||||
for (i in 0 until call.valueArgumentsCount) {
|
||||
newCall.putValueArgument(i, call.getValueArgument(i))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -194,6 +194,9 @@ class JsIrBackendContext(
|
||||
override val ThrowUninitializedPropertyAccessException =
|
||||
symbolTable.referenceSimpleFunction(getFunctions(FqName("kotlin.throwUninitializedPropertyAccessException")).single())
|
||||
|
||||
override val ThrowKotlinNothingValueException: IrSimpleFunctionSymbol =
|
||||
symbolTable.referenceSimpleFunction(getFunctions(FqName("kotlin.throwKotlinNothingValueException")).single())
|
||||
|
||||
override val defaultConstructorMarker =
|
||||
symbolTable.referenceClass(context.getJsInternalClass("DefaultConstructorMarker"))
|
||||
|
||||
@@ -215,7 +218,8 @@ class JsIrBackendContext(
|
||||
|
||||
override val coroutineContextGetter = symbolTable.referenceSimpleFunction(context.coroutineContextProperty.getter!!)
|
||||
|
||||
override val suspendCoroutineUninterceptedOrReturn = symbolTable.referenceSimpleFunction(getJsInternalFunction(COROUTINE_SUSPEND_OR_RETURN_JS_NAME))
|
||||
override val suspendCoroutineUninterceptedOrReturn =
|
||||
symbolTable.referenceSimpleFunction(getJsInternalFunction(COROUTINE_SUSPEND_OR_RETURN_JS_NAME))
|
||||
|
||||
override val coroutineGetContext = symbolTable.referenceSimpleFunction(getJsInternalFunction(GET_COROUTINE_CONTEXT_NAME))
|
||||
|
||||
|
||||
@@ -159,6 +159,12 @@ private val lateinitUsageLoweringPhase = makeBodyLoweringPhase(
|
||||
description = "Insert checks for lateinit field references"
|
||||
)
|
||||
|
||||
private val kotlinNothingValueExceptionPhase = makeBodyLoweringPhase(
|
||||
::KotlinNothingValueExceptionLowering,
|
||||
name = "KotlinNothingValueException",
|
||||
description = "Throw proper exception for calls returning value of type 'kotlin.Nothing'"
|
||||
)
|
||||
|
||||
private val stripTypeAliasDeclarationsPhase = makeDeclarationTransformerPhase(
|
||||
{ StripTypeAliasDeclarationsLowering() },
|
||||
name = "StripTypeAliasDeclarations",
|
||||
@@ -638,6 +644,7 @@ val loweringList = listOf<Lowering>(
|
||||
annotationConstructorLowering,
|
||||
initializersLoweringPhase,
|
||||
initializersCleanupLoweringPhase,
|
||||
kotlinNothingValueExceptionPhase,
|
||||
// Common prefix ends
|
||||
enumEntryInstancesLoweringPhase,
|
||||
enumEntryInstancesBodyLoweringPhase,
|
||||
|
||||
@@ -118,7 +118,8 @@ internal val localDeclarationsPhase = makeIrFilePhase<CommonBackendContext>(
|
||||
override fun forClass(declaration: IrClass, inInlineFunctionScope: Boolean): Visibility =
|
||||
if (declaration.origin == JvmLoweredDeclarationOrigin.LAMBDA_IMPL ||
|
||||
declaration.origin == JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL ||
|
||||
declaration.origin == JvmLoweredDeclarationOrigin.GENERATED_PROPERTY_REFERENCE) {
|
||||
declaration.origin == JvmLoweredDeclarationOrigin.GENERATED_PROPERTY_REFERENCE
|
||||
) {
|
||||
scopedVisibility(inInlineFunctionScope)
|
||||
} else {
|
||||
declaration.visibility
|
||||
@@ -255,12 +256,17 @@ private val syntheticAccessorPhase = makeIrFilePhase(
|
||||
prerequisite = setOf(objectClassPhase, staticDefaultFunctionPhase, interfacePhase)
|
||||
)
|
||||
|
||||
private val tailrecPhase = makeIrFilePhase<JvmBackendContext>(
|
||||
private val tailrecPhase = makeIrFilePhase(
|
||||
::JvmTailrecLowering,
|
||||
name = "Tailrec",
|
||||
description = "Handle tailrec calls"
|
||||
)
|
||||
|
||||
private val kotlinNothingValueExceptionPhase = makeIrFilePhase(
|
||||
::KotlinNothingValueExceptionLowering,
|
||||
name = "KotlinNothingValueException",
|
||||
description = "Throw proper exception for calls returning value of type 'kotlin.Nothing'"
|
||||
)
|
||||
|
||||
@Suppress("Reformat")
|
||||
private val jvmFilePhases =
|
||||
@@ -353,10 +359,11 @@ private val jvmFilePhases =
|
||||
jvmArgumentNullabilityAssertions then
|
||||
toArrayPhase then
|
||||
jvmOptimizationLoweringPhase then
|
||||
ifNullExpressionsFusionPhase then
|
||||
ifNullExpressionsFusionPhase then
|
||||
additionalClassAnnotationPhase then
|
||||
typeOperatorLowering then
|
||||
replaceKFunctionInvokeWithFunctionInvokePhase then
|
||||
kotlinNothingValueExceptionPhase then
|
||||
|
||||
checkLocalNamesWithOldBackendPhase then
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:Suppress("PropertyName")
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ir.Symbols
|
||||
@@ -21,7 +23,6 @@ import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrPackageFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
@@ -76,11 +77,12 @@ class JvmSymbols(
|
||||
override val ThrowTypeCastException: IrFunctionSymbol =
|
||||
typeCastExceptionClass.constructors.single()
|
||||
|
||||
private val unsupportedOperationExceptionClass: IrClassSymbol = createClass(FqName("java.lang.UnsupportedOperationException")) { klass ->
|
||||
klass.addConstructor().apply {
|
||||
addValueParameter("message", irBuiltIns.stringType.makeNullable())
|
||||
private val unsupportedOperationExceptionClass: IrClassSymbol =
|
||||
createClass(FqName("java.lang.UnsupportedOperationException")) { klass ->
|
||||
klass.addConstructor().apply {
|
||||
addValueParameter("message", irBuiltIns.stringType.makeNullable())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val ThrowUnsupportOperationExceptionClass: IrFunctionSymbol =
|
||||
unsupportedOperationExceptionClass.constructors.single()
|
||||
@@ -679,6 +681,15 @@ class JvmSymbols(
|
||||
|
||||
val runSuspendFunction: IrSimpleFunctionSymbol =
|
||||
kotlinCoroutinesJvmInternalRunSuspendKt.functionByName("runSuspend")
|
||||
|
||||
override val ThrowKotlinNothingValueException: IrSimpleFunctionSymbol =
|
||||
buildFun {
|
||||
name = Name.identifier("ThrowKotlinNothingValueException")
|
||||
origin = IrDeclarationOrigin.IR_BUILTINS_STUB
|
||||
returnType = irBuiltIns.nothingType
|
||||
}.apply {
|
||||
parent = kotlinJvmInternalPackage
|
||||
}.symbol
|
||||
}
|
||||
|
||||
private fun IrClassSymbol.functionByName(name: String): IrSimpleFunctionSymbol =
|
||||
|
||||
-2
@@ -451,8 +451,6 @@ class ExpressionCodegen(
|
||||
|
||||
return when {
|
||||
expression.type.isNothing() -> {
|
||||
mv.aconst(null)
|
||||
mv.athrow()
|
||||
unitValue
|
||||
}
|
||||
expression is IrConstructorCall ->
|
||||
|
||||
+2
-1
@@ -112,7 +112,8 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
|
||||
irBuiltIns.dataClassArrayMemberToStringSymbol.toKey()!! to IrDataClassArrayMemberToString,
|
||||
symbols.unsafeCoerceIntrinsic.toKey()!! to UnsafeCoerce,
|
||||
symbols.signatureStringIntrinsic.toKey()!! to SignatureString,
|
||||
symbols.reassignParameterIntrinsic.toKey()!! to ReassignParameter
|
||||
symbols.reassignParameterIntrinsic.toKey()!! to ReassignParameter,
|
||||
symbols.ThrowKotlinNothingValueException.toKey()!! to ThrowKotlinNothingValueException
|
||||
) +
|
||||
numberConversionMethods() +
|
||||
unaryFunForPrimitives("plus", UnaryPlus) +
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* 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.jvm.intrinsics
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
object ThrowKotlinNothingValueException : IntrinsicMethod() {
|
||||
override fun toCallable(
|
||||
expression: IrFunctionAccessExpression,
|
||||
signature: JvmMethodSignature,
|
||||
context: JvmBackendContext
|
||||
): IrIntrinsicFunction =
|
||||
IrIntrinsicFunction.create(expression, signature, context) { mv ->
|
||||
if (context.state.useKotlinNothingValueException) {
|
||||
mv.anew(Type.getObjectType("kotlin/KotlinNothingValueException"))
|
||||
mv.dup()
|
||||
mv.invokespecial("kotlin/KotlinNothingValueException", "<init>", "()V", false)
|
||||
} else {
|
||||
mv.aconst(null)
|
||||
}
|
||||
mv.athrow()
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,8 @@ class WasmSymbols(
|
||||
get() = TODO()
|
||||
override val ThrowUninitializedPropertyAccessException
|
||||
get() = TODO()
|
||||
override val ThrowKotlinNothingValueException: IrSimpleFunctionSymbol
|
||||
get() = TODO()
|
||||
override val defaultConstructorMarker
|
||||
get() = TODO()
|
||||
override val stringBuilder
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// IGNORE_BACKEND: JS, JS_IR, JVM_IR, NATIVE
|
||||
// IGNORE_BACKEND: JS, NATIVE
|
||||
|
||||
fun <T> something(): T = Any() as T
|
||||
|
||||
|
||||
@@ -9,6 +9,10 @@ package kotlin
|
||||
internal fun throwUninitializedPropertyAccessException(name: String): Nothing =
|
||||
throw UninitializedPropertyAccessException("lateinit property $name has not been initialized")
|
||||
|
||||
@PublishedApi
|
||||
internal fun throwKotlinNothingValueException(): Nothing =
|
||||
throw KotlinNothingValueException()
|
||||
|
||||
internal fun noWhenBranchMatchedException(): Nothing = throw NoWhenBranchMatchedException()
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user