[K/N]: Allow invocation of volatile intrinsics on inline function constant arguments.

Invocation of atomic intrinsics is only allowed on property references that are known at compile time. This commit makes it possible to also invoke intrinsics on a constant property reference getter passed as an argument.
See KT-58359

Co-authored-by: Pavel Kunyavskiy <Pavel.Kunyavskiy@jetbrains.com>

Merge-request: KT-MR-10413
Merged-by: Maria Sokolova <maria.sokolova@jetbrains.com>
This commit is contained in:
Pavel Kunyavskiy
2023-07-24 17:45:16 +00:00
committed by Space Team
parent d77af3c43d
commit 488d24296a
6 changed files with 82 additions and 1 deletions
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.util.irCall
@@ -203,11 +204,24 @@ internal class VolatileFieldsLowering(val context: Context) : FileLoweringPass {
IntrinsicType.GET_AND_ADD_FIELD to ::getAndAddFunction,
)
private val IrBlock.singleExpressionOrNull get() = statements.singleOrNull() as? IrExpression
private tailrec fun getConstPropertyReference(expression: IrExpression?, expectedReturn: IrReturnableBlockSymbol?) : IrPropertyReference? {
return when {
expression == null -> null
expectedReturn == null && expression is IrPropertyReference -> expression
expectedReturn == null && expression is IrReturnableBlock -> getConstPropertyReference(expression.singleExpressionOrNull, expression.symbol)
expression is IrReturn && expression.returnTargetSymbol == expectedReturn -> getConstPropertyReference(expression.value, null)
expression is IrBlock -> getConstPropertyReference(expression.singleExpressionOrNull, expectedReturn)
else -> null
}
}
override fun visitCall(expression: IrCall): IrExpression {
expression.transformChildrenVoid(this)
val intrinsicType = tryGetIntrinsicType(expression).takeIf { it in intrinsicMap } ?: return expression
builder.at(expression)
val reference = expression.extensionReceiver as? IrPropertyReference
val reference = getConstPropertyReference(expression.extensionReceiver, null)
?: return unsupported("Only compile-time known IrProperties supported for $intrinsicType")
val property = reference.symbol.owner
val backingField = property.backingField