Implemented intrinsics dataClassArrayToString & dataClassArrayHashCode
This commit is contained in:
+27
@@ -1,6 +1,7 @@
|
|||||||
package org.jetbrains.kotlin.backend.common.ir
|
package org.jetbrains.kotlin.backend.common.ir
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
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.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
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.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
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.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
|
||||||
// This is what Context collects about IR.
|
// 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
|
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 copyRangeTo = arrays.map { symbol ->
|
||||||
val packageViewDescriptor = builtIns.builtInsModule.getPackage(KotlinBuiltIns.COLLECTIONS_PACKAGE_FQ_NAME)
|
val packageViewDescriptor = builtIns.builtInsModule.getPackage(KotlinBuiltIns.COLLECTIONS_PACKAGE_FQ_NAME)
|
||||||
val functionDescriptor = packageViewDescriptor.memberScope
|
val functionDescriptor = packageViewDescriptor.memberScope
|
||||||
|
|||||||
+3
@@ -63,6 +63,9 @@ internal class KonanLower(val context: Context) {
|
|||||||
phaser.phase(KonanPhase.LOWER_STRING_CONCAT) {
|
phaser.phase(KonanPhase.LOWER_STRING_CONCAT) {
|
||||||
StringConcatenationLowering(context).lower(irFile)
|
StringConcatenationLowering(context).lower(irFile)
|
||||||
}
|
}
|
||||||
|
phaser.phase(KonanPhase.LOWER_DATA_CLASSES) {
|
||||||
|
DataClassOperatorsLowering(context).runOnFilePostfix(irFile)
|
||||||
|
}
|
||||||
phaser.phase(KonanPhase.LOWER_ENUMS) {
|
phaser.phase(KonanPhase.LOWER_ENUMS) {
|
||||||
EnumClassLowering(context).run(irFile)
|
EnumClassLowering(context).run(irFile)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -50,6 +50,7 @@ enum class KonanPhase(val description: String,
|
|||||||
/* ... ... */ LOWER_TYPE_OPERATORS("Type operators lowering", LOWER_COROUTINES),
|
/* ... ... */ LOWER_TYPE_OPERATORS("Type operators lowering", LOWER_COROUTINES),
|
||||||
/* ... ... */ BRIDGES_BUILDING("Bridges building", LOWER_COROUTINES),
|
/* ... ... */ BRIDGES_BUILDING("Bridges building", LOWER_COROUTINES),
|
||||||
/* ... ... */ LOWER_STRING_CONCAT("String concatenation lowering"),
|
/* ... ... */ LOWER_STRING_CONCAT("String concatenation lowering"),
|
||||||
|
/* ... ... */ LOWER_DATA_CLASSES("Data classes lowering"),
|
||||||
/* ... ... */ AUTOBOX("Autoboxing of primitive types", BRIDGES_BUILDING, LOWER_COROUTINES),
|
/* ... ... */ AUTOBOX("Autoboxing of primitive types", BRIDGES_BUILDING, LOWER_COROUTINES),
|
||||||
/* ... */ BITCODE("LLVM BitCode Generation"),
|
/* ... */ BITCODE("LLVM BitCode Generation"),
|
||||||
/* ... ... */ RTTI("RTTI 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