Support some new intrinsics

This commit is contained in:
Michael Bogdanov
2016-09-27 14:08:44 +03:00
committed by Dmitry Petrov
parent 1cda60fcd1
commit af76840826
6 changed files with 37 additions and 73 deletions
@@ -456,7 +456,7 @@ class ExpressionCodegen(
get() = StackValue.onStack(this.asmType)
private fun resolveToCallable(irCall: IrMemberAccessExpression, isSuper: Boolean): Callable {
val intrinsic = intrinsics.getIntrinsic(irCall.descriptor as CallableMemberDescriptor)
val intrinsic = intrinsics.getIntrinsic(irCall.descriptor.original as CallableMemberDescriptor)
if (intrinsic != null) {
return intrinsic.toCallable(irCall, typeMapper.mapSignatureSkipGeneric(irCall.descriptor as FunctionDescriptor), classCodegen.context)
}
@@ -19,12 +19,8 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.codegen.Callable
import org.jetbrains.kotlin.codegen.CallableMethod
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.Type
@@ -38,16 +34,6 @@ abstract class IntrinsicMethod {
TODO()
}
open fun toCallable(
fd: FunctionDescriptor,
isSuper: Boolean,
resolvedCall: ResolvedCall<*>,
codegen: ExpressionCodegen
): Callable {
throw UnsupportedOperationException("Not implemented")
}
open fun toCallable(method: CallableMethod): Callable {
throw UnsupportedOperationException("Not implemented")
}
@@ -16,6 +16,8 @@
package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.codegen.BlockInfo
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.AsmUtil.boxType
import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive
@@ -23,53 +25,33 @@ import org.jetbrains.kotlin.codegen.Callable
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.getType
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
object JavaClassProperty : IntrinsicMethod() {
fun generate(
resolvedCall: ResolvedCall<*>?,
codegen: ExpressionCodegen,
returnType: Type,
receiver: StackValue
): StackValue? =
StackValue.operation(returnType) {
val actualType = generateImpl(it, receiver)
StackValue.coerce(actualType, returnType, it)
}
fun generateImpl(v: InstructionAdapter, receiver: StackValue): Type {
val type = receiver.type
if (isPrimitive(type)) {
if (!StackValue.couldSkipReceiverOnStaticCall(receiver)) {
receiver.put(type, v)
AsmUtil.pop(v, type)
}
v.getstatic(boxType(type).internalName, "TYPE", "Ljava/lang/Class;")
}
else {
receiver.put(type, v)
v.invokevirtual("java/lang/Object", "getClass", "()Ljava/lang/Class;", false)
}
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
return object: IrIntrinsicFunction(expression, signature, context) {
return getType(Class::class.java)
}
override fun toCallable(fd: FunctionDescriptor, isSuper: Boolean, resolvedCall: ResolvedCall<*>, codegen: ExpressionCodegen): Callable {
val classType = codegen.getState().typeMapper.mapType(resolvedCall.call.dispatchReceiver!!.type)
return object : IntrinsicCallable(getType(Class::class.java), listOf(), classType, null) {
override fun invokeIntrinsic(v: InstructionAdapter) {
if (isPrimitive(classType)) {
v.getstatic(boxType(classType).internalName, "TYPE", "Ljava/lang/Class;")
override fun invoke(v: InstructionAdapter, codegen: org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen, data: BlockInfo): StackValue {
val value = codegen.gen(expression.extensionReceiver!!, data)
val type = value.type
if (isPrimitive(type)) {
AsmUtil.pop(v, type)
v.getstatic(boxType(type).internalName, "TYPE", "Ljava/lang/Class;")
}
else {
v.invokevirtual("java/lang/Object", "getClass", "()Ljava/lang/Class;", false)
}
}
override fun isStaticCall() = isPrimitive(classType)
return with(codegen) {
expression.onStack
}
}
}
}
}
@@ -16,12 +16,14 @@
package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.codegen.Callable
import org.jetbrains.kotlin.codegen.CallableMethod
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
class StringGetChar : IntrinsicMethod() {
override fun toCallable(method: CallableMethod): Callable =
createIntrinsicCallable(method) {
it.invokevirtual("java/lang/String", "charAt", "(I)C", false)
}
}
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
return IrIntrinsicFunction.create(expression, signature, context) {
it.invokevirtual("java/lang/String", "charAt", "(I)C", false)
}
}
}
@@ -16,13 +16,15 @@
package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.codegen.Callable
import org.jetbrains.kotlin.codegen.CallableMethod
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
class StringPlus : IntrinsicMethod() {
override fun toCallable(method: CallableMethod): Callable =
createIntrinsicCallable(method) {
it.invokestatic("kotlin/jvm/internal/Intrinsics", "stringPlus",
"(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;", false)
}
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
return IrIntrinsicFunction.create(expression, signature, context) {
it.invokestatic("kotlin/jvm/internal/Intrinsics", "stringPlus",
"(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;", false)
}
}
}
@@ -18,21 +18,13 @@ package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.Callable
import org.jetbrains.kotlin.codegen.CallableMethod
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
class ToString : IntrinsicMethod() {
override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction {
return IrIntrinsicFunction.create(expression, signature, context) {
it.neg(AsmUtil.numberFunctionOperandType(signature.returnType))
}
}
override fun toCallable(method: CallableMethod): Callable {
val type = AsmUtil.stringValueOfType(method.dispatchReceiverType ?: method.extensionReceiverType)
return createUnaryIntrinsicCallable(method, newThisType = type) {
val type = AsmUtil.stringValueOfType(calcReceiverType(expression, context))
return IrIntrinsicFunction.create(expression, signature, context, type) {
it.invokestatic("java/lang/String", "valueOf", "(${type.descriptor})Ljava/lang/String;", false)
}
}