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
|
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 stringBuilder: IrClassSymbol
|
||||||
|
|
||||||
abstract val defaultConstructorMarker: 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 =
|
override val ThrowUninitializedPropertyAccessException =
|
||||||
symbolTable.referenceSimpleFunction(getFunctions(FqName("kotlin.throwUninitializedPropertyAccessException")).single())
|
symbolTable.referenceSimpleFunction(getFunctions(FqName("kotlin.throwUninitializedPropertyAccessException")).single())
|
||||||
|
|
||||||
|
override val ThrowKotlinNothingValueException: IrSimpleFunctionSymbol =
|
||||||
|
symbolTable.referenceSimpleFunction(getFunctions(FqName("kotlin.throwKotlinNothingValueException")).single())
|
||||||
|
|
||||||
override val defaultConstructorMarker =
|
override val defaultConstructorMarker =
|
||||||
symbolTable.referenceClass(context.getJsInternalClass("DefaultConstructorMarker"))
|
symbolTable.referenceClass(context.getJsInternalClass("DefaultConstructorMarker"))
|
||||||
|
|
||||||
@@ -215,7 +218,8 @@ class JsIrBackendContext(
|
|||||||
|
|
||||||
override val coroutineContextGetter = symbolTable.referenceSimpleFunction(context.coroutineContextProperty.getter!!)
|
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))
|
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"
|
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(
|
private val stripTypeAliasDeclarationsPhase = makeDeclarationTransformerPhase(
|
||||||
{ StripTypeAliasDeclarationsLowering() },
|
{ StripTypeAliasDeclarationsLowering() },
|
||||||
name = "StripTypeAliasDeclarations",
|
name = "StripTypeAliasDeclarations",
|
||||||
@@ -638,6 +644,7 @@ val loweringList = listOf<Lowering>(
|
|||||||
annotationConstructorLowering,
|
annotationConstructorLowering,
|
||||||
initializersLoweringPhase,
|
initializersLoweringPhase,
|
||||||
initializersCleanupLoweringPhase,
|
initializersCleanupLoweringPhase,
|
||||||
|
kotlinNothingValueExceptionPhase,
|
||||||
// Common prefix ends
|
// Common prefix ends
|
||||||
enumEntryInstancesLoweringPhase,
|
enumEntryInstancesLoweringPhase,
|
||||||
enumEntryInstancesBodyLoweringPhase,
|
enumEntryInstancesBodyLoweringPhase,
|
||||||
|
|||||||
@@ -118,7 +118,8 @@ internal val localDeclarationsPhase = makeIrFilePhase<CommonBackendContext>(
|
|||||||
override fun forClass(declaration: IrClass, inInlineFunctionScope: Boolean): Visibility =
|
override fun forClass(declaration: IrClass, inInlineFunctionScope: Boolean): Visibility =
|
||||||
if (declaration.origin == JvmLoweredDeclarationOrigin.LAMBDA_IMPL ||
|
if (declaration.origin == JvmLoweredDeclarationOrigin.LAMBDA_IMPL ||
|
||||||
declaration.origin == JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL ||
|
declaration.origin == JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL ||
|
||||||
declaration.origin == JvmLoweredDeclarationOrigin.GENERATED_PROPERTY_REFERENCE) {
|
declaration.origin == JvmLoweredDeclarationOrigin.GENERATED_PROPERTY_REFERENCE
|
||||||
|
) {
|
||||||
scopedVisibility(inInlineFunctionScope)
|
scopedVisibility(inInlineFunctionScope)
|
||||||
} else {
|
} else {
|
||||||
declaration.visibility
|
declaration.visibility
|
||||||
@@ -255,12 +256,17 @@ private val syntheticAccessorPhase = makeIrFilePhase(
|
|||||||
prerequisite = setOf(objectClassPhase, staticDefaultFunctionPhase, interfacePhase)
|
prerequisite = setOf(objectClassPhase, staticDefaultFunctionPhase, interfacePhase)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val tailrecPhase = makeIrFilePhase<JvmBackendContext>(
|
private val tailrecPhase = makeIrFilePhase(
|
||||||
::JvmTailrecLowering,
|
::JvmTailrecLowering,
|
||||||
name = "Tailrec",
|
name = "Tailrec",
|
||||||
description = "Handle tailrec calls"
|
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")
|
@Suppress("Reformat")
|
||||||
private val jvmFilePhases =
|
private val jvmFilePhases =
|
||||||
@@ -353,10 +359,11 @@ private val jvmFilePhases =
|
|||||||
jvmArgumentNullabilityAssertions then
|
jvmArgumentNullabilityAssertions then
|
||||||
toArrayPhase then
|
toArrayPhase then
|
||||||
jvmOptimizationLoweringPhase then
|
jvmOptimizationLoweringPhase then
|
||||||
ifNullExpressionsFusionPhase then
|
ifNullExpressionsFusionPhase then
|
||||||
additionalClassAnnotationPhase then
|
additionalClassAnnotationPhase then
|
||||||
typeOperatorLowering then
|
typeOperatorLowering then
|
||||||
replaceKFunctionInvokeWithFunctionInvokePhase then
|
replaceKFunctionInvokeWithFunctionInvokePhase then
|
||||||
|
kotlinNothingValueExceptionPhase then
|
||||||
|
|
||||||
checkLocalNamesWithOldBackendPhase 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.
|
* 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
|
package org.jetbrains.kotlin.backend.jvm
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.ir.Symbols
|
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.builders.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
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.IrPackageFragment
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.*
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
@@ -76,11 +77,12 @@ class JvmSymbols(
|
|||||||
override val ThrowTypeCastException: IrFunctionSymbol =
|
override val ThrowTypeCastException: IrFunctionSymbol =
|
||||||
typeCastExceptionClass.constructors.single()
|
typeCastExceptionClass.constructors.single()
|
||||||
|
|
||||||
private val unsupportedOperationExceptionClass: IrClassSymbol = createClass(FqName("java.lang.UnsupportedOperationException")) { klass ->
|
private val unsupportedOperationExceptionClass: IrClassSymbol =
|
||||||
klass.addConstructor().apply {
|
createClass(FqName("java.lang.UnsupportedOperationException")) { klass ->
|
||||||
addValueParameter("message", irBuiltIns.stringType.makeNullable())
|
klass.addConstructor().apply {
|
||||||
|
addValueParameter("message", irBuiltIns.stringType.makeNullable())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
val ThrowUnsupportOperationExceptionClass: IrFunctionSymbol =
|
val ThrowUnsupportOperationExceptionClass: IrFunctionSymbol =
|
||||||
unsupportedOperationExceptionClass.constructors.single()
|
unsupportedOperationExceptionClass.constructors.single()
|
||||||
@@ -679,6 +681,15 @@ class JvmSymbols(
|
|||||||
|
|
||||||
val runSuspendFunction: IrSimpleFunctionSymbol =
|
val runSuspendFunction: IrSimpleFunctionSymbol =
|
||||||
kotlinCoroutinesJvmInternalRunSuspendKt.functionByName("runSuspend")
|
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 =
|
private fun IrClassSymbol.functionByName(name: String): IrSimpleFunctionSymbol =
|
||||||
|
|||||||
-2
@@ -451,8 +451,6 @@ class ExpressionCodegen(
|
|||||||
|
|
||||||
return when {
|
return when {
|
||||||
expression.type.isNothing() -> {
|
expression.type.isNothing() -> {
|
||||||
mv.aconst(null)
|
|
||||||
mv.athrow()
|
|
||||||
unitValue
|
unitValue
|
||||||
}
|
}
|
||||||
expression is IrConstructorCall ->
|
expression is IrConstructorCall ->
|
||||||
|
|||||||
+2
-1
@@ -112,7 +112,8 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
|
|||||||
irBuiltIns.dataClassArrayMemberToStringSymbol.toKey()!! to IrDataClassArrayMemberToString,
|
irBuiltIns.dataClassArrayMemberToStringSymbol.toKey()!! to IrDataClassArrayMemberToString,
|
||||||
symbols.unsafeCoerceIntrinsic.toKey()!! to UnsafeCoerce,
|
symbols.unsafeCoerceIntrinsic.toKey()!! to UnsafeCoerce,
|
||||||
symbols.signatureStringIntrinsic.toKey()!! to SignatureString,
|
symbols.signatureStringIntrinsic.toKey()!! to SignatureString,
|
||||||
symbols.reassignParameterIntrinsic.toKey()!! to ReassignParameter
|
symbols.reassignParameterIntrinsic.toKey()!! to ReassignParameter,
|
||||||
|
symbols.ThrowKotlinNothingValueException.toKey()!! to ThrowKotlinNothingValueException
|
||||||
) +
|
) +
|
||||||
numberConversionMethods() +
|
numberConversionMethods() +
|
||||||
unaryFunForPrimitives("plus", UnaryPlus) +
|
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()
|
get() = TODO()
|
||||||
override val ThrowUninitializedPropertyAccessException
|
override val ThrowUninitializedPropertyAccessException
|
||||||
get() = TODO()
|
get() = TODO()
|
||||||
|
override val ThrowKotlinNothingValueException: IrSimpleFunctionSymbol
|
||||||
|
get() = TODO()
|
||||||
override val defaultConstructorMarker
|
override val defaultConstructorMarker
|
||||||
get() = TODO()
|
get() = TODO()
|
||||||
override val stringBuilder
|
override val stringBuilder
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
// IGNORE_BACKEND: JS, NATIVE
|
||||||
// IGNORE_BACKEND: JS, JS_IR, JVM_IR, NATIVE
|
|
||||||
|
|
||||||
fun <T> something(): T = Any() as T
|
fun <T> something(): T = Any() as T
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ package kotlin
|
|||||||
internal fun throwUninitializedPropertyAccessException(name: String): Nothing =
|
internal fun throwUninitializedPropertyAccessException(name: String): Nothing =
|
||||||
throw UninitializedPropertyAccessException("lateinit property $name has not been initialized")
|
throw UninitializedPropertyAccessException("lateinit property $name has not been initialized")
|
||||||
|
|
||||||
|
@PublishedApi
|
||||||
|
internal fun throwKotlinNothingValueException(): Nothing =
|
||||||
|
throw KotlinNothingValueException()
|
||||||
|
|
||||||
internal fun noWhenBranchMatchedException(): Nothing = throw NoWhenBranchMatchedException()
|
internal fun noWhenBranchMatchedException(): Nothing = throw NoWhenBranchMatchedException()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user