binary operations on numbers are intrinsics

This commit is contained in:
Dmitry Jemerov
2011-07-13 19:59:24 +02:00
parent 7a87d7e05c
commit 769b9cead5
3 changed files with 62 additions and 23 deletions
@@ -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);
@@ -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<JetExpression> arguments) {
codegen.gen(arguments.get(0), expectedType);
codegen.gen(arguments.get(1), expectedType);
v.visitInsn(expectedType.getOpcode(opcode));
return StackValue.onStack(expectedType);
}
}
@@ -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<String> PRIMITIVE_NUMBER_TYPES = ImmutableList.of("Boolean", "Byte", "Char", "Short", "Int", "Float", "Long", "Double");
private final JetStandardLibrary myStdLib;
private final Map<DeclarationDescriptor, IntrinsicMethod> myMethods = new HashMap<DeclarationDescriptor, IntrinsicMethod>();
@@ -31,8 +37,7 @@ public class IntrinsicMethods {
}
declareIntrinsicProperty("Array", "size", ARRAY_SIZE);
List<String> 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) {