Make kotlinx.cinterop.convert follow C rules
This commit is contained in:
committed by
SvyatoslavScherbina
parent
872deb205c
commit
d5142220d2
+10
@@ -149,6 +149,16 @@ internal class KonanSymbols(context: Context, val symbolTable: SymbolTable, val
|
|||||||
|
|
||||||
val allIntegerClasses = signedIntegerClasses + unsignedIntegerClasses
|
val allIntegerClasses = signedIntegerClasses + unsignedIntegerClasses
|
||||||
|
|
||||||
|
val unsignedToSignedOfSameBitWidth = unsignedIntegerClasses.associate {
|
||||||
|
it to when (it) {
|
||||||
|
uByte -> byte
|
||||||
|
uShort -> short
|
||||||
|
uInt -> int
|
||||||
|
uLong -> long
|
||||||
|
else -> error(it.descriptor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val integerConversions = allIntegerClasses.flatMap { fromClass ->
|
val integerConversions = allIntegerClasses.flatMap { fromClass ->
|
||||||
allIntegerClasses.map { toClass ->
|
allIntegerClasses.map { toClass ->
|
||||||
val name = Name.identifier("to${toClass.descriptor.name.asString().capitalize()}")
|
val name = Name.identifier("to${toClass.descriptor.name.asString().capitalize()}")
|
||||||
|
|||||||
+26
-12
@@ -906,21 +906,20 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
|||||||
val integerClasses = symbols.allIntegerClasses
|
val integerClasses = symbols.allIntegerClasses
|
||||||
val typeOperand = expression.getTypeArgument(0)!!
|
val typeOperand = expression.getTypeArgument(0)!!
|
||||||
val receiverType = expression.symbol.owner.extensionReceiverParameter!!.type
|
val receiverType = expression.symbol.owner.extensionReceiverParameter!!.type
|
||||||
val receiverClass = receiverType.classifierOrFail as IrClassSymbol
|
val source = receiverType.classifierOrFail as IrClassSymbol
|
||||||
assert(receiverClass in integerClasses)
|
assert(source in integerClasses)
|
||||||
|
|
||||||
if (typeOperand is IrSimpleType && typeOperand.classifier in integerClasses && !typeOperand.hasQuestionMark) {
|
if (typeOperand is IrSimpleType && typeOperand.classifier in integerClasses && !typeOperand.hasQuestionMark) {
|
||||||
val typeOperandClass = typeOperand.classifier as IrClassSymbol
|
val target = typeOperand.classifier as IrClassSymbol
|
||||||
|
val valueToConvert = expression.extensionReceiver!!
|
||||||
|
|
||||||
val conversion = symbols.integerConversions[receiverClass to typeOperandClass]!!.owner
|
if (source in symbols.signedIntegerClasses && target in symbols.unsignedIntegerClasses) {
|
||||||
|
// Default Kotlin signed-to-unsigned widening integer conversions don't follow C rules.
|
||||||
builder.irCall(conversion).apply {
|
val signedTarget = symbols.unsignedToSignedOfSameBitWidth[target]!!
|
||||||
val valueToConvert = expression.extensionReceiver!!
|
val widened = builder.irConvertInteger(source, signedTarget, valueToConvert)
|
||||||
if (conversion.dispatchReceiverParameter != null) {
|
builder.irConvertInteger(signedTarget, target, widened)
|
||||||
dispatchReceiver = valueToConvert
|
} else {
|
||||||
} else {
|
builder.irConvertInteger(source, target, valueToConvert)
|
||||||
extensionReceiver = valueToConvert
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
context.reportCompilationError(
|
context.reportCompilationError(
|
||||||
@@ -987,6 +986,21 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun IrBuilderWithScope.irConvertInteger(
|
||||||
|
source: IrClassSymbol,
|
||||||
|
target: IrClassSymbol,
|
||||||
|
value: IrExpression
|
||||||
|
): IrExpression {
|
||||||
|
val conversion = symbols.integerConversions[source to target]!!
|
||||||
|
return irCall(conversion.owner).apply {
|
||||||
|
if (conversion.owner.dispatchReceiverParameter != null) {
|
||||||
|
dispatchReceiver = value
|
||||||
|
} else {
|
||||||
|
extensionReceiver = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun IrType.ensureSupportedInCallbacks(isReturnType: Boolean, reportError: (String) -> Nothing) {
|
private fun IrType.ensureSupportedInCallbacks(isReturnType: Boolean, reportError: (String) -> Nothing) {
|
||||||
this.checkCTypeNullability(reportError)
|
this.checkCTypeNullability(reportError)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user