[Interop][Lowering] Fix support for Nothing expressions

Fix compilation failure in case of `cstructVar.field = TODO()`.

fixup! [Interop][Lowering] Fix support for Nothing expressions

fixup! [Interop][Lowering] Fix support for Nothing expressions
This commit is contained in:
Sergey Bogolepov
2020-05-19 14:40:36 +07:00
committed by Sergey Bogolepov
parent 18b0c7e4a6
commit d72a955411
@@ -100,16 +100,17 @@ private fun InteropCallContext.readValueFromMemory(
it.putValueArgument(0, nativePtr) it.putValueArgument(0, nativePtr)
}) })
} }
return castPrimitiveIfNeeded(memRead, returnType) return castPrimitiveIfNeeded(memRead, memoryValueType, returnType)
} }
private fun InteropCallContext.writeValueToMemory( private fun InteropCallContext.writeValueToMemory(
nativePtr: IrExpression, nativePtr: IrExpression,
value: IrExpression value: IrExpression,
targetType: IrType
): IrExpression { ): IrExpression {
val memoryValueType = determineInMemoryType(value.type) val memoryValueType = determineInMemoryType(targetType)
val memWriteFn = findMemoryAccessFunction(isRead = false, valueType = memoryValueType) val memWriteFn = findMemoryAccessFunction(isRead = false, valueType = memoryValueType)
val valueToWrite = castPrimitiveIfNeeded(value, memoryValueType) val valueToWrite = castPrimitiveIfNeeded(value, targetType, memoryValueType)
return with(builder) { return with(builder) {
irCall(memWriteFn).also { memWrite -> irCall(memWriteFn).also { memWrite ->
memWrite.dispatchReceiver = irGetObject(symbols.nativeMemUtils) memWrite.dispatchReceiver = irGetObject(symbols.nativeMemUtils)
@@ -132,12 +133,13 @@ private fun InteropCallContext.determineInMemoryType(type: IrType): IrType {
private fun InteropCallContext.castPrimitiveIfNeeded( private fun InteropCallContext.castPrimitiveIfNeeded(
value: IrExpression, value: IrExpression,
targetType: IrType fromType: IrType,
toType: IrType
): IrExpression { ): IrExpression {
val valueClass = value.type.classOrNull!! val sourceClass = fromType.classOrNull!!
val targetClass = targetType.classOrNull!! val targetClass = toType.classOrNull!!
return if (valueClass != targetClass) { return if (sourceClass != targetClass) {
val conversion = symbols.integerConversions.getValue(valueClass to targetClass) val conversion = symbols.integerConversions.getValue(sourceClass to targetClass)
builder.irCall(conversion.owner).apply { builder.irCall(conversion.owner).apply {
if (conversion.owner.dispatchReceiverParameter != null) { if (conversion.owner.dispatchReceiverParameter != null) {
dispatchReceiver = value dispatchReceiver = value
@@ -150,19 +152,23 @@ private fun InteropCallContext.castPrimitiveIfNeeded(
} }
} }
private fun InteropCallContext.convertEnumToIntegral(enumValue: IrExpression): IrExpression { private fun InteropCallContext.convertEnumToIntegral(enumValue: IrExpression, targetEnumType: IrType): IrExpression {
val enumClass = enumValue.type.getClass()!! val enumClass = targetEnumType.getClass()!!
val valueProperty = enumClass.properties.single { it.name.asString() == "value" } val valueProperty = enumClass.properties.single { it.name.asString() == "value" }
return builder.irCall(valueProperty.getter!!).also { return builder.irCall(valueProperty.getter!!).also {
it.dispatchReceiver = enumValue it.dispatchReceiver = enumValue
} }
} }
private fun InteropCallContext.convertIntegralToEnum(value: IrExpression, enumType: IrType): IrExpression { private fun InteropCallContext.convertIntegralToEnum(
value: IrExpression,
intergralType: IrType,
enumType: IrType
): IrExpression {
val enumClass = enumType.getClass()!! val enumClass = enumType.getClass()!!
val companionClass = enumClass.companionObject()!! as IrClass val companionClass = enumClass.companionObject()!! as IrClass
val byValue = companionClass.simpleFunctions().single { it.name.asString() == "byValue" } val byValue = companionClass.simpleFunctions().single { it.name.asString() == "byValue" }
val byValueArg = castPrimitiveIfNeeded(value, byValue.valueParameters.first().type) val byValueArg = castPrimitiveIfNeeded(value, intergralType, byValue.valueParameters.first().type)
return builder.irCall(byValue).apply { return builder.irCall(byValue).apply {
dispatchReceiver = builder.irGetObject(companionClass.symbol) dispatchReceiver = builder.irGetObject(companionClass.symbol)
putValueArgument(0, byValueArg) putValueArgument(0, byValueArg)
@@ -179,12 +185,16 @@ private fun IrType.getCEnumPrimitiveType(): IrType {
private fun InteropCallContext.readEnumValueFromMemory(nativePtr: IrExpression, enumType: IrType): IrExpression { private fun InteropCallContext.readEnumValueFromMemory(nativePtr: IrExpression, enumType: IrType): IrExpression {
val enumPrimitiveType = enumType.getCEnumPrimitiveType() val enumPrimitiveType = enumType.getCEnumPrimitiveType()
val readMemory = readValueFromMemory(nativePtr, enumPrimitiveType) val readMemory = readValueFromMemory(nativePtr, enumPrimitiveType)
return convertIntegralToEnum(readMemory, enumType) return convertIntegralToEnum(readMemory, readMemory.type, enumType)
} }
private fun InteropCallContext.writeEnumValueToMemory(nativePtr: IrExpression, value: IrExpression): IrExpression { private fun InteropCallContext.writeEnumValueToMemory(
val valueToWrite = convertEnumToIntegral(value) nativePtr: IrExpression,
return writeValueToMemory(nativePtr, valueToWrite) value: IrExpression,
targetEnumType: IrType
): IrExpression {
val valueToWrite = convertEnumToIntegral(value, targetEnumType)
return writeValueToMemory(nativePtr, valueToWrite, targetEnumType.getCEnumPrimitiveType())
} }
private fun InteropCallContext.convertCPointerToNativePtr(cPointer: IrExpression): IrExpression { private fun InteropCallContext.convertCPointerToNativePtr(cPointer: IrExpression): IrExpression {
@@ -203,7 +213,7 @@ private fun InteropCallContext.writePointerToMemory(
pointerType.isCPointer() -> convertCPointerToNativePtr(value) pointerType.isCPointer() -> convertCPointerToNativePtr(value)
else -> error("Unsupported pointer type") else -> error("Unsupported pointer type")
} }
return writeValueToMemory(nativePtr, valueToWrite) return writeValueToMemory(nativePtr, valueToWrite, valueToWrite.type)
} }
private fun InteropCallContext.calculateFieldPointer(receiver: IrExpression, offset: Long): IrExpression { private fun InteropCallContext.calculateFieldPointer(receiver: IrExpression, offset: Long): IrExpression {
@@ -261,7 +271,10 @@ private fun InteropCallContext.generateEnumVarValueAccess(callSite: IrCall): IrE
} }
return when { return when {
accessor.isGetter -> readEnumValueFromMemory(nativePtr, accessor.returnType) accessor.isGetter -> readEnumValueFromMemory(nativePtr, accessor.returnType)
accessor.isSetter -> writeEnumValueToMemory(nativePtr, callSite.getValueArgument(0)!!) accessor.isSetter -> {
val type = accessor.valueParameters[0].type
writeEnumValueToMemory(nativePtr, callSite.getValueArgument(0)!!, type)
}
else -> error("") else -> error("")
} }
} }
@@ -286,8 +299,8 @@ private fun InteropCallContext.generateMemberAtAccess(callSite: IrCall): IrExpre
val value = callSite.getValueArgument(0)!! val value = callSite.getValueArgument(0)!!
val type = accessor.valueParameters[0].type val type = accessor.valueParameters[0].type
when { when {
type.isCEnumType() -> writeEnumValueToMemory(fieldPointer, value) type.isCEnumType() -> writeEnumValueToMemory(fieldPointer, value, type)
type.isStoredInMemoryDirectly() -> writeValueToMemory(fieldPointer, value) type.isStoredInMemoryDirectly() -> writeValueToMemory(fieldPointer, value, type)
type.isCPointer() -> writePointerToMemory(fieldPointer, value, type) type.isCPointer() -> writePointerToMemory(fieldPointer, value, type)
else -> error("Cannot set field of type ${type.getClass()?.name}") else -> error("Cannot set field of type ${type.getClass()?.name}")
} }
@@ -310,14 +323,15 @@ private fun InteropCallContext.writeBits(
base: IrExpression, base: IrExpression,
offset: Long, offset: Long,
size: Int, size: Int,
value: IrExpression value: IrExpression,
type: IrType
): IrExpression { ): IrExpression {
val integralValue = when { val (integralValue, fromType) = when {
value.type.isCEnumType() -> convertEnumToIntegral(value) type.isCEnumType() -> convertEnumToIntegral(value, type) to type.getCEnumPrimitiveType()
else -> value else -> value to type
} }
val targetType = symbols.writeBits.owner.valueParameters.last().type val targetType = symbols.writeBits.owner.valueParameters.last().type
val valueToWrite = castPrimitiveIfNeeded(integralValue, targetType) val valueToWrite = castPrimitiveIfNeeded(integralValue, fromType, targetType)
return with(builder) { return with(builder) {
irCall(symbols.writeBits).also { irCall(symbols.writeBits).also {
it.putValueArgument(0, base) it.putValueArgument(0, base)
@@ -349,8 +363,8 @@ private fun InteropCallContext.readBits(
} }
} }
return when { return when {
type.isCEnumType() -> convertIntegralToEnum(integralValue, type) type.isCEnumType() -> convertIntegralToEnum(integralValue, integralValue.type, type)
else -> castPrimitiveIfNeeded(integralValue, type) else -> castPrimitiveIfNeeded(integralValue, integralValue.type, type)
} }
} }
@@ -365,7 +379,8 @@ private fun InteropCallContext.generateBitFieldAccess(callSite: IrCall): IrExpre
return when { return when {
accessor.isSetter -> { accessor.isSetter -> {
val argument = callSite.getValueArgument(0)!! val argument = callSite.getValueArgument(0)!!
writeBits(base, offset, size, argument) val type = accessor.valueParameters[0].type
writeBits(base, offset, size, argument, type)
} }
accessor.isGetter -> { accessor.isGetter -> {
val type = accessor.returnType val type = accessor.returnType