Implemented intrinsics dataClassArrayToString & dataClassArrayHashCode
This commit is contained in:
+27
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.kotlin.backend.common.ir
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.replace
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
@@ -8,9 +9,11 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
// This is what Context collects about IR.
|
||||
@@ -92,6 +95,30 @@ open class Symbols<out T: CommonBackendContext>(val context: T, private val symb
|
||||
|
||||
val arrays = PrimitiveType.values().map { primitiveArrayClass(it) } + array
|
||||
|
||||
private fun arrayExtensionFun(type: KotlinType, name: String): IrSimpleFunctionSymbol {
|
||||
val descriptor = builtInsPackage("kotlin")
|
||||
.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND)
|
||||
.singleOrNull { it.valueParameters.isEmpty()
|
||||
&& (it.extensionReceiverParameter?.type?.constructor?.declarationDescriptor as? ClassDescriptor)?.defaultType == type }
|
||||
?: throw Error(type.toString())
|
||||
return symbolTable.referenceSimpleFunction(descriptor)
|
||||
}
|
||||
|
||||
|
||||
private val arrayTypes = arrayOf(
|
||||
builtIns.getPrimitiveArrayKotlinType(PrimitiveType.BYTE),
|
||||
builtIns.getPrimitiveArrayKotlinType(PrimitiveType.CHAR),
|
||||
builtIns.getPrimitiveArrayKotlinType(PrimitiveType.SHORT),
|
||||
builtIns.getPrimitiveArrayKotlinType(PrimitiveType.INT),
|
||||
builtIns.getPrimitiveArrayKotlinType(PrimitiveType.LONG),
|
||||
builtIns.getPrimitiveArrayKotlinType(PrimitiveType.FLOAT),
|
||||
builtIns.getPrimitiveArrayKotlinType(PrimitiveType.DOUBLE),
|
||||
builtIns.getPrimitiveArrayKotlinType(PrimitiveType.BOOLEAN),
|
||||
builtIns.array.defaultType
|
||||
)
|
||||
val arrayContentToString = arrayTypes.associateBy({ it }, { arrayExtensionFun(it, "contentToString") })
|
||||
val arrayContentHashCode = arrayTypes.associateBy({ it }, { arrayExtensionFun(it, "contentHashCode") })
|
||||
|
||||
val copyRangeTo = arrays.map { symbol ->
|
||||
val packageViewDescriptor = builtIns.builtInsModule.getPackage(KotlinBuiltIns.COLLECTIONS_PACKAGE_FQ_NAME)
|
||||
val functionDescriptor = packageViewDescriptor.memberScope
|
||||
|
||||
+3
@@ -63,6 +63,9 @@ internal class KonanLower(val context: Context) {
|
||||
phaser.phase(KonanPhase.LOWER_STRING_CONCAT) {
|
||||
StringConcatenationLowering(context).lower(irFile)
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_DATA_CLASSES) {
|
||||
DataClassOperatorsLowering(context).runOnFilePostfix(irFile)
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_ENUMS) {
|
||||
EnumClassLowering(context).run(irFile)
|
||||
}
|
||||
|
||||
+1
@@ -50,6 +50,7 @@ enum class KonanPhase(val description: String,
|
||||
/* ... ... */ LOWER_TYPE_OPERATORS("Type operators lowering", LOWER_COROUTINES),
|
||||
/* ... ... */ BRIDGES_BUILDING("Bridges building", LOWER_COROUTINES),
|
||||
/* ... ... */ LOWER_STRING_CONCAT("String concatenation lowering"),
|
||||
/* ... ... */ LOWER_DATA_CLASSES("Data classes lowering"),
|
||||
/* ... ... */ AUTOBOX("Autoboxing of primitive types", BRIDGES_BUILDING, LOWER_COROUTINES),
|
||||
/* ... */ BITCODE("LLVM BitCode Generation"),
|
||||
/* ... ... */ RTTI("RTTI Generation"),
|
||||
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FunctionLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irBlock
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
|
||||
internal class DataClassOperatorsLowering(val context: Context): FunctionLoweringPass {
|
||||
|
||||
private val irBuiltins = context.irModule!!.irBuiltins
|
||||
|
||||
override fun lower(irFunction: IrFunction) {
|
||||
irFunction.transformChildrenVoid(object: IrElementTransformerVoid() {
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
if (expression.symbol != irBuiltins.dataClassArrayMemberToStringSymbol
|
||||
&& expression.symbol != irBuiltins.dataClassArrayMemberHashCodeSymbol)
|
||||
return expression
|
||||
|
||||
val argument = expression.getValueArgument(0)!!
|
||||
val argumentType = argument.type.makeNotNullable()
|
||||
val genericType =
|
||||
if (argumentType.arguments.isEmpty())
|
||||
argumentType
|
||||
else
|
||||
(argumentType.constructor.declarationDescriptor as ClassDescriptor).defaultType
|
||||
val isToString = expression.symbol == irBuiltins.dataClassArrayMemberToStringSymbol
|
||||
val newSymbol = if (isToString)
|
||||
context.ir.symbols.arrayContentToString[genericType]!!
|
||||
else
|
||||
context.ir.symbols.arrayContentHashCode[genericType]!!
|
||||
|
||||
val startOffset = expression.startOffset
|
||||
val endOffset = expression.endOffset
|
||||
val irBuilder = context.createIrBuilder(irFunction.symbol, startOffset, endOffset)
|
||||
|
||||
return irBuilder.run {
|
||||
val typeArguments =
|
||||
if (argumentType.arguments.isEmpty())
|
||||
emptyList<KotlinType>()
|
||||
else argumentType.arguments.map { it.type }
|
||||
if (!argument.type.isMarkedNullable) {
|
||||
irCall(newSymbol, typeArguments).apply {
|
||||
extensionReceiver = argument
|
||||
}
|
||||
} else {
|
||||
val tmp = scope.createTemporaryVariable(argument)
|
||||
val call = irCall(newSymbol, typeArguments).apply {
|
||||
extensionReceiver = irGet(tmp.symbol)
|
||||
}
|
||||
irBlock(argument) {
|
||||
+tmp
|
||||
+irIfThenElse(call.type,
|
||||
irEqeqeq(irGet(tmp.symbol), irNull()),
|
||||
if (isToString)
|
||||
irString("null")
|
||||
else
|
||||
irInt(0),
|
||||
call)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user