Do not cast arguments of binary operation to expected type for byte and short
This commit is contained in:
@@ -631,6 +631,14 @@ public class AsmUtil {
|
||||
return Type.INT_TYPE;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Type numberFunctionOperandType(@NotNull Type expectedType) {
|
||||
if (expectedType == Type.SHORT_TYPE || expectedType == Type.BYTE_TYPE) {
|
||||
return Type.INT_TYPE;
|
||||
}
|
||||
return expectedType;
|
||||
}
|
||||
|
||||
public static void pop(@NotNull InstructionAdapter v, @NotNull Type type) {
|
||||
if (type.getSize() == 2) {
|
||||
v.pop2();
|
||||
|
||||
@@ -36,7 +36,7 @@ import org.jetbrains.jet.codegen.binding.CalculatedClosure;
|
||||
import org.jetbrains.jet.codegen.binding.CodegenBinding;
|
||||
import org.jetbrains.jet.codegen.binding.MutableClosure;
|
||||
import org.jetbrains.jet.codegen.context.*;
|
||||
import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethod;
|
||||
import org.jetbrains.jet.codegen.intrinsics.*;
|
||||
import org.jetbrains.jet.codegen.signature.JvmMethodSignature;
|
||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||
import org.jetbrains.jet.codegen.state.JetTypeMapper;
|
||||
@@ -1652,8 +1652,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
|
||||
IntrinsicMethod intrinsic = state.getIntrinsics().getIntrinsic(memberDescriptor);
|
||||
if (intrinsic != null) {
|
||||
Type expectedType = expressionType(expression);
|
||||
return intrinsic.generate(this, v, expectedType, expression, Collections.<JetExpression>emptyList(), receiver, state);
|
||||
Type returnType = typeMapper.mapType(memberDescriptor.getReturnType());
|
||||
return intrinsic.generate(this, v, returnType, expression, Collections.<JetExpression>emptyList(), receiver, state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2030,14 +2030,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
for (ValueArgument argument : call.getValueArguments()) {
|
||||
args.add(argument.getArgumentExpression());
|
||||
}
|
||||
JetType type = resolvedCall.getResultingDescriptor().getReturnType();
|
||||
assert type != null;
|
||||
Type callType = typeMapper.mapType(type);
|
||||
|
||||
Type exprType = asmTypeOrVoid(type);
|
||||
StackValue stackValue = intrinsic.generate(this, v, callType, call.getCallElement(), args, receiver, state);
|
||||
stackValue.put(exprType, v);
|
||||
return StackValue.onStack(exprType);
|
||||
Type returnType = typeMapper.mapType(resolvedCall.getResultingDescriptor().getReturnType());
|
||||
|
||||
StackValue stackValue = intrinsic.generate(this, v, returnType, call.getCallElement(), args, receiver, state);
|
||||
stackValue.put(returnType, v);
|
||||
return StackValue.onStack(returnType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2682,7 +2680,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
Callable callable = resolveToCallable((FunctionDescriptor) op, false);
|
||||
if (callable instanceof IntrinsicMethod) {
|
||||
IntrinsicMethod intrinsic = (IntrinsicMethod) callable;
|
||||
return intrinsic.generate(this, v, expressionType(expression), expression,
|
||||
Type returnType = typeMapper.mapType(resolvedCall.getResultingDescriptor().getReturnType());
|
||||
return intrinsic.generate(this, v, returnType, expression,
|
||||
Arrays.asList(expression.getLeft(), expression.getRight()), receiver, state);
|
||||
}
|
||||
else {
|
||||
@@ -2929,10 +2928,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
//noinspection NullableProblems
|
||||
JetExpression right = expression.getRight();
|
||||
assert right != null;
|
||||
StackValue stackValue = intrinsic.generate(this, v, lhsType, expression,
|
||||
Type returnType = typeMapper.mapType(((FunctionDescriptor) op).getReturnType());
|
||||
StackValue stackValue = intrinsic.generate(this, v, returnType, expression,
|
||||
Arrays.asList(right),
|
||||
StackValue.onStack(lhsType), state);
|
||||
value.store(stackValue.type, v);
|
||||
value.store(lhsType, v);
|
||||
}
|
||||
else {
|
||||
callAugAssignMethod(expression, (CallableMethod) callable, lhsType, true);
|
||||
@@ -3018,7 +3018,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
if (callable instanceof IntrinsicMethod) {
|
||||
IntrinsicMethod intrinsic = (IntrinsicMethod) callable;
|
||||
//noinspection ConstantConditions
|
||||
return intrinsic.generate(this, v, expressionType(expression), expression,
|
||||
Type returnType = typeMapper.mapType(((FunctionDescriptor) op).getReturnType());
|
||||
return intrinsic.generate(this, v, returnType, expression,
|
||||
Arrays.asList(expression.getBaseExpression()), receiver, state);
|
||||
}
|
||||
else {
|
||||
@@ -3589,7 +3590,7 @@ The "returned" value of try expression with no finally is either the last expres
|
||||
DeclarationDescriptor descriptor = rightType.getConstructor().getDeclarationDescriptor();
|
||||
if (descriptor instanceof ClassDescriptor || descriptor instanceof TypeParameterDescriptor) {
|
||||
StackValue value = genQualified(receiver, left);
|
||||
value.put(boxType(value.type), v);
|
||||
value.put(boxType(rightTypeAsm), v);
|
||||
|
||||
if (opToken != JetTokens.AS_SAFE) {
|
||||
if (!CodegenUtil.isNullableType(rightType)) {
|
||||
|
||||
@@ -40,6 +40,11 @@ import static org.jetbrains.jet.codegen.AsmUtil.*;
|
||||
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.*;
|
||||
|
||||
public abstract class StackValue {
|
||||
|
||||
private static final String NULLABLE_BYTE_TYPE_NAME = "java/lang/Byte";
|
||||
private static final String NULLABLE_SHORT_TYPE_NAME = "java/lang/Short";
|
||||
private static final String NULLABLE_LONG_TYPE_NAME = "java/lang/Long";
|
||||
|
||||
@NotNull
|
||||
public final Type type;
|
||||
|
||||
@@ -154,8 +159,17 @@ public abstract class StackValue {
|
||||
}
|
||||
|
||||
private static void box(Type type, Type toType, InstructionAdapter v) {
|
||||
// TODO handle toType correctly
|
||||
if (type == Type.INT_TYPE || (isIntPrimitive(type) && toType.getInternalName().equals("java/lang/Integer"))) {
|
||||
if (type == Type.BYTE_TYPE || toType.getInternalName().equals(NULLABLE_BYTE_TYPE_NAME) && type == Type.INT_TYPE) {
|
||||
v.invokestatic(NULLABLE_BYTE_TYPE_NAME, "valueOf", "(B)L" + NULLABLE_BYTE_TYPE_NAME + ";");
|
||||
}
|
||||
else if (type == Type.SHORT_TYPE || toType.getInternalName().equals(NULLABLE_SHORT_TYPE_NAME) && type == Type.INT_TYPE) {
|
||||
v.invokestatic(NULLABLE_SHORT_TYPE_NAME, "valueOf", "(S)L" + NULLABLE_SHORT_TYPE_NAME + ";");
|
||||
}
|
||||
else if (toType.getInternalName().equals(NULLABLE_LONG_TYPE_NAME) && type == Type.INT_TYPE) {
|
||||
v.cast(type, Type.LONG_TYPE);
|
||||
v.invokestatic(NULLABLE_LONG_TYPE_NAME, "valueOf", "(J)L" + NULLABLE_LONG_TYPE_NAME +";");
|
||||
}
|
||||
else if (type == Type.INT_TYPE) {
|
||||
v.invokestatic("java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;");
|
||||
}
|
||||
else if (type == Type.BOOLEAN_TYPE) {
|
||||
@@ -164,15 +178,9 @@ public abstract class StackValue {
|
||||
else if (type == Type.CHAR_TYPE) {
|
||||
v.invokestatic("java/lang/Character", "valueOf", "(C)Ljava/lang/Character;");
|
||||
}
|
||||
else if (type == Type.SHORT_TYPE) {
|
||||
v.invokestatic("java/lang/Short", "valueOf", "(S)Ljava/lang/Short;");
|
||||
}
|
||||
else if (type == Type.LONG_TYPE) {
|
||||
v.invokestatic("java/lang/Long", "valueOf", "(J)Ljava/lang/Long;");
|
||||
}
|
||||
else if (type == Type.BYTE_TYPE) {
|
||||
v.invokestatic("java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;");
|
||||
}
|
||||
else if (type == Type.FLOAT_TYPE) {
|
||||
v.invokestatic("java/lang/Float", "valueOf", "(F)Ljava/lang/Float;");
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import java.util.List;
|
||||
|
||||
import static org.jetbrains.asm4.Opcodes.*;
|
||||
import static org.jetbrains.jet.codegen.AsmUtil.boxType;
|
||||
import static org.jetbrains.jet.codegen.AsmUtil.numberFunctionOperandType;
|
||||
import static org.jetbrains.jet.codegen.AsmUtil.unboxType;
|
||||
|
||||
public class BinaryOp implements IntrinsicMethod {
|
||||
@@ -48,26 +49,25 @@ public class BinaryOp implements IntrinsicMethod {
|
||||
StackValue receiver,
|
||||
@NotNull GenerationState state
|
||||
) {
|
||||
|
||||
boolean nullable = expectedType.getSort() == Type.OBJECT;
|
||||
if (nullable) {
|
||||
expectedType = unboxType(expectedType);
|
||||
}
|
||||
assert !nullable : "Return type of BinaryOp intrinsic should be of primitive type : " + expectedType;
|
||||
|
||||
Type operandType = numberFunctionOperandType(expectedType);
|
||||
|
||||
if (arguments.size() == 1) {
|
||||
// Intrinsic is called as an ordinary function
|
||||
if (receiver != null) {
|
||||
receiver.put(expectedType, v);
|
||||
receiver.put(operandType, v);
|
||||
}
|
||||
codegen.gen(arguments.get(0), shift() ? Type.INT_TYPE : expectedType);
|
||||
codegen.gen(arguments.get(0), shift() ? Type.INT_TYPE : operandType);
|
||||
}
|
||||
else {
|
||||
codegen.gen(arguments.get(0), expectedType);
|
||||
codegen.gen(arguments.get(1), shift() ? Type.INT_TYPE : expectedType);
|
||||
codegen.gen(arguments.get(0), operandType);
|
||||
codegen.gen(arguments.get(1), shift() ? Type.INT_TYPE : operandType);
|
||||
}
|
||||
v.visitInsn(expectedType.getOpcode(opcode));
|
||||
|
||||
if (nullable) {
|
||||
StackValue.onStack(expectedType).put(expectedType = boxType(expectedType), v);
|
||||
}
|
||||
return StackValue.onStack(expectedType);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,9 +50,8 @@ public class Increment implements IntrinsicMethod {
|
||||
@NotNull GenerationState state
|
||||
) {
|
||||
boolean nullable = expectedType.getSort() == Type.OBJECT;
|
||||
if (nullable) {
|
||||
expectedType = unboxType(expectedType);
|
||||
}
|
||||
assert !nullable : "Return type of Increment intrinsic should be of primitive type : " + expectedType;
|
||||
|
||||
if (arguments.size() > 0) {
|
||||
JetExpression operand = arguments.get(0);
|
||||
while (operand instanceof JetParenthesizedExpression) {
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.codegen.AsmUtil.numberFunctionOperandType;
|
||||
import static org.jetbrains.jet.codegen.AsmUtil.unboxType;
|
||||
|
||||
public class Inv implements IntrinsicMethod {
|
||||
@@ -41,10 +42,9 @@ public class Inv implements IntrinsicMethod {
|
||||
@NotNull GenerationState state
|
||||
) {
|
||||
boolean nullable = expectedType.getSort() == Type.OBJECT;
|
||||
if (nullable) {
|
||||
expectedType = unboxType(expectedType);
|
||||
}
|
||||
receiver.put(expectedType, v);
|
||||
assert !nullable : "Return type of Inv intrinsic should be of primitive type : " + expectedType;
|
||||
|
||||
receiver.put(numberFunctionOperandType(expectedType), v);
|
||||
if (expectedType == Type.LONG_TYPE) {
|
||||
v.lconst(-1L);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.codegen.AsmUtil.genNegate;
|
||||
import static org.jetbrains.jet.codegen.AsmUtil.numberFunctionOperandType;
|
||||
import static org.jetbrains.jet.codegen.AsmUtil.unboxType;
|
||||
|
||||
public class UnaryMinus implements IntrinsicMethod {
|
||||
@@ -42,16 +43,16 @@ public class UnaryMinus implements IntrinsicMethod {
|
||||
@NotNull GenerationState state
|
||||
) {
|
||||
boolean nullable = expectedType.getSort() == Type.OBJECT;
|
||||
if (nullable) {
|
||||
expectedType = unboxType(expectedType);
|
||||
}
|
||||
assert !nullable : "Return type of UnaryMinus intrinsic should be of primitive type : " + expectedType;
|
||||
|
||||
Type operandType = numberFunctionOperandType(expectedType);
|
||||
|
||||
if (arguments.size() == 1) {
|
||||
codegen.gen(arguments.get(0), expectedType);
|
||||
codegen.gen(arguments.get(0), operandType);
|
||||
}
|
||||
else {
|
||||
receiver.put(expectedType, v);
|
||||
receiver.put(operandType, v);
|
||||
}
|
||||
StackValue.coerce(genNegate(expectedType, v), expectedType, v);
|
||||
return StackValue.onStack(expectedType);
|
||||
return StackValue.onStack(genNegate(expectedType, v));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,9 +42,8 @@ public class UnaryPlus implements IntrinsicMethod {
|
||||
@NotNull GenerationState state
|
||||
) {
|
||||
boolean nullable = expectedType.getSort() == Type.OBJECT;
|
||||
if (nullable) {
|
||||
expectedType = unboxType(expectedType);
|
||||
}
|
||||
assert !nullable : "Return type of UnaryPlus intrinsic should be of primitive type : " + expectedType;
|
||||
|
||||
if (receiver != null && receiver != StackValue.none()) {
|
||||
receiver.put(expectedType, v);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user