From bda97c53dfee2f149b3c9046bae63067ae73ad5a Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 15 Jul 2011 14:24:59 +0200 Subject: [PATCH] generate prefix ++ and -- as intrinsics --- .../jet/codegen/ExpressionCodegen.java | 45 ++++++---------- .../jet/codegen/intrinsics/Increment.java | 53 +++++++++++++++++++ .../codegen/intrinsics/IntrinsicMethods.java | 4 ++ 3 files changed, 72 insertions(+), 30 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/codegen/intrinsics/Increment.java diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 02e31d88dda..5920fa4f3a3 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -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) { diff --git a/idea/src/org/jetbrains/jet/codegen/intrinsics/Increment.java b/idea/src/org/jetbrains/jet/codegen/intrinsics/Increment.java new file mode 100644 index 00000000000..e8679429e4e --- /dev/null +++ b/idea/src/org/jetbrains/jet/codegen/intrinsics/Increment.java @@ -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 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; + } +} diff --git a/idea/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java b/idea/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java index b3285004a4f..6e4fbff5a21 100644 --- a/idea/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java +++ b/idea/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java @@ -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 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();