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

refactored conditional jump generation to enable and/or generation

上级 6c1bda7f
......@@ -86,18 +86,20 @@ public class ExpressionCodegen extends JetVisitor {
}
if (thenExpression == null) {
generateSingleBranchIf(elseExpression, false);
generateSingleBranchIf(elseExpression, true);
return;
}
if (elseExpression == null) {
generateSingleBranchIf(thenExpression, true);
generateSingleBranchIf(thenExpression, false);
return;
}
Label thenLabel = 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);
......@@ -123,7 +125,9 @@ public class ExpressionCodegen extends JetVisitor {
myLoopEnds.push(end);
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);
v.goTo(condition);
......@@ -145,7 +149,7 @@ public class ExpressionCodegen extends JetVisitor {
gen(expression.getBody(), Type.VOID_TYPE);
gen(expression.getCondition());
myStack.pop().condJump(condition, false, v);
myStack.pop().condJump(condition, end, v);
v.mark(end);
......@@ -176,13 +180,15 @@ public class ExpressionCodegen extends JetVisitor {
}
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);
v.mark(endLabel);
v.mark(ifFalse);
}
@Override
......@@ -497,12 +503,14 @@ public class ExpressionCodegen extends JetVisitor {
final IElementType opToken = expression.getOperationReference().getReferencedNameElementType();
if (opToken == JetTokens.EQ) {
generateAssignmentExpression(expression);
return;
}
if (JetTokens.AUGMENTED_ASSIGNMENTS.contains(opToken)) {
else if (JetTokens.AUGMENTED_ASSIGNMENTS.contains(opToken)) {
generateAugmentedAssignment(expression);
return;
}
else if (opToken == JetTokens.ANDAND) {
generateBooleanExpression(expression);
}
else {
DeclarationDescriptor op = bindingContext.resolveReferenceExpression(expression.getOperationReference());
if (op instanceof FunctionDescriptor) {
JetType returnType = bindingContext.getExpressionType(expression);
......@@ -534,6 +542,11 @@ public class ExpressionCodegen extends JetVisitor {
}
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) {
if (!(descriptor instanceof ClassDescriptor)) {
......@@ -594,7 +607,7 @@ public class ExpressionCodegen extends JetVisitor {
private void generateCompareOp(JetBinaryExpression expression, IElementType opToken, Type type) {
gen(expression.getLeft(), type);
gen(expression.getRight(), type);
myStack.push(StackValue.cmp(opToken));
myStack.push(StackValue.cmp(opToken, type));
}
private void generateAssignmentExpression(JetBinaryExpression expression) {
......
......@@ -32,15 +32,15 @@ public abstract class StackValue {
return new Constant(value, type);
}
public static StackValue cmp(IElementType opToken) {
return new NumberCompare(opToken);
public static StackValue cmp(IElementType opToken, Type operandType) {
return new NumberCompare(opToken, operandType);
}
public static StackValue not(StackValue 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) {
if (type == Type.INT_TYPE) {
......@@ -80,8 +80,10 @@ public abstract class StackValue {
protected void putAsBoolean(InstructionAdapter v) {
Label ifTrue = new Label();
Label ifFalse = new Label();
Label end = new Label();
condJump(ifTrue, false, v);
condJump(ifTrue, ifFalse, v);
v.mark(ifFalse);
v.iconst(0);
v.goTo(end);
v.mark(ifTrue);
......@@ -105,14 +107,11 @@ public abstract class StackValue {
}
@Override
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
public void condJump(Label ifTrue, Label ifFalse, InstructionAdapter v) {
put(Type.INT_TYPE, v);
if (jumpIfFalse) {
v.ifeq(label);
}
else {
v.ifne(label);
}
// TODO optimize extra jump away
v.ifne(ifTrue);
v.goTo(ifFalse);
}
}
......@@ -127,14 +126,11 @@ public abstract class StackValue {
}
@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 (jumpIfFalse) {
v.ifeq(label);
}
else {
v.ifne(label);
}
// TODO optimize extra jump away
v.ifne(ifTrue);
v.goTo(ifFalse);
}
else {
throw new UnsupportedOperationException("can't generate a cond jump for a non-boolean value on stack");
......@@ -157,12 +153,10 @@ public abstract class StackValue {
}
@Override
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
public void condJump(Label ifTrue, Label ifFalse, InstructionAdapter v) {
if (value instanceof Boolean) {
boolean boolValue = ((Boolean) value).booleanValue();
if (boolValue ^ jumpIfFalse) {
v.goTo(label);
}
v.goTo(boolValue ? ifTrue : ifFalse);
}
else {
throw new UnsupportedOperationException("don't know how to generate this condjump");
......@@ -172,10 +166,12 @@ public abstract class StackValue {
private static class NumberCompare extends StackValue {
private final IElementType opToken;
private final Type operandType;
public NumberCompare(IElementType opToken) {
public NumberCompare(IElementType opToken, Type operandType) {
super(Type.BOOLEAN_TYPE);
this.opToken = opToken;
this.operandType = operandType;
}
@Override
......@@ -187,44 +183,33 @@ public abstract class StackValue {
}
@Override
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
public void condJump(Label ifTrue, Label ifFalse, InstructionAdapter v) {
int opcode;
if (opToken == JetTokens.EQEQ) {
opcode = jumpIfFalse ? Opcodes.IFNE : Opcodes.IFEQ;
}
else if (opToken == JetTokens.EXCLEQ) {
opcode = jumpIfFalse ? Opcodes.IFEQ : Opcodes.IFNE;
}
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;
}
if (opToken == JetTokens.EQEQ) opcode = Opcodes.IFEQ;
else if (opToken == JetTokens.EXCLEQ) opcode = Opcodes.IFNE;
else if (opToken == JetTokens.GT) opcode = Opcodes.IFGT;
else if (opToken == JetTokens.GTEQ) opcode = Opcodes.IFGE;
else if (opToken == JetTokens.LT) opcode = Opcodes.IFLT;
else if (opToken == JetTokens.LTEQ) opcode = Opcodes.IFLE;
else {
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) {
v.cmpg(type);
v.cmpg(operandType);
}
else {
v.cmpl(type);
v.cmpl(operandType);
}
}
else if (type == Type.LONG_TYPE) {
else if (operandType == Type.LONG_TYPE) {
v.lcmp();
}
else {
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 {
}
@Override
public void condJump(Label label, boolean jumpIfFalse, InstructionAdapter v) {
myOperand.condJump(label, !jumpIfFalse, v);
public void condJump(Label ifTrue, Label ifFalse, InstructionAdapter 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 {
}
public void testIf() throws Exception {
loadFile("if.jet");
loadText("fun foo(b: Boolean): Int { return if (b) 15 else 20 }");
System.out.println(generateToText());
final Method main = generateFunction();
......@@ -118,7 +118,7 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
}
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());
final Method main = generateFunction();
......@@ -451,6 +451,21 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
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 {
loadText(text);
System.out.println(generateToText());
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册