RenageTo convertion & before call

This commit is contained in:
Michael Bogdanov
2015-04-04 10:45:31 +03:00
parent 83f8dae9ac
commit 6e9d5ebe78
6 changed files with 102 additions and 52 deletions
@@ -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) {
}
}
@@ -2347,6 +2347,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> 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<StackValue, StackValue> 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();
@@ -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);
}
@@ -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?) {
}
}
@@ -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;
}
}
@@ -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<JetExpression>, 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<JetExpression> 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(), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, type, type), false);
v.invokespecial(returnType.getInternalName(), "<init>", 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(), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, argType, argType), false)
}
}
}
}