All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.kotlinx.atomicfu.compiler.backend.native.NativeAtomicSymbols.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.native

import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.jvm.functionByName
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlinx.atomicfu.compiler.backend.common.AbstractAtomicSymbols
import org.jetbrains.kotlinx.atomicfu.compiler.backend.js.referenceFunction

class NativeAtomicSymbols(
    context: IrPluginContext,
    moduleFragment: IrModuleFragment
) : AbstractAtomicSymbols(context, moduleFragment) {
    // kotlin.concurrent.Volatile annotation class
    override val volatileAnnotationClass: IrClass
        get() = context.referenceClass(ClassId(FqName("kotlin.concurrent"), Name.identifier("Volatile")))?.owner
            ?: error("kotlin.concurrent.Volatile class is not found")

    // kotlin.concurrent.AtomicIntArray
    override val atomicIntArrayClassSymbol: IrClassSymbol
        get() = context.referenceClass(ClassId(FqName("kotlin.concurrent"), Name.identifier("AtomicIntArray")))
            ?: error("kotlin.concurrent.AtomicIntArray is not found")

    // kotlin.concurrent.AtomicLongArray
    override val atomicLongArrayClassSymbol: IrClassSymbol
        get() = context.referenceClass(ClassId(FqName("kotlin.concurrent"), Name.identifier("AtomicLongArray")))
            ?: error("kotlin.concurrent.AtomicLongArray is not found")

    // kotlin.concurrent.AtomicArray
    override val atomicRefArrayClassSymbol: IrClassSymbol
        get() = context.referenceClass(ClassId(FqName("kotlin.concurrent"), Name.identifier("AtomicArray")))
            ?: error("kotlin.concurrent.AtomicArray is not found")

    override fun getAtomicArrayConstructor(atomicArrayClassSymbol: IrClassSymbol): IrFunctionSymbol =
        when (atomicArrayClassSymbol) {
            atomicIntArrayClassSymbol, atomicLongArrayClassSymbol -> {
                atomicArrayClassSymbol.owner.constructors.singleOrNull {
                    it.valueParameters.size == 1 && it.valueParameters[0].type == irBuiltIns.intType
                }?.symbol ?: error("No `public constructor(size: Int) {}` was found for ${atomicArrayClassSymbol.owner.render()}")
            }
            atomicRefArrayClassSymbol -> {
                context.referenceFunctions(CallableId(FqName("kotlin.concurrent"), Name.identifier("AtomicArray"))).singleOrNull()
                    ?: error("No factory function `public inline fun  AtomicArray(size: Int, noinline init: (Int) -> T)` was found for ${atomicArrayClassSymbol.owner.render()}")
            }
            else -> error("Unsupported atomic array class found: ${atomicArrayClassSymbol.owner.render()}")
        }

    // Intrinsics for atomic update of volatile properties

    val atomicGetFieldIntrinsic =
        context.referenceFunctions(CallableId(FqName("kotlin.concurrent"), Name.identifier("atomicGetField"))).single()

    val atomicSetFieldIntrinsic =
        context.referenceFunctions(CallableId(FqName("kotlin.concurrent"), Name.identifier("atomicSetField"))).single()

    val compareAndSetFieldIntrinsic =
        context.referenceFunctions(CallableId(FqName("kotlin.concurrent"), Name.identifier("compareAndSetField"))).single()

    val getAndSetFieldIntrinsic =
        context.referenceFunctions(CallableId(FqName("kotlin.concurrent"), Name.identifier("getAndSetField"))).single()

    val getAndAddIntFieldIntrinsic =
        context.referenceFunctions(CallableId(FqName("kotlin.concurrent"), Name.identifier("getAndAddField")))
            .single { it.owner.returnType.isInt() }

    val getAndAddLongFieldIntrinsic =
        context.referenceFunctions(CallableId(FqName("kotlin.concurrent"), Name.identifier("getAndAddField")))
            .single { it.owner.returnType.isLong() }

    val intPlusOperator = context.referenceFunctions(CallableId(StandardClassIds.Int, Name.identifier("plus")))
        .single { it.owner.valueParameters[0].type.isInt() }

    val longPlusOperator = context.referenceFunctions(CallableId(StandardClassIds.Long, Name.identifier("plus")))
        .single { it.owner.valueParameters[0].type.isLong() }

    // KMutableProperty0
    fun kMutableProperty0Type(typeArg: IrType): IrType =
        buildSimpleType(irBuiltIns.kMutableProperty0Class, listOf(typeArg))

    // () -> KMutableProperty0
    fun kMutableProperty0GetterType(typeArg: IrType): IrType = function0Type(kMutableProperty0Type(typeArg))

    fun getParameterizedAtomicArrayType(elementType: IrType): IrType {
        val atomicArrayClassSymbol = getAtomicArrayClassByValueType(elementType)
        return if (atomicArrayClassSymbol == atomicRefArrayClassSymbol) {
            buildSimpleType(atomicArrayClassSymbol, listOf(elementType))
        } else {
            atomicArrayClassSymbol.defaultType
        }
    }

    override fun createBuilder(symbol: IrSymbol, startOffset: Int, endOffset: Int) =
        NativeAtomicfuIrBuilder(this, symbol, startOffset, endOffset)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy