From 769b9cead59b7b3bfc88abbe9ea170848046b3c7 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 13 Jul 2011 19:59:24 +0200 Subject: [PATCH] binary operations on numbers are intrinsics --- .../jet/codegen/ExpressionCodegen.java | 26 ++++------------ .../jet/codegen/intrinsics/BinaryOp.java | 29 ++++++++++++++++++ .../codegen/intrinsics/IntrinsicMethods.java | 30 +++++++++++++++++-- 3 files changed, 62 insertions(+), 23 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/codegen/intrinsics/BinaryOp.java diff --git a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 515d3fc0749..ac3baabc7c8 100644 --- a/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1079,13 +1079,14 @@ public class ExpressionCodegen extends JetVisitor { else { DeclarationDescriptor op = bindingContext.resolveReferenceExpression(expression.getOperationReference()); if (op instanceof FunctionDescriptor) { - DeclarationDescriptor cls = op.getContainingDeclaration(); - if (isNumberPrimitive(cls)) { - int opcode = opcodeForMethod(op.getName()); - generateBinaryOp(expression, (FunctionDescriptor) op, opcode); + final IntrinsicMethod intrinsic = intrinsics.getIntrinsic(op); + if (intrinsic != null) { + myStack.push(intrinsic.generate(this, v, expressionType(expression), expression, + Arrays.asList(expression.getLeft(), expression.getRight()))); return; } - else if (isClass(cls, "String") && op.getName().equals("plus")) { + DeclarationDescriptor cls = op.getContainingDeclaration(); + if (isClass(cls, "String") && op.getName().equals("plus")) { generateConcatenation(expression); return; } @@ -1240,21 +1241,6 @@ public class ExpressionCodegen extends JetVisitor { throw new UnsupportedOperationException("Don't know how to generate binary op method " + name); } - private void generateBinaryOp(JetBinaryExpression expression, FunctionDescriptor op, int opcode) { - JetType returnType = op.getReturnType(); - final Type asmType = typeMapper.mapType(returnType); - if (asmType == Type.INT_TYPE || asmType == Type.LONG_TYPE || - asmType == Type.FLOAT_TYPE || asmType == Type.DOUBLE_TYPE) { - gen(expression.getLeft(), asmType); - gen(expression.getRight(), asmType); - v.visitInsn(asmType.getOpcode(opcode)); - myStack.push(StackValue.onStack(asmType)); - } - else { - throw new UnsupportedOperationException("Don't know how to generate binary op with return type " + returnType); - } - } - private void generateCompareOp(JetExpression left, JetExpression right, IElementType opToken, Type operandType) { gen(left, operandType); gen(right, operandType); diff --git a/idea/src/org/jetbrains/jet/codegen/intrinsics/BinaryOp.java b/idea/src/org/jetbrains/jet/codegen/intrinsics/BinaryOp.java new file mode 100644 index 00000000000..78253d2b0bb --- /dev/null +++ b/idea/src/org/jetbrains/jet/codegen/intrinsics/BinaryOp.java @@ -0,0 +1,29 @@ +package org.jetbrains.jet.codegen.intrinsics; + +import com.intellij.psi.PsiElement; +import org.jetbrains.jet.codegen.ExpressionCodegen; +import org.jetbrains.jet.codegen.StackValue; +import org.jetbrains.jet.lang.psi.JetExpression; +import org.objectweb.asm.Type; +import org.objectweb.asm.commons.InstructionAdapter; + +import java.util.List; + +/** + * @author yole + */ +public class BinaryOp implements IntrinsicMethod { + private final int opcode; + + public BinaryOp(int opcode) { + this.opcode = opcode; + } + + @Override + public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List arguments) { + codegen.gen(arguments.get(0), expectedType); + codegen.gen(arguments.get(1), expectedType); + v.visitInsn(expectedType.getOpcode(opcode)); + return StackValue.onStack(expectedType); + } +} diff --git a/idea/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java b/idea/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java index 0e02797523a..47280c57ffe 100644 --- a/idea/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java +++ b/idea/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java @@ -6,8 +6,12 @@ import org.jetbrains.jet.lang.resolve.JetScope; import org.jetbrains.jet.lang.types.JetStandardClasses; import org.jetbrains.jet.lang.types.JetStandardLibrary; import org.jetbrains.jet.lang.types.TypeProjection; +import org.objectweb.asm.Opcodes; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * @author yole @@ -20,6 +24,8 @@ public class IntrinsicMethods { private static final IntrinsicMethod TYPEINFO = new TypeInfo(); private static final IntrinsicMethod VALUE_TYPEINFO = new ValueTypeInfo(); + private static final List PRIMITIVE_NUMBER_TYPES = ImmutableList.of("Boolean", "Byte", "Char", "Short", "Int", "Float", "Long", "Double"); + private final JetStandardLibrary myStdLib; private final Map myMethods = new HashMap(); @@ -31,8 +37,7 @@ public class IntrinsicMethods { } declareIntrinsicProperty("Array", "size", ARRAY_SIZE); - List primitiveNumberTypes = ImmutableList.of("Boolean", "Byte", "Char", "Short", "Int", "Float", "Long", "Double"); - for (String primitiveNumberType : primitiveNumberTypes) { + for (String primitiveNumberType : PRIMITIVE_NUMBER_TYPES) { declareIntrinsicFunction(primitiveNumberType, "minus", 0, UNARY_MINUS); declareIntrinsicFunction(primitiveNumberType, "inv", 0, INV); } @@ -40,6 +45,25 @@ public class IntrinsicMethods { final FunctionGroup typeInfoFunctionGroup = stdlib.getTypeInfoFunctionGroup(); declareOverload(typeInfoFunctionGroup, 0, TYPEINFO); declareOverload(typeInfoFunctionGroup, 1, VALUE_TYPEINFO); + + declareBinaryOp("plus", Opcodes.IADD); + declareBinaryOp("minus", Opcodes.ISUB); + declareBinaryOp("times", Opcodes.IMUL); + declareBinaryOp("div", Opcodes.IDIV); + declareBinaryOp("mod", Opcodes.IREM); + declareBinaryOp("shl", Opcodes.ISHL); + declareBinaryOp("shr", Opcodes.ISHR); + declareBinaryOp("ushr", Opcodes.IUSHR); + declareBinaryOp("and", Opcodes.IAND); + declareBinaryOp("or", Opcodes.IOR); + declareBinaryOp("xor", Opcodes.IXOR); + } + + private void declareBinaryOp(String methodName, int opcode) { + BinaryOp op = new BinaryOp(opcode); + for (String type : PRIMITIVE_NUMBER_TYPES) { + declareIntrinsicFunction(type, methodName, 1, op); + } } private void declareIntrinsicProperty(String className, String methodName, IntrinsicMethod implementation) {