[K/N] Wrap volatile boolean to byte
^KT-54944
This commit is contained in:
committed by
Space Team
parent
fc95b88eef
commit
49d286e4e8
+57
-2
@@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user