generate prefix ++ and -- as intrinsics

This commit is contained in:
Dmitry Jemerov
2011-07-15 14:24:59 +02:00
parent 10d6e584ff
commit bda97c53df
3 changed files with 72 additions and 30 deletions
@@ -1006,7 +1006,7 @@ public class ExpressionCodegen extends JetVisitor {
return typeMapper.mapType(bindingContext.getExpressionType(expr));
}
private int indexOfLocal(JetReferenceExpression lhs) {
public int indexOfLocal(JetReferenceExpression lhs) {
final DeclarationDescriptor declarationDescriptor = bindingContext.resolveReferenceExpression(lhs);
return lookupLocal(declarationDescriptor);
}
@@ -1317,12 +1317,21 @@ public class ExpressionCodegen extends JetVisitor {
@Override
public void visitPrefixExpression(JetPrefixExpression expression) {
DeclarationDescriptor op = bindingContext.resolveReferenceExpression(expression.getOperationSign());
if (op instanceof FunctionDescriptor) {
final Type asmType = expressionType(expression);
generateUnaryOp(op, asmType, expression);
return;
final Callable callable = resolveToCallable(op);
if (callable instanceof IntrinsicMethod) {
IntrinsicMethod intrinsic = (IntrinsicMethod) callable;
myStack.push(intrinsic.generate(this, v, expressionType(expression), expression,
Arrays.asList(expression.getBaseExpression()), false));
}
else {
CallableMethod callableMethod = (CallableMethod) callable;
genToJVMStack(expression.getBaseExpression());
callableMethod.invoke(v);
final StackValue value = returnValueAsStackValue((FunctionDescriptor) op, callableMethod.getSignature().getReturnType());
if (value != null) {
myStack.push(value);
}
}
throw new UnsupportedOperationException("Don't know how to generate this prefix expression");
}
@Override
@@ -1348,30 +1357,6 @@ public class ExpressionCodegen extends JetVisitor {
throw new UnsupportedOperationException("Don't know how to generate this prefix expression");
}
private void generateUnaryOp(DeclarationDescriptor op, Type asmType, final JetUnaryExpression unaryExpression) {
final JetExpression operand = unaryExpression.getBaseExpression();
if (isNumberPrimitive(asmType) && (op.getName().equals("inc") || op.getName().equals("dec"))) {
myStack.push(generateIncrement(op, asmType, operand));
return;
}
final Callable callable = resolveToCallable(op);
if (callable instanceof IntrinsicMethod) {
IntrinsicMethod intrinsic = (IntrinsicMethod) callable;
myStack.push(intrinsic.generate(this, v, expressionType(unaryExpression), unaryExpression,
Arrays.asList(unaryExpression.getBaseExpression()), false));
}
else {
CallableMethod callableMethod = (CallableMethod) callable;
genToJVMStack(unaryExpression.getBaseExpression());
callableMethod.invoke(v);
final StackValue value = returnValueAsStackValue((FunctionDescriptor) op, callableMethod.getSignature().getReturnType());
if (value != null) {
myStack.push(value);
}
}
}
private StackValue generateIncrement(DeclarationDescriptor op, Type asmType, JetExpression operand) {
int increment = op.getName().equals("inc") ? 1 : -1;
if (operand instanceof JetReferenceExpression) {
@@ -0,0 +1,53 @@
package org.jetbrains.jet.codegen.intrinsics;
import com.intellij.psi.PsiElement;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.JetTypeMapper;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
import java.util.List;
/**
* @author yole
*/
public class Increment implements IntrinsicMethod {
private final int myDelta;
public Increment(int delta) {
myDelta = delta;
}
@Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, boolean haveReceiver) {
final JetExpression operand = arguments.get(0);
if (operand instanceof JetReferenceExpression) {
final int index = codegen.indexOfLocal((JetReferenceExpression) operand);
if (index >= 0 && JetTypeMapper.isIntPrimitive(expectedType)) {
v.iinc(index, myDelta);
return StackValue.local(index, expectedType);
}
}
StackValue value = codegen.generateIntermediateValue(operand);
value.dupReceiver(v, 0);
value.put(expectedType, v);
if (expectedType == Type.LONG_TYPE) {
v.aconst(Long.valueOf(myDelta));
}
else if (expectedType == Type.FLOAT_TYPE) {
v.aconst(Float.valueOf(myDelta));
}
else if (expectedType == Type.DOUBLE_TYPE) {
v.aconst(Double.valueOf(myDelta));
}
else {
v.aconst(myDelta);
}
v.add(expectedType);
value.store(v);
return value;
}
}
@@ -25,6 +25,8 @@ public class IntrinsicMethods {
private static final IntrinsicMethod TYPEINFO = new TypeInfo();
private static final IntrinsicMethod VALUE_TYPEINFO = new ValueTypeInfo();
private static final IntrinsicMethod RANGE_TO = new RangeTo();
private static final IntrinsicMethod INC = new Increment(1);
private static final IntrinsicMethod DEC = new Increment(-1);
private static final List<String> PRIMITIVE_NUMBER_TYPES = ImmutableList.of("Boolean", "Byte", "Char", "Short", "Int", "Float", "Long", "Double");
@@ -45,6 +47,8 @@ public class IntrinsicMethods {
declareIntrinsicFunction(type, "minus", 0, UNARY_MINUS);
declareIntrinsicFunction(type, "inv", 0, INV);
declareIntrinsicFunction(type, "rangeTo", 1, RANGE_TO);
declareIntrinsicFunction(type, "inc", 0, INC);
declareIntrinsicFunction(type, "dec", 0, DEC);
}
final FunctionGroup typeInfoFunctionGroup = stdlib.getTypeInfoFunctionGroup();