Add a TypeOperatorLowering for JVM_IR
This commit is contained in:
committed by
max-kammerer
parent
39ba462540
commit
b6ea135e70
@@ -191,6 +191,7 @@ private val jvmFilePhases =
|
||||
toArrayPhase then
|
||||
jvmBuiltinOptimizationLoweringPhase then
|
||||
additionalClassAnnotationPhase then
|
||||
typeOperatorLowering then
|
||||
|
||||
recordNamesForKotlinTypeMapperPhase then
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrPackageFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl
|
||||
@@ -41,32 +42,47 @@ class JvmSymbols(
|
||||
firMode: Boolean
|
||||
) : Symbols<JvmBackendContext>(context, symbolTable) {
|
||||
private val storageManager = LockBasedStorageManager(this::class.java.simpleName)
|
||||
|
||||
private val irBuiltIns = context.irBuiltIns
|
||||
|
||||
override val ThrowNullPointerException: IrSimpleFunctionSymbol
|
||||
get() = error("Unused in JVM IR")
|
||||
|
||||
override val ThrowNoWhenBranchMatchedException: IrSimpleFunctionSymbol
|
||||
get() = error("Unused in JVM IR")
|
||||
|
||||
override val ThrowTypeCastException: IrSimpleFunctionSymbol
|
||||
get() = error("Unused in JVM IR")
|
||||
|
||||
private fun createPackage(fqName: FqName): IrPackageFragment =
|
||||
IrExternalPackageFragmentImpl(IrExternalPackageFragmentSymbolImpl(EmptyPackageFragmentDescriptor(context.state.module, fqName)))
|
||||
|
||||
private val kotlinPackage: IrPackageFragment = createPackage(FqName("kotlin"))
|
||||
private val kotlinJvmPackage: IrPackageFragment = createPackage(FqName("kotlin.jvm"))
|
||||
private val kotlinJvmInternalPackage: IrPackageFragment = createPackage(FqName("kotlin.jvm.internal"))
|
||||
private val kotlinJvmFunctionsPackage: IrPackageFragment = createPackage(FqName("kotlin.jvm.functions"))
|
||||
private val javaLangPackage: IrPackageFragment = createPackage(FqName("java.lang"))
|
||||
|
||||
private val irBuiltIns = context.irBuiltIns
|
||||
|
||||
private val nullPointerExceptionClass: IrClassSymbol =
|
||||
createClass(FqName("java.lang.NullPointerException")) { klass ->
|
||||
klass.addConstructor().apply {
|
||||
addValueParameter("message", irBuiltIns.stringType)
|
||||
}
|
||||
}.symbol
|
||||
|
||||
override val ThrowNullPointerException: IrFunctionSymbol =
|
||||
nullPointerExceptionClass.constructors.single()
|
||||
|
||||
override val ThrowNoWhenBranchMatchedException: IrSimpleFunctionSymbol
|
||||
get() = error("Unused in JVM IR")
|
||||
|
||||
private val typeCastExceptionClass: IrClassSymbol =
|
||||
createClass(FqName("kotlin.TypeCastException")) { klass ->
|
||||
klass.addConstructor().apply {
|
||||
addValueParameter("message", irBuiltIns.stringType)
|
||||
}
|
||||
}.symbol
|
||||
|
||||
override val ThrowTypeCastException: IrFunctionSymbol =
|
||||
typeCastExceptionClass.constructors.single()
|
||||
|
||||
private fun createPackage(fqName: FqName): IrPackageFragment =
|
||||
IrExternalPackageFragmentImpl(IrExternalPackageFragmentSymbolImpl(EmptyPackageFragmentDescriptor(context.state.module, fqName)))
|
||||
|
||||
private fun createClass(fqName: FqName, classKind: ClassKind = ClassKind.CLASS, block: (IrClass) -> Unit): IrClass =
|
||||
buildClass {
|
||||
name = fqName.shortName()
|
||||
kind = classKind
|
||||
}.apply {
|
||||
parent = when (fqName.parent().asString()) {
|
||||
"kotlin" -> kotlinPackage
|
||||
"kotlin.jvm.internal" -> kotlinJvmInternalPackage
|
||||
"kotlin.jvm.functions" -> kotlinJvmFunctionsPackage
|
||||
"java.lang" -> javaLangPackage
|
||||
@@ -82,8 +98,22 @@ class JvmSymbols(
|
||||
klass.addFunction("throwUninitializedPropertyAccessException", irBuiltIns.unitType, isStatic = true).apply {
|
||||
addValueParameter("propertyName", irBuiltIns.stringType)
|
||||
}
|
||||
klass.addFunction("checkExpressionValueIsNotNull", irBuiltIns.unitType, isStatic = true).apply {
|
||||
addValueParameter("value", irBuiltIns.anyNType)
|
||||
addValueParameter("expression", irBuiltIns.stringType)
|
||||
}
|
||||
klass.addFunction("checkNotNullExpressionValue", irBuiltIns.unitType, isStatic = true).apply {
|
||||
addValueParameter("value", irBuiltIns.anyNType)
|
||||
addValueParameter("expression", irBuiltIns.stringType)
|
||||
}
|
||||
}.symbol
|
||||
|
||||
val checkExpressionValueIsNotNull: IrSimpleFunctionSymbol =
|
||||
intrinsicsClass.functions.single { it.owner.name.asString() == "checkExpressionValueIsNotNull" }
|
||||
|
||||
val checkNotNullExpressionValue: IrSimpleFunctionSymbol =
|
||||
intrinsicsClass.functions.single { it.owner.name.asString() == "checkNotNullExpressionValue" }
|
||||
|
||||
override val ThrowUninitializedPropertyAccessException: IrSimpleFunctionSymbol =
|
||||
intrinsicsClass.functions.single { it.owner.name.asString() == "throwUninitializedPropertyAccessException" }
|
||||
|
||||
|
||||
+11
-38
@@ -9,7 +9,6 @@ import org.jetbrains.kotlin.backend.common.lower.BOUND_RECEIVER_PARAMETER
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicMethods
|
||||
import org.jetbrains.kotlin.backend.jvm.intrinsics.JavaClassProperty
|
||||
import org.jetbrains.kotlin.backend.jvm.intrinsics.Not
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.constantValue
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.unboxInlineClass
|
||||
@@ -20,6 +19,7 @@ import org.jetbrains.kotlin.codegen.inline.*
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.Companion.putNeedClassReificationMarker
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.OperationKind.AS
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner.OperationKind.SAFE_AS
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics
|
||||
import org.jetbrains.kotlin.codegen.pseudoInsns.fakeAlwaysFalseIfeq
|
||||
import org.jetbrains.kotlin.codegen.pseudoInsns.fixStackAndJump
|
||||
import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter
|
||||
@@ -637,15 +637,8 @@ class ExpressionCodegen(
|
||||
val typeOperand = expression.typeOperand
|
||||
val kotlinType = typeOperand.toKotlinType()
|
||||
return when (expression.operator) {
|
||||
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT -> {
|
||||
expression.argument.accept(this, data).discard()
|
||||
expression.argument.markEndOfStatementIfNeeded()
|
||||
defaultValue(expression.type)
|
||||
}
|
||||
|
||||
IrTypeOperator.IMPLICIT_CAST, IrTypeOperator.IMPLICIT_INTEGER_COERCION -> {
|
||||
IrTypeOperator.IMPLICIT_CAST ->
|
||||
expression.argument.accept(this, data).coerce(expression.type)
|
||||
}
|
||||
|
||||
IrTypeOperator.CAST, IrTypeOperator.SAFE_CAST -> {
|
||||
val result = expression.argument.accept(this, data)
|
||||
@@ -654,44 +647,26 @@ class ExpressionCodegen(
|
||||
val boxedRightType = typeMapper.boxType(typeOperand)
|
||||
|
||||
if (typeOperand.isReifiedTypeParameter) {
|
||||
putReifiedOperationMarkerIfTypeIsReifiedParameter(
|
||||
typeOperand, if (IrTypeOperator.SAFE_CAST == expression.operator) SAFE_AS else AS, mv, this
|
||||
)
|
||||
val operationKind = if (expression.operator == IrTypeOperator.CAST) AS else SAFE_AS
|
||||
putReifiedOperationMarkerIfTypeIsReifiedParameter(typeOperand, operationKind, mv, this)
|
||||
v.checkcast(boxedRightType)
|
||||
} else {
|
||||
generateAsCast(
|
||||
mv, kotlinType, boxedRightType, expression.operator == IrTypeOperator.SAFE_CAST, state.languageVersionSettings
|
||||
)
|
||||
assert(expression.operator == IrTypeOperator.CAST) { "IrTypeOperator.SAFE_CAST should have been lowered." }
|
||||
TypeIntrinsics.checkcast(mv, kotlinType, boxedRightType, false)
|
||||
}
|
||||
MaterialValue(this, boxedRightType, expression.type).coerce(expression.type)
|
||||
}
|
||||
|
||||
IrTypeOperator.INSTANCEOF, IrTypeOperator.NOT_INSTANCEOF -> {
|
||||
expression.argument.accept(this, data).coerce(OBJECT_TYPE, context.irBuiltIns.anyNType).materialize()
|
||||
IrTypeOperator.INSTANCEOF -> {
|
||||
expression.argument.accept(this, data).coerce(context.irBuiltIns.anyNType).materialize()
|
||||
val type = typeMapper.boxType(typeOperand)
|
||||
if (typeOperand.isReifiedTypeParameter) {
|
||||
putReifiedOperationMarkerIfTypeIsReifiedParameter(typeOperand, ReifiedTypeInliner.OperationKind.IS, mv, this)
|
||||
v.instanceOf(type)
|
||||
} else {
|
||||
generateIsCheck(mv, kotlinType, type, state.languageVersionSettings.isReleaseCoroutines())
|
||||
TypeIntrinsics.instanceOf(mv, kotlinType, type, state.languageVersionSettings.isReleaseCoroutines())
|
||||
}
|
||||
// TODO remove this type operator, generate an intrinsic call around INSTANCEOF instead
|
||||
if (IrTypeOperator.NOT_INSTANCEOF == expression.operator)
|
||||
Not.BooleanNegation(expression.onStack.coerceToBoolean())
|
||||
else
|
||||
expression.onStack
|
||||
}
|
||||
|
||||
IrTypeOperator.IMPLICIT_NOTNULL -> {
|
||||
val value = expression.argument.accept(this, data).materialized
|
||||
mv.dup()
|
||||
mv.visitLdcInsn("TODO provide message for IMPLICIT_NOTNULL") /*TODO*/
|
||||
val methodName =
|
||||
if (state.languageVersionSettings.apiVersion >= ApiVersion.KOTLIN_1_4) "checkNotNullExpressionValue"
|
||||
else "checkExpressionValueIsNotNull"
|
||||
mv.invokestatic(IrIntrinsicMethods.INTRINSICS_CLASS_NAME, methodName, "(Ljava/lang/Object;Ljava/lang/String;)V", false)
|
||||
// Unbox primitives.
|
||||
value.coerce(expression.type)
|
||||
expression.onStack
|
||||
}
|
||||
|
||||
else -> throw AssertionError("type operator ${expression.operator} should have been lowered")
|
||||
@@ -942,9 +917,7 @@ class ExpressionCodegen(
|
||||
|
||||
override fun visitThrow(expression: IrThrow, data: BlockInfo): PromisedValue {
|
||||
expression.markLineNumber(startOffset = true)
|
||||
expression.value.accept(this, data)
|
||||
.coerce(AsmTypes.JAVA_THROWABLE_TYPE, context.irBuiltIns.throwableType)
|
||||
.materialize()
|
||||
expression.value.accept(this, data).materialize()
|
||||
mv.athrow()
|
||||
return immaterialUnitValue
|
||||
}
|
||||
|
||||
+194
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.lower.IrBuildingTransformer
|
||||
import org.jetbrains.kotlin.backend.common.lower.at
|
||||
import org.jetbrains.kotlin.backend.common.lower.irNot
|
||||
import org.jetbrains.kotlin.backend.common.lower.irThrow
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.fileParent
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
|
||||
import org.jetbrains.kotlin.config.ApiVersion
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
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.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
|
||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
// After this pass runs there are only four kinds of IrTypeOperatorCalls left:
|
||||
//
|
||||
// - IMPLICIT_CAST
|
||||
// - SAFE_CAST with reified type parameters
|
||||
// - INSTANCEOF with non-nullable type operand or reified type parameters
|
||||
// - CAST with non-nullable argument, nullable type operand, or reified type parameters
|
||||
//
|
||||
// The latter two correspond to the instanceof/checkcast instructions on the JVM, except for
|
||||
// the presence of reified type parameters.
|
||||
internal val typeOperatorLowering = makeIrFilePhase(
|
||||
::TypeOperatorLowering,
|
||||
name = "TypeOperatorLowering",
|
||||
description = "Lower IrTypeOperatorCalls to (implicit) casts and instanceof checks"
|
||||
)
|
||||
|
||||
private class TypeOperatorLowering(private val context: JvmBackendContext) : FileLoweringPass, IrBuildingTransformer(context) {
|
||||
override fun lower(irFile: IrFile) = irFile.transformChildrenVoid()
|
||||
|
||||
private fun IrExpression.transformVoid() = transform(this@TypeOperatorLowering, null)
|
||||
|
||||
private val IrType.isReifiedTypeParameter: Boolean
|
||||
get() = classifierOrNull?.safeAs<IrTypeParameterSymbol>()?.owner?.isReified == true
|
||||
|
||||
private fun lowerInstanceOf(argument: IrExpression, type: IrType) = with(builder) {
|
||||
when {
|
||||
type.isReifiedTypeParameter ->
|
||||
irIs(argument, type)
|
||||
argument.type.isNullable() && type.isNullable() -> {
|
||||
irLetS(argument) { valueSymbol ->
|
||||
context.oror(
|
||||
irEqualsNull(irGet(valueSymbol.owner)),
|
||||
irIs(irGet(valueSymbol.owner), type.makeNotNull())
|
||||
)
|
||||
}
|
||||
}
|
||||
else -> irIs(argument, type.makeNotNull())
|
||||
}
|
||||
}
|
||||
|
||||
private fun lowerCast(argument: IrExpression, type: IrType): IrExpression = when {
|
||||
type.isReifiedTypeParameter ->
|
||||
builder.irAs(argument, type)
|
||||
argument.type.isNullable() && !type.isNullable() ->
|
||||
with(builder) {
|
||||
irLetS(argument) { valueSymbol ->
|
||||
irIfNull(
|
||||
type,
|
||||
irGet(valueSymbol.owner),
|
||||
irThrow(irCall(typeCastException).apply {
|
||||
putValueArgument(0, irString("null cannot be cast to non-null type ${type.render()}"))
|
||||
}),
|
||||
lowerCast(irGet(valueSymbol.owner), type.makeNullable())
|
||||
)
|
||||
}
|
||||
}
|
||||
argument.type.isSubtypeOfClass(type.erasedUpperBound.symbol) ->
|
||||
argument
|
||||
else ->
|
||||
builder.irAs(argument, type)
|
||||
}
|
||||
|
||||
override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression = with(builder) {
|
||||
at(expression)
|
||||
return when (expression.operator) {
|
||||
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT ->
|
||||
irComposite(resultType = expression.type) {
|
||||
+expression.argument.transformVoid()
|
||||
// TODO: Don't generate these casts in the first place
|
||||
if (!expression.argument.type.isSubtypeOf(expression.type.makeNullable(), context.irBuiltIns)) {
|
||||
+IrCompositeImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, expression.type)
|
||||
}
|
||||
}
|
||||
|
||||
// There is no difference between IMPLICIT_CAST and IMPLICIT_INTEGER_COERCION on JVM_IR.
|
||||
// Instead, this is handled in StackValue.coerce.
|
||||
IrTypeOperator.IMPLICIT_INTEGER_COERCION ->
|
||||
irImplicitCast(expression.argument.transformVoid(), expression.typeOperand)
|
||||
|
||||
IrTypeOperator.CAST ->
|
||||
lowerCast(expression.argument.transformVoid(), expression.typeOperand)
|
||||
|
||||
IrTypeOperator.SAFE_CAST ->
|
||||
if (expression.typeOperand.isReifiedTypeParameter) {
|
||||
expression.transformChildrenVoid()
|
||||
expression
|
||||
} else {
|
||||
irLetS(expression.argument.transformVoid(), IrStatementOrigin.SAFE_CALL) { valueSymbol ->
|
||||
irIfThenElse(
|
||||
expression.type,
|
||||
lowerInstanceOf(irGet(valueSymbol.owner), expression.typeOperand.makeNotNull()),
|
||||
irGet(valueSymbol.owner),
|
||||
irNull(expression.type)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
IrTypeOperator.INSTANCEOF ->
|
||||
lowerInstanceOf(expression.argument.transformVoid(), expression.typeOperand)
|
||||
|
||||
IrTypeOperator.NOT_INSTANCEOF ->
|
||||
irNot(lowerInstanceOf(expression.argument.transformVoid(), expression.typeOperand))
|
||||
|
||||
IrTypeOperator.IMPLICIT_NOTNULL -> {
|
||||
val (startOffset, endOffset) = expression.extents()
|
||||
val source = sourceViewFor(parent as IrDeclaration).subSequence(startOffset, endOffset).toString()
|
||||
|
||||
irLetS(expression.argument.transformVoid()) { valueSymbol ->
|
||||
irComposite(resultType = expression.type) {
|
||||
+irCall(checkExpressionValueIsNotNull).apply {
|
||||
putValueArgument(0, irGet(valueSymbol.owner))
|
||||
putValueArgument(1, irString(source))
|
||||
}
|
||||
+irGet(valueSymbol.owner)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
expression.transformChildrenVoid()
|
||||
expression
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrElement.extents(): Pair<Int, Int> {
|
||||
var startOffset = UNDEFINED_OFFSET
|
||||
var endOffset = UNDEFINED_OFFSET
|
||||
acceptVoid(object : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
if (startOffset == UNDEFINED_OFFSET || element.startOffset != UNDEFINED_OFFSET && element.startOffset < startOffset)
|
||||
startOffset = element.startOffset
|
||||
if (endOffset == UNDEFINED_OFFSET || element.endOffset != UNDEFINED_OFFSET && endOffset < element.endOffset)
|
||||
endOffset = element.endOffset
|
||||
}
|
||||
})
|
||||
return startOffset to endOffset
|
||||
}
|
||||
|
||||
private fun sourceViewFor(declaration: IrDeclaration) =
|
||||
context.psiSourceManager.getKtFile(declaration.fileParent)!!.viewProvider.contents
|
||||
|
||||
// Since Kotlin 1.4 we throw NullPointerExceptions instead of more specialized exception classes.
|
||||
private val useNullPointerExceptions: Boolean
|
||||
get() = context.state.languageVersionSettings.apiVersion >= ApiVersion.KOTLIN_1_4
|
||||
|
||||
private val typeCastException: IrFunctionSymbol =
|
||||
if (useNullPointerExceptions)
|
||||
context.ir.symbols.ThrowNullPointerException
|
||||
else
|
||||
context.ir.symbols.ThrowTypeCastException
|
||||
|
||||
private val checkExpressionValueIsNotNull: IrFunctionSymbol =
|
||||
if (useNullPointerExceptions)
|
||||
context.ir.symbols.checkNotNullExpressionValue
|
||||
else
|
||||
context.ir.symbols.checkExpressionValueIsNotNull
|
||||
}
|
||||
@@ -19,20 +19,6 @@ import org.jetbrains.kotlin.utils.addToStdlib.assertedCast
|
||||
|
||||
val IrBuilderWithScope.parent get() = scope.getLocalDeclarationParent()
|
||||
|
||||
inline fun IrBuilderWithScope.irLet(
|
||||
value: IrExpression,
|
||||
origin: IrStatementOrigin? = null,
|
||||
nameHint: String? = null,
|
||||
body: (VariableDescriptor) -> IrExpression
|
||||
): IrExpression {
|
||||
val irTemporary = scope.createTemporaryVariable(value, nameHint)
|
||||
val irResult = body(irTemporary.descriptor)
|
||||
val irBlock = IrBlockImpl(startOffset, endOffset, irResult.type, origin)
|
||||
irBlock.statements.add(irTemporary)
|
||||
irBlock.statements.add(irResult)
|
||||
return irBlock
|
||||
}
|
||||
|
||||
inline fun IrBuilderWithScope.irLetS(
|
||||
value: IrExpression,
|
||||
origin: IrStatementOrigin? = null,
|
||||
@@ -185,13 +171,13 @@ fun IrBuilderWithScope.irEqeqeq(arg1: IrExpression, arg2: IrExpression) =
|
||||
context.eqeqeq(startOffset, endOffset, arg1, arg2)
|
||||
|
||||
fun IrBuilderWithScope.irNull() =
|
||||
IrConstImpl.constNull(startOffset, endOffset, context.irBuiltIns.nothingNType)
|
||||
irNull(context.irBuiltIns.nothingNType)
|
||||
|
||||
fun IrBuilderWithScope.irNull(irType: IrType) =
|
||||
IrConstImpl.constNull(startOffset, endOffset, irType)
|
||||
|
||||
fun IrBuilderWithScope.irEqualsNull(argument: IrExpression) =
|
||||
primitiveOp2(
|
||||
startOffset, endOffset, context.irBuiltIns.eqeqSymbol, context.irBuiltIns.booleanType, IrStatementOrigin.EQEQ,
|
||||
argument, irNull()
|
||||
)
|
||||
irEquals(argument, irNull())
|
||||
|
||||
fun IrBuilderWithScope.irEquals(arg1: IrExpression, arg2: IrExpression, origin: IrStatementOrigin = IrStatementOrigin.EQEQ) =
|
||||
primitiveOp2(
|
||||
|
||||
Reference in New Issue
Block a user