Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.jetbrains.kotlinx.atomicfu.compiler.backend.common.AbstractAtomicfuIrBuilder.kt Maven / Gradle / Ivy
/*
* Copyright 2010-2022 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.kotlinx.atomicfu.compiler.backend.common
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
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.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.defaultType
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.isBoolean
import org.jetbrains.kotlin.ir.types.isInt
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.util.capitalizeDecapitalize.decapitalizeAsciiOnly
abstract class AbstractAtomicfuIrBuilder(
private val irBuiltIns: IrBuiltIns,
symbol: IrSymbol,
startOffset: Int,
endOffset: Int
) : IrBuilderWithScope(IrGeneratorContextBase(irBuiltIns), Scope(symbol), startOffset, endOffset) {
abstract val atomicSymbols: AbstractAtomicSymbols
fun irGetProperty(property: IrProperty, dispatchReceiver: IrExpression?) =
irCall(property.getter?.symbol ?: error("Getter is not defined for the property ${property.render()}")).apply {
this.dispatchReceiver = dispatchReceiver?.deepCopyWithSymbols()
}
// atomicArr.get(index)
fun atomicGetArrayElement(atomicArrayClass: IrClassSymbol, returnType: IrType, receiver: IrExpression, index: IrExpression): IrCall {
val arrayElement = irCall(atomicSymbols.getAtomicHandlerFunctionSymbol(atomicArrayClass, "get")).apply {
dispatchReceiver = receiver
putValueArgument(0, index)
}
return if (returnType.isBoolean() && arrayElement.type.isInt()) arrayElement.toBoolean() else arrayElement
}
fun irCallWithArgs(symbol: IrSimpleFunctionSymbol, dispatchReceiver: IrExpression?, extensionReceiver: IrExpression?, valueArguments: List) =
irCall(symbol).apply {
this.dispatchReceiver = dispatchReceiver
this.extensionReceiver = extensionReceiver
valueArguments.forEachIndexed { i, arg ->
putValueArgument(i, arg)
}
}
fun callAtomicExtension(
symbol: IrSimpleFunctionSymbol,
dispatchReceiver: IrExpression?,
syntheticValueArguments: List,
valueArguments: List
) = irCallWithArgs(symbol, dispatchReceiver, null, syntheticValueArguments + valueArguments)
fun irVolatileField(
name: String,
type: IrType,
initValue: IrExpression?,
annotations: List,
parentContainer: IrDeclarationContainer
): IrField =
context.irFactory.buildField {
this.name = Name.identifier(name)
this.type = type
isFinal = false
isStatic = parentContainer is IrFile
visibility = DescriptorVisibilities.PRIVATE
origin = AbstractAtomicSymbols.ATOMICFU_GENERATED_FIELD
}.apply {
initializer = initValue?.let(context.irFactory::createExpressionBody)
this.annotations = annotations + atomicSymbols.volatileAnnotationConstructorCall
this.parent = parentContainer
}
fun irAtomicArrayField(
name: Name,
arrayClass: IrClassSymbol,
isStatic: Boolean,
annotations: List,
size: IrExpression,
dispatchReceiver: IrExpression?,
parentContainer: IrDeclarationContainer
): IrField =
context.irFactory.buildField {
this.name = name
type = arrayClass.defaultType
this.isFinal = true
this.isStatic = isStatic
visibility = DescriptorVisibilities.PRIVATE
origin = AbstractAtomicSymbols.ATOMICFU_GENERATED_FIELD
}.apply {
this.initializer = context.irFactory.createExpressionBody(
newAtomicArray(arrayClass, size, dispatchReceiver)
)
this.annotations = annotations
this.parent = parentContainer
}
abstract fun newAtomicArray(
atomicArrayClass: IrClassSymbol,
size: IrExpression,
dispatchReceiver: IrExpression?
): IrFunctionAccessExpression
// atomicArr.compareAndSet(index, expect, update)
fun callAtomicArray(
arrayClassSymbol: IrClassSymbol,
functionName: String,
dispatchReceiver: IrExpression?,
index: IrExpression,
valueArguments: List,
isBooleanReceiver: Boolean
): IrCall {
val irCall = irCall(atomicSymbols.getAtomicHandlerFunctionSymbol(arrayClassSymbol, functionName)).apply {
this.dispatchReceiver = dispatchReceiver
putValueArgument(0, index) // array element index
valueArguments.forEachIndexed { index, arg ->
// as AtomicBooleanArray is represented with AtomicIntArray,
// boolean arguments should be cast to int
putValueArgument(index + 1, if (isBooleanReceiver) arg?.toInt() else arg)
}
}
return if (isBooleanReceiver && irCall.type.isInt()) irCall.toBoolean() else irCall
}
fun buildClassInstance(
irClass: IrClass,
parentContainer: IrDeclarationContainer,
isStatic: Boolean
): IrField =
context.irFactory.buildField {
this.name = Name.identifier(irClass.name.asString().decapitalizeAsciiOnly())
type = irClass.defaultType
isFinal = true
this.isStatic = isStatic
this.visibility = DescriptorVisibilities.PRIVATE
origin = AbstractAtomicSymbols.ATOMICFU_GENERATED_FIELD
}.apply {
initializer = context.irFactory.createExpressionBody(
IrConstructorCallImpl.fromSymbolOwner(
irClass.defaultType,
irClass.primaryConstructor!!.symbol
)
)
this.parent = parentContainer
}
fun IrExpression.toBoolean() = irNotEquals(this, irInt(0)) as IrCall
fun IrExpression.toInt() = irIfThenElse(irBuiltIns.intType, this, irInt(1), irInt(0))
fun irClassWithPrivateConstructor(
name: String,
visibility: DescriptorVisibility,
parentContainer: IrDeclarationContainer
): IrClass = context.irFactory.buildClass {
this.name = Name.identifier(name)
kind = ClassKind.CLASS
origin = AbstractAtomicSymbols.ATOMICFU_GENERATED_CLASS
}.apply {
val irClass = this
this.parent = parentContainer
parentContainer.addChild(irClass)
thisReceiver = buildValueParameter(irClass) {
this.name = Name.identifier("\$this")
type = IrSimpleTypeImpl(irClass.symbol, false, emptyList(), emptyList())
}
irClass.visibility = visibility
addConstructor {
isPrimary = true
}.apply {
body = atomicSymbols.createBuilder(symbol).irBlockBody(startOffset, endOffset) {
+irDelegatingConstructorCall(context.irBuiltIns.anyClass.owner.constructors.single())
+IrInstanceInitializerCallImpl(startOffset, endOffset, irClass.symbol, context.irBuiltIns.unitType)
}
this.visibility = DescriptorVisibilities.PRIVATE // constructor of the wrapper class should be private
}
}
fun IrDeclarationContainer.replacePropertyAtIndex(
field: IrField,
visibility: DescriptorVisibility,
isVar: Boolean,
isStatic: Boolean,
index: Int
): IrProperty = buildPropertyWithAccessors(field, visibility, isVar, isStatic, this).also { declarations[index] = it }
fun IrDeclarationContainer.addProperty(
field: IrField,
visibility: DescriptorVisibility,
isVar: Boolean,
isStatic: Boolean
): IrProperty = buildPropertyWithAccessors(field, visibility, isVar, isStatic, this).also { declarations.add(it) }
private fun buildPropertyWithAccessors(
field: IrField,
visibility: DescriptorVisibility,
isVar: Boolean,
isStatic: Boolean,
parentContainer: IrDeclarationContainer
) = context.irFactory.buildProperty {
this.name = field.name
this.visibility = visibility
this.isVar = isVar
origin = AbstractAtomicSymbols.ATOMICFU_GENERATED_PROPERTY
}.apply {
backingField = field
field.correspondingPropertySymbol = this.symbol
parent = parentContainer
addGetter(isStatic, parentContainer, irBuiltIns)
if (isVar) {
addSetter(isStatic, parentContainer, irBuiltIns)
}
}
private fun IrProperty.addGetter(isStatic: Boolean, parentContainer: IrDeclarationContainer, irBuiltIns: IrBuiltIns) {
val property = this
val field = requireNotNull(backingField) { "The backing field of the property $property should not be null."}
addGetter {
visibility = property.visibility
returnType = field.type
origin = AbstractAtomicSymbols.ATOMICFU_GENERATED_PROPERTY_ACCESSOR
}.apply {
dispatchReceiverParameter = if (isStatic) null else (parentContainer as? IrClass)?.thisReceiver?.deepCopyWithSymbols(this)
body = factory.createBlockBody(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, listOf(
IrReturnImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
irBuiltIns.nothingType,
symbol,
IrGetFieldImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
field.symbol,
field.type,
dispatchReceiverParameter?.let {
IrGetValueImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
it.type,
it.symbol
)
}
)
)
)
)
}
}
private fun IrProperty.addSetter(isStatic: Boolean, parentClass: IrDeclarationContainer, irBuiltIns: IrBuiltIns) {
val property = this
val field = requireNotNull(property.backingField) { "The backing field of the property $property should not be null."}
[email protected] {
visibility = property.visibility
returnType = irBuiltIns.unitType
origin = AbstractAtomicSymbols.ATOMICFU_GENERATED_PROPERTY_ACCESSOR
}.apply {
dispatchReceiverParameter = if (isStatic) null else (parentClass as? IrClass)?.thisReceiver?.deepCopyWithSymbols(this)
addValueParameter("value", field.type)
val value = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valueParameters[0].type, valueParameters[0].symbol)
body = factory.createBlockBody(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, listOf(
IrReturnImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
irBuiltIns.unitType,
symbol,
IrSetFieldImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
field.symbol,
dispatchReceiverParameter?.let {
IrGetValueImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
it.type,
it.symbol
)
},
value,
irBuiltIns.unitType
)
)
)
)
}
}
abstract fun atomicfuLoopBody(valueType: IrType, valueParameters: List): IrBlockBody
abstract fun atomicfuArrayLoopBody(atomicArrayClass: IrClassSymbol, valueType: IrType, valueParameters: List): IrBlockBody
abstract fun atomicfuUpdateBody(functionName: String, valueType: IrType, valueParameters: List): IrBlockBody
abstract fun atomicfuArrayUpdateBody(functionName: String, valueType: IrType, atomicArrayClass: IrClassSymbol, valueParameters: List): IrBlockBody
}