binary operations on numbers are intrinsics
This commit is contained in:
@@ -1079,13 +1079,14 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
else {
|
else {
|
||||||
DeclarationDescriptor op = bindingContext.resolveReferenceExpression(expression.getOperationReference());
|
DeclarationDescriptor op = bindingContext.resolveReferenceExpression(expression.getOperationReference());
|
||||||
if (op instanceof FunctionDescriptor) {
|
if (op instanceof FunctionDescriptor) {
|
||||||
DeclarationDescriptor cls = op.getContainingDeclaration();
|
final IntrinsicMethod intrinsic = intrinsics.getIntrinsic(op);
|
||||||
if (isNumberPrimitive(cls)) {
|
if (intrinsic != null) {
|
||||||
int opcode = opcodeForMethod(op.getName());
|
myStack.push(intrinsic.generate(this, v, expressionType(expression), expression,
|
||||||
generateBinaryOp(expression, (FunctionDescriptor) op, opcode);
|
Arrays.asList(expression.getLeft(), expression.getRight())));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (isClass(cls, "String") && op.getName().equals("plus")) {
|
DeclarationDescriptor cls = op.getContainingDeclaration();
|
||||||
|
if (isClass(cls, "String") && op.getName().equals("plus")) {
|
||||||
generateConcatenation(expression);
|
generateConcatenation(expression);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1240,21 +1241,6 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
throw new UnsupportedOperationException("Don't know how to generate binary op method " + name);
|
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) {
|
private void generateCompareOp(JetExpression left, JetExpression right, IElementType opToken, Type operandType) {
|
||||||
gen(left, operandType);
|
gen(left, operandType);
|
||||||
gen(right, 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.JetStandardClasses;
|
||||||
import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
||||||
import org.jetbrains.jet.lang.types.TypeProjection;
|
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
|
* @author yole
|
||||||
@@ -20,6 +24,8 @@ public class IntrinsicMethods {
|
|||||||
private static final IntrinsicMethod TYPEINFO = new TypeInfo();
|
private static final IntrinsicMethod TYPEINFO = new TypeInfo();
|
||||||
private static final IntrinsicMethod VALUE_TYPEINFO = new ValueTypeInfo();
|
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 JetStandardLibrary myStdLib;
|
||||||
private final Map<DeclarationDescriptor, IntrinsicMethod> myMethods = new HashMap<DeclarationDescriptor, IntrinsicMethod>();
|
private final Map<DeclarationDescriptor, IntrinsicMethod> myMethods = new HashMap<DeclarationDescriptor, IntrinsicMethod>();
|
||||||
|
|
||||||
@@ -31,8 +37,7 @@ public class IntrinsicMethods {
|
|||||||
}
|
}
|
||||||
declareIntrinsicProperty("Array", "size", ARRAY_SIZE);
|
declareIntrinsicProperty("Array", "size", ARRAY_SIZE);
|
||||||
|
|
||||||
List<String> primitiveNumberTypes = ImmutableList.of("Boolean", "Byte", "Char", "Short", "Int", "Float", "Long", "Double");
|
for (String primitiveNumberType : PRIMITIVE_NUMBER_TYPES) {
|
||||||
for (String primitiveNumberType : primitiveNumberTypes) {
|
|
||||||
declareIntrinsicFunction(primitiveNumberType, "minus", 0, UNARY_MINUS);
|
declareIntrinsicFunction(primitiveNumberType, "minus", 0, UNARY_MINUS);
|
||||||
declareIntrinsicFunction(primitiveNumberType, "inv", 0, INV);
|
declareIntrinsicFunction(primitiveNumberType, "inv", 0, INV);
|
||||||
}
|
}
|
||||||
@@ -40,6 +45,25 @@ public class IntrinsicMethods {
|
|||||||
final FunctionGroup typeInfoFunctionGroup = stdlib.getTypeInfoFunctionGroup();
|
final FunctionGroup typeInfoFunctionGroup = stdlib.getTypeInfoFunctionGroup();
|
||||||
declareOverload(typeInfoFunctionGroup, 0, TYPEINFO);
|
declareOverload(typeInfoFunctionGroup, 0, TYPEINFO);
|
||||||
declareOverload(typeInfoFunctionGroup, 1, VALUE_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) {
|
private void declareIntrinsicProperty(String className, String methodName, IntrinsicMethod implementation) {
|
||||||
|
|||||||
Reference in New Issue
Block a user