Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -460,13 +460,10 @@ private boolean codeBoolean(AST.BinaryExpr binaryExpr) {
jumpTo(l3);
startBlock(l2);
// Below we must write to the same temp
//code(new Instruction.Move(new Operand.ConstantOperand(isAnd ? 0 : 1, typeDictionary.INT), new Operand.TempRegisterOperand(temp.reg)));
code(new Instruction.Move(new Operand.ConstantOperand(isAnd ? 0 : 1, typeDictionary.INT), temp));
jumpTo(l3);
startBlock(l3);
// leave temp on virtual stack
// var temp2 = (Operand.TempRegisterOperand) pop();
// pushOperand(new Operand.TempRegisterOperand(temp2.reg));
return false;
}

Expand All @@ -483,10 +480,19 @@ private boolean compileBinaryExpr(AST.BinaryExpr binaryExpr) {
indexed = compileExpr(binaryExpr.expr2);
if (indexed)
codeIndexedLoad();
opCode = binaryExpr.op.str;
Operand right = pop();
Operand left = pop();
if (left instanceof Operand.ConstantOperand leftconstant &&
if (left instanceof Operand.NullConstantOperand &&
right instanceof Operand.NullConstantOperand) {
long value = 0;
switch (opCode) {
case "==": value = 1; break;
case "!=": value = 0; break;
default: throw new CompilerException("Invalid binary op");
}
pushConstant(value, typeDictionary.INT);
}
else if (left instanceof Operand.ConstantOperand leftconstant &&
right instanceof Operand.ConstantOperand rightconstant) {
long value = 0;
switch (opCode) {
Expand Down Expand Up @@ -535,14 +541,22 @@ private boolean compileUnaryExpr(AST.UnaryExpr unaryExpr) {
}

private boolean compileConstantExpr(AST.LiteralExpr constantExpr) {
pushConstant(constantExpr.value.num.intValue(), constantExpr.type);
if (constantExpr.type instanceof Type.TypeInteger)
pushConstant(constantExpr.value.num.intValue(), constantExpr.type);
else if (constantExpr.type instanceof Type.TypeNull)
pushNullConstant(constantExpr.type);
else throw new CompilerException("Invalid constant type");
return false;
}

private void pushConstant(long value, Type type) {
pushOperand(new Operand.ConstantOperand(value, type));
}

private void pushNullConstant(Type type) {
pushOperand(new Operand.NullConstantOperand(type));
}

private Operand.TempRegisterOperand createTemp(Type type) {
var tempRegister = new Operand.TempRegisterOperand(registerPool.newTempReg(type));
pushOperand(tempRegister);
Expand All @@ -552,8 +566,8 @@ private Operand.TempRegisterOperand createTemp(Type type) {
Type typeOfOperand(Operand operand) {
if (operand instanceof Operand.ConstantOperand constant)
return constant.type;
// else if (operand instanceof Operand.NullConstantOperand nullConstantOperand)
// return nullConstantOperand.type;
else if (operand instanceof Operand.NullConstantOperand nullConstantOperand)
return nullConstantOperand.type;
else if (operand instanceof Operand.RegisterOperand registerOperand)
return registerOperand.type;
else throw new CompilerException("Invalid operand");
Expand All @@ -569,7 +583,7 @@ private Operand.TempRegisterOperand createTempAndMove(Operand src) {
private Operand.RegisterOperand ensureTemp() {
Operand top = top();
if (top instanceof Operand.ConstantOperand
//|| top instanceof Operand.NullConstantOperand
|| top instanceof Operand.NullConstantOperand
|| top instanceof Operand.LocalRegisterOperand) {
return createTempAndMove(pop());
} else if (top instanceof Operand.IndexedOperand) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public void rename(Integer source, Integer target) {
var toSet = edges.get(target);
if (toSet == null) {
//throw new RuntimeException("Cannot find edge " + target + " from " + source);
return; // FIXME this is workaround to handle sceanrio where target is arg register but we need a better way
return; // FIXME this is workaround to handle scenario where target is arg register but we need a better way
}
toSet.addAll(fromSet);
// If any node interfered with from
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ public String toString() {
}
}

public static class NullConstantOperand extends Operand {
public NullConstantOperand(Type type) {
this.type = type;
}
@Override
public String toString() {
return "null";
}
}

public static class RegisterOperand extends Operand {
final Register reg;
protected RegisterOperand(Register reg) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -377,35 +377,40 @@ private boolean evalInstruction(Instruction instruction) {
}
case Instruction.Binary binaryInst -> {
var cell = valueLattice.get(binaryInst.result().reg);
LatticeElement left, right;
LatticeElement left = null;
LatticeElement right = null;
// TODO we cannot yet evaluate null in comparisons
if (binaryInst.left() instanceof Operand.ConstantOperand constant)
left = new LatticeElement(V_CONSTANT, constant.value);
else if (binaryInst.left() instanceof Operand.RegisterOperand registerOperand)
left = valueLattice.get(registerOperand.reg);
else throw new IllegalStateException();
if (binaryInst.right() instanceof Operand.ConstantOperand constant)
right = new LatticeElement(V_CONSTANT, constant.value);
else if (binaryInst.right() instanceof Operand.RegisterOperand registerOperand)
right = valueLattice.get(registerOperand.reg);
else throw new IllegalStateException();
switch (binaryInst.binOp) {
case "+":
case "-":
case "*":
case "/":
case "%":
changed = evalArith(cell, left, right, binaryInst.binOp);
break;
case "==":
case "!=":
case "<":
case ">":
case "<=":
case ">=":
changed = evalLogical(cell, left, right, binaryInst.binOp);
break;
default:
throw new IllegalStateException();
if (left != null && right != null) {
switch (binaryInst.binOp) {
case "+":
case "-":
case "*":
case "/":
case "%":
changed = evalArith(cell, left, right, binaryInst.binOp);
break;
case "==":
case "!=":
case "<":
case ">":
case "<=":
case ">=":
changed = evalLogical(cell, left, right, binaryInst.binOp);
break;
default:
throw new IllegalStateException();
}
}
else {
cell.setKind(V_VARYING);
}
}
case Instruction.NewArray newArrayInst -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ public Value interpret(ExecutionStack execStack, Frame frame) {
if (retInst.value() instanceof Operand.ConstantOperand constantOperand) {
execStack.stack[base] = new Value.IntegerValue(constantOperand.value);
}
else if (retInst.value() instanceof Operand.NullConstantOperand) {
execStack.stack[base] = new Value.NullValue();
}
else if (retInst.value() instanceof Operand.RegisterOperand registerOperand) {
execStack.stack[base] = execStack.stack[base+registerOperand.frameSlot()];
}
Expand All @@ -63,6 +66,9 @@ else if (retInst.value() instanceof Operand.RegisterOperand registerOperand) {
else if (moveInst.from() instanceof Operand.ConstantOperand constantOperand) {
execStack.stack[base + toReg.frameSlot()] = new Value.IntegerValue(constantOperand.value);
}
else if (moveInst.from() instanceof Operand.NullConstantOperand) {
execStack.stack[base + toReg.frameSlot()] = new Value.NullValue();
}
else throw new IllegalStateException();
}
else throw new IllegalStateException();
Expand Down Expand Up @@ -107,6 +113,9 @@ else if (cbrInst.condition() instanceof Operand.ConstantOperand constantOperand)
else if (arg instanceof Operand.ConstantOperand constantOperand) {
execStack.stack[base + reg] = new Value.IntegerValue(constantOperand.value);
}
else if (arg instanceof Operand.NullConstantOperand) {
execStack.stack[base + reg] = new Value.NullValue();
}
reg += 1;
}
// Call function
Expand Down Expand Up @@ -135,31 +144,60 @@ else if (arg instanceof Operand.ConstantOperand constantOperand) {
case Instruction.Binary binaryInst -> {
long x, y;
long value = 0;
if (binaryInst.left() instanceof Operand.ConstantOperand constant)
x = constant.value;
else if (binaryInst.left() instanceof Operand.RegisterOperand registerOperand)
x = ((Value.IntegerValue) execStack.stack[base + registerOperand.frameSlot()]).value;
else throw new IllegalStateException();
if (binaryInst.right() instanceof Operand.ConstantOperand constant)
y = constant.value;
else if (binaryInst.right() instanceof Operand.RegisterOperand registerOperand)
y = ((Value.IntegerValue) execStack.stack[base + registerOperand.frameSlot()]).value;
else throw new IllegalStateException();
switch (binaryInst.binOp) {
case "+": value = x + y; break;
case "-": value = x - y; break;
case "*": value = x * y; break;
case "/": value = x / y; break;
case "%": value = x % y; break;
case "==": value = x == y ? 1 : 0; break;
case "!=": value = x != y ? 1 : 0; break;
case "<": value = x < y ? 1: 0; break;
case ">": value = x > y ? 1 : 0; break;
case "<=": value = x <= y ? 1 : 0; break;
case ">=": value = x <= y ? 1 : 0; break;
default: throw new IllegalStateException();
boolean intOp = true;
if (binaryInst.binOp.equals("==") || binaryInst.binOp.equals("!=")) {
Operand.RegisterOperand nonNullLitOperand = null;
if (binaryInst.left() instanceof Operand.NullConstantOperand) {
nonNullLitOperand = (Operand.RegisterOperand)binaryInst.right();
}
else if (binaryInst.right() instanceof Operand.NullConstantOperand) {
nonNullLitOperand = (Operand.RegisterOperand)binaryInst.left();
}
if (nonNullLitOperand != null) {
intOp = false;
Value otherValue = execStack.stack[base + nonNullLitOperand.frameSlot()];
switch (binaryInst.binOp) {
case "==": {
value = otherValue instanceof Value.NullValue ? 1 : 0;
break;
}
case "!=": {
value = otherValue instanceof Value.NullValue ? 0 : 1;
break;
}
default:
throw new IllegalStateException();
}
execStack.stack[base + binaryInst.result().frameSlot()] = new Value.IntegerValue(value);
}
}
if (intOp) {
if (binaryInst.left() instanceof Operand.ConstantOperand constant)
x = constant.value;
else if (binaryInst.left() instanceof Operand.RegisterOperand registerOperand)
x = ((Value.IntegerValue) execStack.stack[base + registerOperand.frameSlot()]).value;
else throw new IllegalStateException();
if (binaryInst.right() instanceof Operand.ConstantOperand constant)
y = constant.value;
else if (binaryInst.right() instanceof Operand.RegisterOperand registerOperand)
y = ((Value.IntegerValue) execStack.stack[base + registerOperand.frameSlot()]).value;
else throw new IllegalStateException();
switch (binaryInst.binOp) {
case "+": value = x + y; break;
case "-": value = x - y; break;
case "*": value = x * y; break;
case "/": value = x / y; break;
case "%": value = x % y; break;
case "==": value = x == y ? 1 : 0; break;
case "!=": value = x != y ? 1 : 0; break;
case "<": value = x < y ? 1: 0; break;
case ">": value = x > y ? 1 : 0; break;
case "<=": value = x <= y ? 1 : 0; break;
case ">=": value = x <= y ? 1 : 0; break;
default: throw new IllegalStateException();
}
execStack.stack[base + binaryInst.result().frameSlot()] = new Value.IntegerValue(value);
}
execStack.stack[base + binaryInst.result().frameSlot()] = new Value.IntegerValue(value);
}
case Instruction.NewArray newArrayInst -> {
execStack.stack[base + newArrayInst.destOperand().frameSlot()] = new Value.ArrayValue(newArrayInst.type);
Expand All @@ -172,6 +210,9 @@ else if (binaryInst.right() instanceof Operand.RegisterOperand registerOperand)
if (arrayAppendInst.value() instanceof Operand.ConstantOperand constant) {
arrayValue.values.add(new Value.IntegerValue(constant.value));
}
else if (arrayAppendInst.value() instanceof Operand.NullConstantOperand) {
arrayValue.values.add(new Value.NullValue());
}
else if (arrayAppendInst.value() instanceof Operand.RegisterOperand registerOperand) {
arrayValue.values.add(execStack.stack[base + registerOperand.frameSlot()]);
}
Expand All @@ -193,6 +234,9 @@ else if (arrayStoreInst.indexOperand() instanceof Operand.RegisterOperand regist
if (arrayStoreInst.sourceOperand() instanceof Operand.ConstantOperand constantOperand) {
value = new Value.IntegerValue(constantOperand.value);
}
else if (arrayStoreInst.sourceOperand() instanceof Operand.NullConstantOperand) {
value = new Value.NullValue();
}
else if (arrayStoreInst.sourceOperand() instanceof Operand.RegisterOperand registerOperand) {
value = execStack.stack[base + registerOperand.frameSlot()];
}
Expand Down Expand Up @@ -221,6 +265,9 @@ else if (arrayLoadInst.indexOperand() instanceof Operand.RegisterOperand registe
if (setFieldInst.sourceOperand() instanceof Operand.ConstantOperand constant) {
value = new Value.IntegerValue(constant.value);
}
else if (setFieldInst.sourceOperand() instanceof Operand.NullConstantOperand) {
value = new Value.NullValue();
}
else if (setFieldInst.sourceOperand() instanceof Operand.RegisterOperand registerOperand) {
value = execStack.stack[base + registerOperand.frameSlot()];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ public IntegerValue(long value) {
}
public final long value;
}
static public class NullValue extends Value {
public NullValue() {}
}
static public class ArrayValue extends Value {
public final Type.TypeArray arrayType;
public final ArrayList<Value> values;
Expand Down
Loading