|
|
|
@ -53,6 +53,9 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
|
/** Index out of bounds. */
|
|
|
|
|
private final Label errorOob = new Label("error.OOB");
|
|
|
|
|
|
|
|
|
|
/** Not implemented. */
|
|
|
|
|
private final Label errorNI = new Label("error.NI");
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Emits the top level of the program.
|
|
|
|
|
*
|
|
|
|
@ -313,45 +316,79 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
|
@Override
|
|
|
|
|
public Register analyze(BinaryExpr node)
|
|
|
|
|
{
|
|
|
|
|
node.left.dispatch(this);
|
|
|
|
|
backend.emitSW(Register.A0, Register.FP, -sp_off*wordSize, "Push on stack slot "+sp_off);
|
|
|
|
|
sp_off++;
|
|
|
|
|
node.right.dispatch(this);
|
|
|
|
|
sp_off--;
|
|
|
|
|
backend.emitLW(Register.T0, Register.FP, -sp_off*wordSize, "Pop stack slot "+sp_off);
|
|
|
|
|
// Arithmetic Operators
|
|
|
|
|
if(node.operator.equals("+"))
|
|
|
|
|
backend.emitADD(Register.A0, Register.A0, Register.T0, "Add operation");
|
|
|
|
|
else if(node.operator.equals("-"))
|
|
|
|
|
backend.emitSUB(Register.A0, Register.A0, Register.T0, "Sub operation");
|
|
|
|
|
else if(node.operator.equals("*"))
|
|
|
|
|
backend.emitMUL(Register.A0, Register.A0, Register.T0, "Mul operation");
|
|
|
|
|
else if(node.operator.equals("/"))
|
|
|
|
|
backend.emitDIV(Register.A0, Register.A0, Register.T0, "Div operation");
|
|
|
|
|
else
|
|
|
|
|
{ // Comparison operators
|
|
|
|
|
elseBlock = generateLocalLabel();
|
|
|
|
|
String comment="Branch on not "+node.operator;
|
|
|
|
|
if(node.operator.equals("=="))
|
|
|
|
|
backend.emitBNE(Register.A0, Register.T0,elseBlock, comment);
|
|
|
|
|
else if(node.operator.equals("!="))
|
|
|
|
|
backend.emitBEQ(Register.A0, Register.T0,elseBlock, comment);
|
|
|
|
|
else if(node.operator.equals("<"))
|
|
|
|
|
backend.emitBGE(Register.A0, Register.T0,elseBlock, comment);
|
|
|
|
|
else if(node.operator.equals(">"))
|
|
|
|
|
{
|
|
|
|
|
backend.emitBLT(Register.A0, Register.T0,elseBlock, comment);
|
|
|
|
|
backend.emitBEQ(Register.A0, Register.T0,elseBlock, comment);
|
|
|
|
|
String operator = node.operator;
|
|
|
|
|
if(node.left.getInferredType().equals(Type.INT_TYPE) && node.right.getInferredType().equals(Type.INT_TYPE))
|
|
|
|
|
{
|
|
|
|
|
node.left.dispatch(this);
|
|
|
|
|
backend.emitSW(Register.A0, Register.FP, -sp_off*wordSize, "Push on stack slot "+sp_off);
|
|
|
|
|
sp_off++;
|
|
|
|
|
node.right.dispatch(this);
|
|
|
|
|
sp_off--;
|
|
|
|
|
backend.emitLW(Register.T0, Register.FP, -sp_off*wordSize, "Pop stack slot "+sp_off);
|
|
|
|
|
|
|
|
|
|
// Arithmetic Operators
|
|
|
|
|
if(operator.equals("+"))
|
|
|
|
|
backend.emitADD(Register.A0, Register.A0, Register.T0, "Add operation");
|
|
|
|
|
else if(operator.equals("-"))
|
|
|
|
|
backend.emitSUB(Register.A0, Register.A0, Register.T0, "Sub operation");
|
|
|
|
|
else if(operator.equals("*"))
|
|
|
|
|
backend.emitMUL(Register.A0, Register.A0, Register.T0, "Mul operation");
|
|
|
|
|
else if(operator.equals("//"))
|
|
|
|
|
{
|
|
|
|
|
Label label = generateLocalLabel();
|
|
|
|
|
backend.emitBNEZ(Register.T0, label, "Check for Divide-by-zero");
|
|
|
|
|
backend.emitJAL(errorDiv, "Divide-by-zero error");
|
|
|
|
|
backend.emitLocalLabel(label, "Divide since divisor not zero");
|
|
|
|
|
backend.emitDIV(Register.A0, Register.A0, Register.T0, "Divide operation");
|
|
|
|
|
}
|
|
|
|
|
else if(operator.equals("%"))
|
|
|
|
|
{
|
|
|
|
|
Label label = generateLocalLabel();
|
|
|
|
|
backend.emitBNEZ(Register.T0, label, "Check for Divide-by-zero");
|
|
|
|
|
backend.emitJAL(errorDiv, "Divide-by-zero error");
|
|
|
|
|
backend.emitLocalLabel(label, "Divide since divisor not zero");
|
|
|
|
|
backend.emitREM(Register.A0, Register.A0, Register.T0, "Modulus operation");
|
|
|
|
|
}
|
|
|
|
|
else if(node.operator.equals(">="))
|
|
|
|
|
backend.emitBLT(Register.A0, Register.T0,elseBlock, comment);
|
|
|
|
|
else if(node.operator.equals("<="))
|
|
|
|
|
{
|
|
|
|
|
Label temp = generateLocalLabel();
|
|
|
|
|
backend.emitBEQ(Register.A0, Register.T0,temp, "Branch on "+node.operator);
|
|
|
|
|
backend.emitBGE(Register.A0, Register.T0,elseBlock, comment);
|
|
|
|
|
backend.emitLocalLabel(temp, "True part of if check");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{ // Comparison operators
|
|
|
|
|
//elseBlock = generateLocalLabel();
|
|
|
|
|
String comment="Operator: "+operator;
|
|
|
|
|
if(operator.equals("=="))
|
|
|
|
|
{
|
|
|
|
|
backend.emitXOR(Register.A0, Register.A0, Register.T0, "Check for equality");
|
|
|
|
|
backend.emitSEQZ(Register.A0, Register.A0, "Result is True if XOR equals 0");
|
|
|
|
|
}
|
|
|
|
|
else if(operator.equals("!="))
|
|
|
|
|
{
|
|
|
|
|
backend.emitXOR(Register.A0, Register.A0, Register.T0, "Check for inequality");
|
|
|
|
|
backend.emitSNEZ(Register.A0, Register.A0, "Result is True if XOR does not equal 0");
|
|
|
|
|
}
|
|
|
|
|
else if(operator.equals("<"))
|
|
|
|
|
backend.emitSLT(Register.A0,Register.A0, Register.T0, comment);
|
|
|
|
|
else if(operator.equals(">"))
|
|
|
|
|
backend.emitSLT(Register.A0, Register.T0, Register.A0, comment);
|
|
|
|
|
else if(operator.equals("<="))
|
|
|
|
|
{
|
|
|
|
|
backend.emitADDI(Register.T0,Register.T0, 1, "Increment by 1");
|
|
|
|
|
backend.emitSLT(Register.A0, Register.A0, Register.T0, comment);
|
|
|
|
|
}
|
|
|
|
|
else if(operator.equals(">="))
|
|
|
|
|
{
|
|
|
|
|
backend.emitADDI(Register.A0,Register.A0, 1, "Increment by 1");
|
|
|
|
|
backend.emitSLT(Register.A0, Register.A0, Register.T0, comment);
|
|
|
|
|
}
|
|
|
|
|
else if(operator.equals("is"))
|
|
|
|
|
{
|
|
|
|
|
backend.emitXOR(Register.A0, Register.A0, Register.T0, "is operation");
|
|
|
|
|
backend.emitSEQZ(Register.A0, Register.A0, "Result is True if XOR equals 0");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if(node.left.getInferredType().equals(Type.STR_TYPE) && node.right.getInferredType().equals(Type.STR_TYPE))
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
@ -534,6 +571,7 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
|
emitErrorFunc(errorNone, "Operation on None");
|
|
|
|
|
emitErrorFunc(errorDiv, "Division by zero");
|
|
|
|
|
emitErrorFunc(errorOob, "Index out of bounds");
|
|
|
|
|
emitErrorFunc(errorNI, "Not Implemented");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Emit an error routine labeled ERRLABEL that aborts with message MSG. */
|
|
|
|
|