generate comparisons and conditional jumps

This commit is contained in:
Dmitry Jemerov
2011-04-01 13:58:10 +02:00
parent 76dc0376e5
commit fb5175dbe8
4 changed files with 109 additions and 18 deletions
@@ -1,6 +1,7 @@
package org.jetbrains.jet.codegen;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.*;
@@ -72,7 +73,9 @@ public class ExpressionCodegen extends JetVisitor {
public void visitIfExpression(JetIfExpression expression) {
JetType expressionType = bindingContext.getExpressionType(expression);
Type asmType = typeMapper.mapType(expressionType);
gen(expression.getCondition(), Type.BOOLEAN_TYPE);
int oldStackDepth = myStack.size();
gen(expression.getCondition());
assert myStack.size() == oldStackDepth+1;
JetExpression thenExpression = expression.getThen();
JetExpression elseExpression = expression.getElse();
@@ -93,7 +96,7 @@ public class ExpressionCodegen extends JetVisitor {
Label elseLabel = new Label();
v.ifeq(elseLabel); // == 0, i.e. false
myStack.pop().condJump(elseLabel, true, v); // == 0, i.e. false
gen(thenExpression, asmType);
@@ -173,12 +176,7 @@ public class ExpressionCodegen extends JetVisitor {
private void generateSingleBranchIf(JetExpression expression, boolean inverse) {
Label endLabel = new Label();
if (inverse) {
v.ifeq(endLabel);
}
else {
v.ifne(endLabel);
}
myStack.pop().condJump(endLabel, inverse, v);
genToUnit(expression);
@@ -449,7 +447,8 @@ public class ExpressionCodegen extends JetVisitor {
@Override
public void visitBinaryExpression(JetBinaryExpression expression) {
if (expression.getOperationReference().getReferencedNameElementType() == JetTokens.EQ) {
final IElementType opToken = expression.getOperationReference().getReferencedNameElementType();
if (opToken == JetTokens.EQ) {
generateAssignmentExpression(expression);
return;
}
@@ -457,21 +456,44 @@ public class ExpressionCodegen extends JetVisitor {
if (op instanceof FunctionDescriptor) {
DeclarationDescriptor cls = op.getContainingDeclaration();
if (cls instanceof ClassDescriptor && cls.getName().equals("Int")) {
if (op.getName().equals("plus")) {
JetType returnType = ((FunctionDescriptor) op).getUnsubstitutedReturnType();
if (returnType.equals(stdlib.getIntType())) {
gen(expression.getLeft(), Type.INT_TYPE);
gen(expression.getRight(), Type.INT_TYPE);
v.add(Type.INT_TYPE);
myStack.push(StackValue.onStack(Type.INT_TYPE));
return;
}
if (op.getName().equals("compareTo")) {
generateCompareOp(expression, opToken);
}
else {
int opcode;
if (op.getName().equals("plus")) {
opcode = Opcodes.IADD;
}
else {
throw new UnsupportedOperationException("Don't know how to generate binary op method " + op.getName());
}
generateBinaryOp(expression, (FunctionDescriptor) op, opcode);
}
return;
}
}
throw new UnsupportedOperationException("Don't know how to generate binary op " + expression);
}
private void generateBinaryOp(JetBinaryExpression expression, FunctionDescriptor op, int opcode) {
JetType returnType = op.getUnsubstitutedReturnType();
if (returnType.equals(stdlib.getIntType())) {
gen(expression.getLeft(), Type.INT_TYPE);
gen(expression.getRight(), Type.INT_TYPE);
v.visitInsn(Type.INT_TYPE.getOpcode(opcode));
myStack.push(StackValue.onStack(Type.INT_TYPE));
}
else {
throw new UnsupportedOperationException("Don't know how to generate binary op with return type " + returnType);
}
}
private void generateCompareOp(JetBinaryExpression expression, IElementType opToken) {
gen(expression.getLeft(), Type.INT_TYPE);
gen(expression.getRight(), Type.INT_TYPE);
myStack.push(StackValue.icmp(opToken));
}
private void generateAssignmentExpression(JetBinaryExpression expression) {
if (expression.getLeft() instanceof JetReferenceExpression) {
final JetReferenceExpression lhs = (JetReferenceExpression) expression.getLeft();
@@ -1,6 +1,10 @@
package org.jetbrains.jet.codegen;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
@@ -22,6 +26,12 @@ public abstract class StackValue {
return new Constant(value);
}
public static StackValue icmp(IElementType opToken) {
return new IntCompare(opToken);
}
public abstract void condJump(Label label, boolean inverse, InstructionAdapter v);
public static class Local extends StackValue {
private final int index;
private final JetType type;
@@ -36,6 +46,17 @@ public abstract class StackValue {
v.load(index, type);
// TODO box/unbox
}
@Override
public void condJump(Label label, boolean inverse, InstructionAdapter v) {
put(Type.INT_TYPE, v);
if (inverse) {
v.ifeq(label);
}
else {
v.ifne(label);
}
}
}
public static class OnStack extends StackValue {
@@ -48,6 +69,11 @@ public abstract class StackValue {
@Override
public void put(Type type, InstructionAdapter v) {
}
@Override
public void condJump(Label label, boolean inverse, InstructionAdapter v) {
throw new UnsupportedOperationException("don't know how to generate this condjump");
}
}
public static class Constant extends StackValue {
@@ -72,5 +98,35 @@ public abstract class StackValue {
v.aconst(value);
}
}
@Override
public void condJump(Label label, boolean inverse, InstructionAdapter v) {
throw new UnsupportedOperationException("don't know how to generate this condjump");
}
}
private static class IntCompare extends StackValue {
private final IElementType opToken;
public IntCompare(IElementType opToken) {
this.opToken = opToken;
}
@Override
public void put(Type type, InstructionAdapter v) {
throw new UnsupportedOperationException("don't know how to put an IntCompare on stack");
}
@Override
public void condJump(Label label, boolean inverse, InstructionAdapter v) {
int opcode;
if (opToken == JetTokens.GT) {
opcode = inverse ? Opcodes.IF_ICMPLE : Opcodes.IF_ICMPGT;
}
else {
throw new UnsupportedOperationException("don't know how to generate this condjump");
}
v.visitJumpInsn(opcode, label);
}
}
}
+4
View File
@@ -0,0 +1,4 @@
fun foo(f: Int): Boolean {
if (f > 0) return true;
return false;
}
@@ -132,6 +132,15 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
assertEquals(2, main.invoke(null));
}
public void testGt() throws Exception {
loadFile("gt.jet");
System.out.println(generateToText());
final Method main = generateFunction();
assertEquals(true, main.invoke(null, 1));
assertEquals(false, main.invoke(null, 0));
}
private void loadFile(final String name) {
myFixture.configureByFile(JetParsingTest.getTestDataDir() + "/codegen/" + name);
}