Implemented intrinsics dataClassArrayToString & dataClassArrayHashCode

This commit is contained in:
Igor Chevdar
2017-06-16 19:13:56 +03:00
parent 0c66db0720
commit dbc885b811
4 changed files with 107 additions and 0 deletions
@@ -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
@@ -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)
}
@@ -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"),
@@ -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)
}
}
}
}
})
}
}