Experimental 'CompareTo' intrinsic

This commit is contained in:
Michael Bogdanov
2016-09-21 15:57:27 +03:00
committed by Dmitry Petrov
parent 0c92174e42
commit 29bd7c3804
3 changed files with 61 additions and 9 deletions
@@ -16,10 +16,19 @@
package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.BlockInfo
import org.jetbrains.kotlin.backend.jvm.ExpressionCodegen
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.codegen.AsmUtil.comparisonOperandType
import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive
import org.jetbrains.kotlin.codegen.OwnerKind
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.IrUnaryPrimitiveImpl
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
@@ -37,12 +46,42 @@ class CompareTo : IntrinsicMethod() {
}
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
val parameterType = comparisonOperandType(
expressionType(expression.dispatchReceiver ?: expression.extensionReceiver!!, context),
signature.valueParameters.single().asmType
)
return IrIntrinsicFunction.create(expression, signature, listOf(parameterType, parameterType)) {
genInvoke(parameterType, it)
assert (expression is IrUnaryPrimitiveImpl)
val compareCall = expression.getValueArgument(0) as IrCall
val args = compareCall.receiverAndArgs()
val argTypes = args.asmTypes(context)
val leftType = argTypes[0]
val rightType = argTypes[1]
val parameterType = comparisonOperandType(leftType, rightType)
val newSignature = context.state.typeMapper.mapSignatureSkipGeneric(compareCall.descriptor as FunctionDescriptor, OwnerKind.IMPLEMENTATION)
return object : IrIntrinsicFunction(compareCall, newSignature, listOf(parameterType, parameterType)) {
override fun invoke(v: InstructionAdapter, codegen: ExpressionCodegen, data: BlockInfo): StackValue {
val isPrimitiveIntrinsic = codegen.intrinsics.intrinsics.getIntrinsic(compareCall.descriptor as FunctionDescriptor) != null
val operationType: Type
val leftValue: StackValue
val rightValue: StackValue
if (isPrimitive(leftType) && isPrimitive(rightType) && isPrimitiveIntrinsic) {
operationType = comparisonOperandType(leftType, rightType)
leftValue = codegen.gen(args[0], operationType, data)
rightValue = codegen.gen(args[1], operationType,data)
}
else {
operationType = Type.INT_TYPE
leftValue = codegen.gen(compareCall, data)
rightValue = StackValue.constant(0, leftType)
}
val origin = expression.origin
val token = when (origin) {
IrStatementOrigin.GT -> KtTokens.GT
IrStatementOrigin.GTEQ -> KtTokens.GTEQ
IrStatementOrigin.LT -> KtTokens.LT
IrStatementOrigin.LTEQ -> KtTokens.LTEQ
else -> TODO()
}
StackValue.cmp(token, operationType, leftValue, rightValue).put(Type.BOOLEAN_TYPE, v)
return StackValue.onStack(Type.BOOLEAN_TYPE)
}
}
}
}
@@ -88,8 +88,7 @@ open class IrIntrinsicFunction(
signature: JvmMethodSignature,
context: JvmBackendContext,
invokeInstuction: (InstructionAdapter) -> Unit): IrIntrinsicFunction {
val args = (expression.dispatchReceiver?.let { listOf(context.state.typeMapper.mapType(it.type)) } ?: emptyList<Type>()) +
signature.valueParameters.map { it.asmType }
val args = expression.receiverAndArgs().map { context.state.typeMapper.mapType(it.type) }
return object : IrIntrinsicFunction(expression, signature, args) {
override fun genInvokeInstruction(v: InstructionAdapter) {
invokeInstuction(v)
@@ -104,4 +103,13 @@ open class IrIntrinsicFunction(
return create(expression, signature, listOf(type), invokeInstuction)
}
}
}
fun IrMemberAccessExpression.receiverAndArgs(): List<IrExpression> {
return (arrayListOf(this.dispatchReceiver, this.extensionReceiver) +
descriptor.valueParameters.mapIndexed { i, valueParameterDescriptor ->getValueArgument(i)}).filterNotNull()
}
fun List<IrExpression>.asmTypes(context: JvmBackendContext): List<Type> {
return map { context.state.typeMapper.mapType(it.type) }
}
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.lexer.KtTokens
class IrIntrinsicMethods(irBuiltIns: IrBuiltIns) {
private val intrinsics = IntrinsicMethods()
val intrinsics = IntrinsicMethods()
private val irMapping = hashMapOf<CallableMemberDescriptor, IntrinsicMethod>()
@@ -31,6 +31,11 @@ class IrIntrinsicMethods(irBuiltIns: IrBuiltIns) {
irMapping.put(irBuiltIns.eqeq, Equals(KtTokens.EQEQ))
irMapping.put(irBuiltIns.eqeqeq, Equals(KtTokens.EQEQEQ))
irMapping.put(irBuiltIns.booleanNot, Not())
val compare = CompareTo()
irMapping.put(irBuiltIns.lt0, compare)
irMapping.put(irBuiltIns.lteq0, compare)
irMapping.put(irBuiltIns.gt0, compare)
irMapping.put(irBuiltIns.gteq0, compare)
}
fun getIntrinsic(descriptor: CallableMemberDescriptor): IntrinsicMethod? {