From 6e9d5ebe78e6a95634870a839d83472b88ef96dd Mon Sep 17 00:00:00 2001 From: Michael Bogdanov Date: Sat, 4 Apr 2015 10:45:31 +0300 Subject: [PATCH] RenageTo convertion & before call --- .../kotlin/codegen/CallableMethod.java | 5 + .../kotlin/codegen/ExpressionCodegen.java | 10 +- .../kotlin/codegen/ExtendedCallable.java | 4 + .../codegen/intrinsics/IntrinsicCallable.kt | 5 + .../codegen/intrinsics/IntrinsicMethod.java | 8 +- .../kotlin/codegen/intrinsics/RangeTo.kt | 122 +++++++++++------- 6 files changed, 102 insertions(+), 52 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/CallableMethod.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/CallableMethod.java index 6f1c6a205c7..0a4a8eab4c6 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/CallableMethod.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/CallableMethod.java @@ -181,4 +181,9 @@ public class CallableMethod implements ExtendedCallable { public boolean isStaticCall() { return invokeOpcode == Opcodes.INVOKESTATIC; } + + @Override + public void beforeParameterGeneration(@NotNull InstructionAdapter v, @Nullable StackValue value) { + + } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 124172992f8..b95b7ea554e 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -2347,6 +2347,7 @@ public class ExpressionCodegen extends JetVisitor implem @NotNull CallGenerator callGenerator, @NotNull ArgumentGenerator argumentGenerator ) { + StackValue.SafeCall safeCallReceiver = receiver instanceof StackValue.SafeCall ? (StackValue.SafeCall) receiver : null; if (!(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor)) { // otherwise already receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod); @@ -2358,7 +2359,14 @@ public class ExpressionCodegen extends JetVisitor implem } } - receiver.put(receiver.type, v); + if (safeCallReceiver != null) { + //justCoerce + receiver.put(receiver.type, v); + callableMethod.beforeParameterGeneration(v, StackValue.onStack(receiver.type)); + } else { + callableMethod.beforeParameterGeneration(v, null); + receiver.put(receiver.type, v); + } } callGenerator.putHiddenParams(); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExtendedCallable.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExtendedCallable.java index bb59bbcb61a..73bd8f63508 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExtendedCallable.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExtendedCallable.java @@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; +import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument; import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; @@ -55,4 +56,7 @@ public interface ExtendedCallable extends Callable { @Nullable Type getReceiverClass(); + + void beforeParameterGeneration(@NotNull InstructionAdapter v, @Nullable StackValue value); + } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/IntrinsicCallable.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/IntrinsicCallable.kt index f064357b5fd..f708bf57536 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/IntrinsicCallable.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/IntrinsicCallable.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen.intrinsics import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.codegen.CallableMethod import org.jetbrains.kotlin.codegen.ExtendedCallable +import org.jetbrains.kotlin.codegen.StackValue import org.jetbrains.kotlin.codegen.context.CodegenContext import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.descriptors.CallableDescriptor @@ -112,6 +113,10 @@ public abstract class IntrinsicCallable(val returnType1: Type, public fun calcReceiverType(): Type? { return getReceiverClass() ?: getThisType() } + + override fun beforeParameterGeneration(v: InstructionAdapter, value: StackValue?) { + + } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/IntrinsicMethod.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/IntrinsicMethod.java index e1bb21c33b6..b7ec6a5a60a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/IntrinsicMethod.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/IntrinsicMethod.java @@ -104,7 +104,13 @@ public abstract class IntrinsicMethod implements Callable { } }); } + public Type nullOrObject(Type type) { - return type == null ? null : AsmTypes.OBJECT_TYPE; + return nullOr(type, AsmTypes.OBJECT_TYPE); } + + public Type nullOr(Type type, Type newType) { + return type == null ? null : newType; + } + } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/RangeTo.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/RangeTo.kt index c09557ca961..258fe40aab1 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/RangeTo.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/intrinsics/RangeTo.kt @@ -14,82 +14,104 @@ * limitations under the License. */ -package org.jetbrains.kotlin.codegen.intrinsics; +package org.jetbrains.kotlin.codegen.intrinsics -import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.kotlin.codegen.ExpressionCodegen; -import org.jetbrains.kotlin.codegen.StackValue; -import org.jetbrains.kotlin.psi.JetBinaryExpression; -import org.jetbrains.kotlin.psi.JetExpression; -import org.jetbrains.org.objectweb.asm.Type; -import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.codegen.ExpressionCodegen +import org.jetbrains.kotlin.codegen.ExtendedCallable +import org.jetbrains.kotlin.codegen.StackValue +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.psi.JetBinaryExpression +import org.jetbrains.kotlin.psi.JetExpression +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter -import java.util.List; +import org.jetbrains.org.objectweb.asm.Type.* -import static org.jetbrains.org.objectweb.asm.Type.*; +public class RangeTo : IntrinsicMethod() { + override fun generateImpl(codegen: ExpressionCodegen, v: InstructionAdapter, returnType: Type, element: PsiElement?, arguments: List, receiver: StackValue): Type { + v.anew(returnType) + v.dup() -public class RangeTo extends IntrinsicMethod { - @NotNull - @Override - public Type generateImpl( - @NotNull ExpressionCodegen codegen, - @NotNull InstructionAdapter v, - @NotNull Type returnType, - PsiElement element, - @NotNull List arguments, - @NotNull StackValue receiver - ) { - v.anew(returnType); - v.dup(); - - Type type; + val type: Type if (arguments.size() == 1) { - assert receiver instanceof StackValue.CallReceiver : - "Receiver in an intrinsic qualified expression should be CallReceiver: " + receiver + " on " + element.getText(); - type = parameterType(receiver.type, codegen.expressionType(arguments.get(0))); - receiver.put(type, v); - codegen.gen(arguments.get(0), type); + assert(receiver is StackValue.CallReceiver) { "Receiver in an intrinsic qualified expression should be CallReceiver: " + receiver + " on " + element!!.getText() } + type = parameterType(receiver.type, codegen.expressionType(arguments.get(0))) + receiver.put(type, v) + codegen.gen(arguments.get(0), type) } else { - JetBinaryExpression expression = (JetBinaryExpression) element; - type = parameterType(codegen.expressionType(expression.getLeft()), codegen.expressionType(expression.getRight())); - codegen.gen(expression.getLeft(), type); - codegen.gen(expression.getRight(), type); + val expression = element as JetBinaryExpression + type = parameterType(codegen.expressionType(expression.getLeft()), codegen.expressionType(expression.getRight())) + codegen.gen(expression.getLeft(), type) + codegen.gen(expression.getRight(), type) } - v.invokespecial(returnType.getInternalName(), "", Type.getMethodDescriptor(Type.VOID_TYPE, type, type), false); + v.invokespecial(returnType.getInternalName(), "", Type.getMethodDescriptor(Type.VOID_TYPE, type, type), false) - return returnType; + return returnType } - @NotNull - private static Type parameterType(@NotNull Type leftType, @NotNull Type rightType) { - int left = leftType.getSort(); - int right = rightType.getSort(); + private fun nameToPrimitive(name: String) : Type { + return when (name) { + "Double" -> DOUBLE_TYPE; + "Float" -> FLOAT_TYPE + "Long" -> LONG_TYPE + "Int" -> INT_TYPE + "Short" -> SHORT_TYPE + "Char" -> CHAR_TYPE + "Byte" -> BYTE_TYPE + else -> throw IllegalStateException("RangeTo intrinsic can only work for primitive types: " + name) + } + } + + private fun parameterType(leftType: Type, rightType: Type): Type { + val left = leftType.getSort() + val right = rightType.getSort() if (left == DOUBLE || right == DOUBLE) { - return DOUBLE_TYPE; + return DOUBLE_TYPE } else if (left == FLOAT || right == FLOAT) { - return FLOAT_TYPE; + return FLOAT_TYPE } else if (left == LONG || right == LONG) { - return LONG_TYPE; + return LONG_TYPE } else if (left == INT || right == INT) { - return INT_TYPE; + return INT_TYPE } else if (left == SHORT || right == SHORT) { - return SHORT_TYPE; + return SHORT_TYPE } else if (left == CHAR || right == CHAR) { - return CHAR_TYPE; + return CHAR_TYPE } else if (left == BYTE || right == BYTE) { - return BYTE_TYPE; + return BYTE_TYPE } else { - throw new IllegalStateException("RangeTo intrinsic can only work for primitive types: " + leftType + ", " + rightType); + throw IllegalStateException("RangeTo intrinsic can only work for primitive types: " + leftType + ", " + rightType) } } -} + + override fun supportCallable(): Boolean { + return true + } + + override fun toCallable(fd: FunctionDescriptor, isSuper: Boolean, resolvedCall: ResolvedCall<*>, codegen: ExpressionCodegen): ExtendedCallable { + val method = codegen.getState().getTypeMapper().mapToCallableMethod(fd, false, codegen.getContext()) + val argType = nameToPrimitive(method.getReturnType().getInternalName().substringAfter("kotlin/").substringBefore("Range")) + return object : IntrinsicCallable(method.getReturnType(), method.getValueParameterTypes().map { argType }, nullOr(method.getThisType(), argType), nullOr(method.getReceiverClass(), argType)) { + override fun beforeParameterGeneration(v: InstructionAdapter, value: StackValue?) { + v.anew(getReturnType()) + v.dup() + value?.moveToTopOfStack(value!!.type, v, 2) + } + + override fun invokeIntrinsic(v: InstructionAdapter) { + v.invokespecial(getReturnType().getInternalName(), "", Type.getMethodDescriptor(Type.VOID_TYPE, argType, argType), false) + } + } + } +} \ No newline at end of file