提交 b74bdb9c 编写于 作者: D Dmitry Jemerov

refactored conditional jump generation to enable and/or generation

上级 6c1bda7f
...@@ -86,18 +86,20 @@ public class ExpressionCodegen extends JetVisitor { ...@@ -86,18 +86,20 @@ public class ExpressionCodegen extends JetVisitor {
} }
if (thenExpression == null) { if (thenExpression == null) {
generateSingleBranchIf(elseExpression, false); generateSingleBranchIf(elseExpression, true);
return; return;
} }
if (elseExpression == null) { if (elseExpression == null) {
generateSingleBranchIf(thenExpression, true); generateSingleBranchIf(thenExpression, false);
return; return;
} }
Label thenLabel = new Label();
Label elseLabel = new Label(); Label elseLabel = new Label();
myStack.pop().condJump(elseLabel, true, v); // == 0, i.e. false myStack.pop().condJump(thenLabel, elseLabel, v);
v.mark(thenLabel);
gen(thenExpression, asmType); gen(thenExpression, asmType);
...@@ -123,7 +125,9 @@ public class ExpressionCodegen extends JetVisitor { ...@@ -123,7 +125,9 @@ public class ExpressionCodegen extends JetVisitor {
myLoopEnds.push(end); myLoopEnds.push(end);
gen(expression.getCondition()); gen(expression.getCondition());
myStack.pop().condJump(end, true, v); Label thenLabel = new Label();
myStack.pop().condJump(thenLabel, end, v);
v.mark(thenLabel);
gen(expression.getBody(), Type.VOID_TYPE); gen(expression.getBody(), Type.VOID_TYPE);
v.goTo(condition); v.goTo(condition);
...@@ -145,7 +149,7 @@ public class ExpressionCodegen extends JetVisitor { ...@@ -145,7 +149,7 @@ public class ExpressionCodegen extends JetVisitor {
gen(expression.getBody(), Type.VOID_TYPE); gen(expression.getBody(), Type.VOID_TYPE);
gen(expression.getCondition()); gen(expression.getCondition());
myStack.pop().condJump(condition, false, v); myStack.pop().condJump(condition, end, v);
v.mark(end); v.mark(end);
...@@ -176,13 +180,15 @@ public class ExpressionCodegen extends JetVisitor { ...@@ -176,13 +180,15 @@ public class ExpressionCodegen extends JetVisitor {
} }
private void generateSingleBranchIf(JetExpression expression, boolean inverse) { private void generateSingleBranchIf(JetExpression expression, boolean inverse) {
Label endLabel = new Label(); Label ifTrue = new Label();
Label ifFalse = new Label();
myStack.pop().condJump(endLabel, inverse, v); myStack.pop().condJump(inverse ? ifFalse : ifTrue, inverse ? ifTrue : ifFalse, v);
v.mark(ifTrue);
gen(expression, Type.VOID_TYPE); gen(expression, Type.VOID_TYPE);
v.mark(endLabel); v.mark(ifFalse);
} }
@Override @Override
...@@ -497,42 +503,49 @@ public class ExpressionCodegen extends JetVisitor { ...@@ -497,42 +503,49 @@ public class ExpressionCodegen extends JetVisitor {
final IElementType opToken = expression.getOperationReference().getReferencedNameElementType(); final IElementType opToken = expression.getOperationReference().getReferencedNameElementType();
if (opToken == JetTokens.EQ) { if (opToken == JetTokens.EQ) {
generateAssignmentExpression(expression); generateAssignmentExpression(expression);
return;
} }
if (JetTokens.AUGMENTED_ASSIGNMENTS.contains(opToken)) { else if (JetTokens.AUGMENTED_ASSIGNMENTS.contains(opToken)) {
generateAugmentedAssignment(expression); generateAugmentedAssignment(expression);
return;
} }
DeclarationDescriptor op = bindingContext.resolveReferenceExpression(expression.getOperationReference()); else if (opToken == JetTokens.ANDAND) {
if (op instanceof FunctionDescriptor) { generateBooleanExpression(expression);
JetType returnType = bindingContext.getExpressionType(expression); }
final Type asmType = typeMapper.mapType(returnType); else {
DeclarationDescriptor cls = op.getContainingDeclaration(); DeclarationDescriptor op = bindingContext.resolveReferenceExpression(expression.getOperationReference());
if (isNumberPrimitive(cls)) { if (op instanceof FunctionDescriptor) {
if (op.getName().equals("compareTo")) { JetType returnType = bindingContext.getExpressionType(expression);
generateCompareOp(expression, opToken, asmType); final Type asmType = typeMapper.mapType(returnType);
} DeclarationDescriptor cls = op.getContainingDeclaration();
else { if (isNumberPrimitive(cls)) {
int opcode = opcodeForMethod(op.getName()); if (op.getName().equals("compareTo")) {
generateBinaryOp(expression, (FunctionDescriptor) op, opcode); generateCompareOp(expression, opToken, asmType);
}
return;
}
else if (isClass(cls, "Hashable")) {
if (op.getName().equals("equals")) {
final Type leftType = typeMapper.mapType(bindingContext.getExpressionType(expression.getLeft()));
final Type rightType = typeMapper.mapType(bindingContext.getExpressionType(expression.getRight()));
if (isNumberPrimitive(leftType) && leftType == rightType) {
generateCompareOp(expression, opToken, leftType);
return;
} }
else { else {
throw new UnsupportedOperationException("Don't know how to generate equality for these types"); int opcode = opcodeForMethod(op.getName());
generateBinaryOp(expression, (FunctionDescriptor) op, opcode);
}
return;
}
else if (isClass(cls, "Hashable")) {
if (op.getName().equals("equals")) {
final Type leftType = typeMapper.mapType(bindingContext.getExpressionType(expression.getLeft()));
final Type rightType = typeMapper.mapType(bindingContext.getExpressionType(expression.getRight()));
if (isNumberPrimitive(leftType) && leftType == rightType) {
generateCompareOp(expression, opToken, leftType);
return;
}
else {
throw new UnsupportedOperationException("Don't know how to generate equality for these types");
}
} }
} }
} }
throw new UnsupportedOperationException("Don't know how to generate binary op " + expression);
} }
throw new UnsupportedOperationException("Don't know how to generate binary op " + expression); }
private void generateBooleanExpression(JetBinaryExpression expression) {
throw new UnsupportedOperationException();
} }
private static boolean isNumberPrimitive(DeclarationDescriptor descriptor) { private static boolean isNumberPrimitive(DeclarationDescriptor descriptor) {
...@@ -594,7 +607,7 @@ public class ExpressionCodegen extends JetVisitor { ...@@ -594,7 +607,7 @@ public class ExpressionCodegen extends JetVisitor {
private void generateCompareOp(JetBinaryExpression expression, IElementType opToken, Type type) { private void generateCompareOp(JetBinaryExpression expression, IElementType opToken, Type type) {
gen(expression.getLeft(), type); gen(expression.getLeft(), type);
gen(expression.getRight(), type); gen(expression.getRight(), type);
myStack.push(StackValue.cmp(opToken)); myStack.push(StackValue.cmp(opToken, type));
} }
private void generateAssignmentExpression(JetBinaryExpression expression) { private void generateAssignmentExpression(JetBinaryExpression expression) {
......
...@@ -32,15 +32,15 @@ public abstract class StackValue { ...@@ -32,15 +32,15 @@ public abstract class StackValue {
return new Constant(value, type); return new Constant(value, type);
} }
public static StackValue cmp(IElementType opToken) { public static StackValue cmp(IElementType opToken, Type operandType) {
return new NumberCompare(opToken); return new NumberCompare(opToken, operandType);
} }
public static StackValue not(StackValue stackValue) { public static StackValue not(StackValue stackValue) {
return new Invert(stackValue); return new Invert(stackValue);
} }
public abstract void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v); public abstract void condJump(Label jumpIfTrue, Label jumpIfFalse, InstructionAdapter v);
private static void box(final Type type, InstructionAdapter v) { private static void box(final Type type, InstructionAdapter v) {
if (type == Type.INT_TYPE) { if (type == Type.INT_TYPE) {
...@@ -80,8 +80,10 @@ public abstract class StackValue { ...@@ -80,8 +80,10 @@ public abstract class StackValue {
protected void putAsBoolean(InstructionAdapter v) { protected void putAsBoolean(InstructionAdapter v) {
Label ifTrue = new Label(); Label ifTrue = new Label();
Label ifFalse = new Label();
Label end = new Label(); Label end = new Label();
condJump(ifTrue, false, v); condJump(ifTrue, ifFalse, v);
v.mark(ifFalse);
v.iconst(0); v.iconst(0);
v.goTo(end); v.goTo(end);
v.mark(ifTrue); v.mark(ifTrue);
...@@ -105,14 +107,11 @@ public abstract class StackValue { ...@@ -105,14 +107,11 @@ public abstract class StackValue {
} }
@Override @Override
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) { public void condJump(Label ifTrue, Label ifFalse, InstructionAdapter v) {
put(Type.INT_TYPE, v); put(Type.INT_TYPE, v);
if (jumpIfFalse) { // TODO optimize extra jump away
v.ifeq(label); v.ifne(ifTrue);
} v.goTo(ifFalse);
else {
v.ifne(label);
}
} }
} }
...@@ -127,14 +126,11 @@ public abstract class StackValue { ...@@ -127,14 +126,11 @@ public abstract class StackValue {
} }
@Override @Override
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) { public void condJump(Label ifTrue, Label ifFalse, InstructionAdapter v) {
if (this.type == Type.BOOLEAN_TYPE) { if (this.type == Type.BOOLEAN_TYPE) {
if (jumpIfFalse) { // TODO optimize extra jump away
v.ifeq(label); v.ifne(ifTrue);
} v.goTo(ifFalse);
else {
v.ifne(label);
}
} }
else { else {
throw new UnsupportedOperationException("can't generate a cond jump for a non-boolean value on stack"); throw new UnsupportedOperationException("can't generate a cond jump for a non-boolean value on stack");
...@@ -157,12 +153,10 @@ public abstract class StackValue { ...@@ -157,12 +153,10 @@ public abstract class StackValue {
} }
@Override @Override
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) { public void condJump(Label ifTrue, Label ifFalse, InstructionAdapter v) {
if (value instanceof Boolean) { if (value instanceof Boolean) {
boolean boolValue = ((Boolean) value).booleanValue(); boolean boolValue = ((Boolean) value).booleanValue();
if (boolValue ^ jumpIfFalse) { v.goTo(boolValue ? ifTrue : ifFalse);
v.goTo(label);
}
} }
else { else {
throw new UnsupportedOperationException("don't know how to generate this condjump"); throw new UnsupportedOperationException("don't know how to generate this condjump");
...@@ -172,10 +166,12 @@ public abstract class StackValue { ...@@ -172,10 +166,12 @@ public abstract class StackValue {
private static class NumberCompare extends StackValue { private static class NumberCompare extends StackValue {
private final IElementType opToken; private final IElementType opToken;
private final Type operandType;
public NumberCompare(IElementType opToken) { public NumberCompare(IElementType opToken, Type operandType) {
super(Type.BOOLEAN_TYPE); super(Type.BOOLEAN_TYPE);
this.opToken = opToken; this.opToken = opToken;
this.operandType = operandType;
} }
@Override @Override
...@@ -187,44 +183,33 @@ public abstract class StackValue { ...@@ -187,44 +183,33 @@ public abstract class StackValue {
} }
@Override @Override
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) { public void condJump(Label ifTrue, Label ifFalse, InstructionAdapter v) {
int opcode; int opcode;
if (opToken == JetTokens.EQEQ) { if (opToken == JetTokens.EQEQ) opcode = Opcodes.IFEQ;
opcode = jumpIfFalse ? Opcodes.IFNE : Opcodes.IFEQ; else if (opToken == JetTokens.EXCLEQ) opcode = Opcodes.IFNE;
} else if (opToken == JetTokens.GT) opcode = Opcodes.IFGT;
else if (opToken == JetTokens.EXCLEQ) { else if (opToken == JetTokens.GTEQ) opcode = Opcodes.IFGE;
opcode = jumpIfFalse ? Opcodes.IFEQ : Opcodes.IFNE; else if (opToken == JetTokens.LT) opcode = Opcodes.IFLT;
} else if (opToken == JetTokens.LTEQ) opcode = Opcodes.IFLE;
else if (opToken == JetTokens.GT) {
opcode = jumpIfFalse ? Opcodes.IFLE : Opcodes.IFGT;
}
else if (opToken == JetTokens.GTEQ) {
opcode = jumpIfFalse ? Opcodes.IFLT : Opcodes.IFGE;
}
else if (opToken == JetTokens.LT) {
opcode = jumpIfFalse ? Opcodes.IFGE : Opcodes.IFLT;
}
else if (opToken == JetTokens.LTEQ) {
opcode = jumpIfFalse ? Opcodes.IFGT : Opcodes.IFLE;
}
else { else {
throw new UnsupportedOperationException("don't know how to generate this condjump"); throw new UnsupportedOperationException("don't know how to generate this condjump");
} }
if (type == Type.FLOAT_TYPE || type == Type.DOUBLE_TYPE) { if (operandType == Type.FLOAT_TYPE || operandType == Type.DOUBLE_TYPE) {
if (opToken == JetTokens.GT || opToken == JetTokens.GTEQ) { if (opToken == JetTokens.GT || opToken == JetTokens.GTEQ) {
v.cmpg(type); v.cmpg(operandType);
} }
else { else {
v.cmpl(type); v.cmpl(operandType);
} }
} }
else if (type == Type.LONG_TYPE) { else if (operandType == Type.LONG_TYPE) {
v.lcmp(); v.lcmp();
} }
else { else {
opcode += (Opcodes.IF_ICMPEQ - Opcodes.IFEQ); opcode += (Opcodes.IF_ICMPEQ - Opcodes.IFEQ);
} }
v.visitJumpInsn(opcode, label); v.visitJumpInsn(opcode, ifTrue);
v.goTo(ifFalse);
} }
} }
...@@ -245,8 +230,8 @@ public abstract class StackValue { ...@@ -245,8 +230,8 @@ public abstract class StackValue {
} }
@Override @Override
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) { public void condJump(Label ifTrue, Label ifFalse, InstructionAdapter v) {
myOperand.condJump(label, !jumpIfFalse, v); myOperand.condJump(ifFalse, ifTrue, v);
} }
} }
} }
fun foo(b: Boolean): Int { return if (b) 15 else 20 }
\ No newline at end of file
fun foo(b: Boolean) : Int {
if (b) return 15;
return 20;
}
...@@ -109,7 +109,7 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase { ...@@ -109,7 +109,7 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
} }
public void testIf() throws Exception { public void testIf() throws Exception {
loadFile("if.jet"); loadText("fun foo(b: Boolean): Int { return if (b) 15 else 20 }");
System.out.println(generateToText()); System.out.println(generateToText());
final Method main = generateFunction(); final Method main = generateFunction();
...@@ -118,7 +118,7 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase { ...@@ -118,7 +118,7 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
} }
public void testSingleBranchIf() throws Exception { public void testSingleBranchIf() throws Exception {
loadFile("singleBranchIf.jet"); loadText("fun foo(b: Boolean) : Int { if (b) return 15;\n return 20; }");
System.out.println(generateToText()); System.out.println(generateToText());
final Method main = generateFunction(); final Method main = generateFunction();
...@@ -451,6 +451,21 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase { ...@@ -451,6 +451,21 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
assertEquals(0, main.invoke(null, 4)); assertEquals(0, main.invoke(null, 4));
} }
public void _testAnd() throws Exception {
loadText("fun foo(a : Int): Boolean = a > 0 && a/0 > 0");
final Method main = generateFunction();
assertEquals(false, main.invoke(null, 0));
boolean hadException = false;
try {
main.invoke(null, 5);
} catch (InvocationTargetException e) {
if (e.getTargetException() instanceof ArithmeticException) {
hadException = true;
}
}
assertTrue(hadException);
}
private void binOpTest(final String text, final Object arg1, final Object arg2, final Object expected) throws Exception { private void binOpTest(final String text, final Object arg1, final Object arg2, final Object expected) throws Exception {
loadText(text); loadText(text);
System.out.println(generateToText()); System.out.println(generateToText());
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册