[K/N] Wrap volatile boolean to byte

^KT-54944
This commit is contained in:
Pavel Kunyavskiy
2022-12-01 15:35:15 +01:00
committed by Space Team
parent fc95b88eef
commit 49d286e4e8
@@ -15,13 +15,15 @@ import org.jetbrains.kotlin.backend.konan.ir.buildSimpleAnnotation
import org.jetbrains.kotlin.backend.konan.llvm.IntrinsicType import org.jetbrains.kotlin.backend.konan.llvm.IntrinsicType
import org.jetbrains.kotlin.backend.konan.llvm.tryGetIntrinsicType import org.jetbrains.kotlin.backend.konan.llvm.tryGetIntrinsicType
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
import org.jetbrains.kotlin.ir.builders.declarations.buildFun import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.builders.irString
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.util.irCall
import org.jetbrains.kotlin.ir.visitors.* import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.util.capitalizeDecapitalize.* import org.jetbrains.kotlin.util.capitalizeDecapitalize.*
@@ -29,6 +31,19 @@ import org.jetbrains.kotlin.util.capitalizeDecapitalize.*
object IR_DECLARATION_ORIGIN_VOLATILE : IrDeclarationOriginImpl("VOLATILE") object IR_DECLARATION_ORIGIN_VOLATILE : IrDeclarationOriginImpl("VOLATILE")
internal class VolatileFieldsLowering(val context: Context) : FileLoweringPass { internal class VolatileFieldsLowering(val context: Context) : FileLoweringPass {
private val symbols = context.ir.symbols
private val irBuiltins = context.irBuiltIns
private fun IrBuilderWithScope.irByteToBool(expression: IrExpression) = irCall(symbols.areEqualByValue[PrimitiveBinaryType.BYTE]!!).apply {
putValueArgument(0, expression)
putValueArgument(1, irByte(1))
}
private fun IrBuilderWithScope.irBoolToByte(expression: IrExpression) = irWhen(irBuiltins.byteType, listOf(
irBranch(expression, irByte(1)),
irElseBranch(irByte(0))
))
private val convertedBooleanFields = mutableSetOf<IrFieldSymbol>()
private fun IrField.requiresBooleanConversion() = (type == irBuiltins.booleanType && hasAnnotation(KonanFqNames.volatile)) || symbol in convertedBooleanFields
private fun buildIntrinsicFunction(irField: IrField, intrinsicType: IntrinsicType, builder: IrSimpleFunction.() -> Unit) = context.irFactory.buildFun { private fun buildIntrinsicFunction(irField: IrField, intrinsicType: IntrinsicType, builder: IrSimpleFunction.() -> Unit) = context.irFactory.buildFun {
isExternal = true isExternal = true
origin = IR_DECLARATION_ORIGIN_VOLATILE origin = IR_DECLARATION_ORIGIN_VOLATILE
@@ -108,6 +123,7 @@ internal class VolatileFieldsLowering(val context: Context) : FileLoweringPass {
override fun lower(irFile: IrFile) { override fun lower(irFile: IrFile) {
irFile.transformChildrenVoid(object : IrBuildingTransformer(context) { irFile.transformChildrenVoid(object : IrBuildingTransformer(context) {
override fun visitClass(declaration: IrClass): IrStatement { override fun visitClass(declaration: IrClass): IrStatement {
declaration.transformChildrenVoid()
declaration.declarations.transformFlat { declaration.declarations.transformFlat {
when { when {
it !is IrProperty -> null it !is IrProperty -> null
@@ -128,14 +144,40 @@ internal class VolatileFieldsLowering(val context: Context) : FileLoweringPass {
} }
} }
} }
declaration.transformChildrenVoid()
return declaration return declaration
} }
override fun visitField(declaration: IrField): IrStatement {
if (declaration.type == irBuiltins.booleanType && declaration.hasAnnotation(KonanFqNames.volatile)) {
convertedBooleanFields.add(declaration.symbol)
declaration.type = irBuiltins.byteType
}
return super.visitField(declaration)
}
private fun unsupported(message: String) = builder.irCall(context.ir.symbols.throwIllegalArgumentExceptionWithMessage).apply { private fun unsupported(message: String) = builder.irCall(context.ir.symbols.throwIllegalArgumentExceptionWithMessage).apply {
putValueArgument(0, builder.irString(message)) putValueArgument(0, builder.irString(message))
} }
override fun visitGetField(expression: IrGetField): IrExpression {
super.visitGetField(expression)
return if (expression.symbol.owner.requiresBooleanConversion()) {
builder.at(expression).irByteToBool(expression.apply { type = irBuiltins.byteType })
} else {
expression
}
}
override fun visitSetField(expression: IrSetField): IrExpression {
super.visitSetField(expression)
return if (expression.symbol.owner.requiresBooleanConversion()) {
expression.apply { value = builder.at(value).irBoolToByte(value) }
} else {
expression
}
}
private val intrinsicMap = mapOf( private val intrinsicMap = mapOf(
IntrinsicType.COMPARE_AND_SET_FIELD to ::compareAndSetFunction, IntrinsicType.COMPARE_AND_SET_FIELD to ::compareAndSetFunction,
IntrinsicType.COMPARE_AND_SWAP_FIELD to ::compareAndSwapFunction, IntrinsicType.COMPARE_AND_SWAP_FIELD to ::compareAndSwapFunction,
@@ -164,6 +206,19 @@ internal class VolatileFieldsLowering(val context: Context) : FileLoweringPass {
if (intrinsicType == IntrinsicType.COMPARE_AND_SET_FIELD || intrinsicType == IntrinsicType.COMPARE_AND_SWAP_FIELD) { if (intrinsicType == IntrinsicType.COMPARE_AND_SET_FIELD || intrinsicType == IntrinsicType.COMPARE_AND_SWAP_FIELD) {
putValueArgument(1, expression.getValueArgument(2)) putValueArgument(1, expression.getValueArgument(2))
} }
}.let {
if (backingField.requiresBooleanConversion()) {
for (arg in 0 until it.valueArgumentsCount) {
it.putValueArgument(arg, builder.irBoolToByte(it.getValueArgument(arg)!!))
}
if (intrinsicType == IntrinsicType.COMPARE_AND_SWAP_FIELD || intrinsicType == IntrinsicType.GET_AND_SET_FIELD) {
builder.irByteToBool(it)
} else {
it
}
} else {
it
}
} }
} }
}) })