|
|
@ -32,12 +32,12 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
{
|
|
|
|
{
|
|
|
|
/** Label for built-in routines. */
|
|
|
|
/** Label for built-in routines. */
|
|
|
|
protected final Label makeintLabel = new Label("makeint");
|
|
|
|
protected final Label makeintLabel = new Label("makeint");
|
|
|
|
protected final Label strneqlLablel = new Label("strneql");
|
|
|
|
protected final Label strneqlLabel = new Label("strneql");
|
|
|
|
protected final Label streqlLablel = new Label("streql");
|
|
|
|
protected final Label streqlLabel = new Label("streql");
|
|
|
|
protected final Label makeboolLabel = new Label("makebool");
|
|
|
|
protected final Label makeboolLabel = new Label("makebool");
|
|
|
|
protected final Label strcatLablel = new Label("strcat");
|
|
|
|
protected final Label strcatLabel = new Label("strcat");
|
|
|
|
protected final Label concatLablel = new Label("concat");
|
|
|
|
protected final Label concatLabel = new Label("concat");
|
|
|
|
protected final Label conslistLablel = new Label("conslist");
|
|
|
|
protected final Label conslistLabel = new Label("conslist");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -709,24 +709,42 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(node.left.getInferredType().isListType() && node.right.getInferredType().isListType())
|
|
|
|
else if(node.left.getInferredType().isListType() && node.right.getInferredType().isListType())
|
|
|
|
{
|
|
|
|
{
|
|
|
|
node.right.dispatch(this);
|
|
|
|
|
|
|
|
backend.emitSW(Register.A0, Register.FP, -sp_off*wordSize, "Push on stack slot "+sp_off);
|
|
|
|
|
|
|
|
incSp(1);
|
|
|
|
|
|
|
|
node.left.dispatch(this);
|
|
|
|
|
|
|
|
sp_off--;
|
|
|
|
|
|
|
|
backend.emitLW(Register.T0, Register.FP, -sp_off*wordSize, "Pop stack slot "+sp_off);
|
|
|
|
|
|
|
|
if(operator.equals("+"))
|
|
|
|
if(operator.equals("+"))
|
|
|
|
addLists();
|
|
|
|
{
|
|
|
|
|
|
|
|
node.left.dispatch(this);
|
|
|
|
|
|
|
|
backend.emitSW(Register.A0, Register.FP, -sp_off*wordSize, "Push left operand on stack slot "+sp_off);
|
|
|
|
|
|
|
|
incSp(1);
|
|
|
|
|
|
|
|
node.right.dispatch(this);
|
|
|
|
|
|
|
|
backend.emitSW(Register.A0, Register.FP, -sp_off*wordSize, "Push right operand on stack slot "+sp_off);
|
|
|
|
|
|
|
|
incSp(1);
|
|
|
|
|
|
|
|
backend.emitADDI(Register.SP,Register.FP,-sp_off*wordSize,"Set SP to last argument");
|
|
|
|
|
|
|
|
backend.emitJAL(concatLabel, "Call concatenation routine");
|
|
|
|
|
|
|
|
backend.emitADDI(Register.SP, Register.FP, "-"+size_label, "Set SP to stack frame");
|
|
|
|
|
|
|
|
return Register.A0;
|
|
|
|
|
|
|
|
//addLists();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
backend.emitJAL(errorNI, "Operator not implemented for list operands");
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(node.left.getInferredType().equals(Type.STR_TYPE) && node.right.getInferredType().equals(Type.STR_TYPE))
|
|
|
|
else if(node.left.getInferredType().equals(Type.STR_TYPE) && node.right.getInferredType().equals(Type.STR_TYPE))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
if(operator.equals("=="))
|
|
|
|
|
|
|
|
{
|
|
|
|
incSp(2);
|
|
|
|
incSp(2);
|
|
|
|
backend.emitSW(node.left.dispatch(this), FP, (1 - sp_off) *wordSize, "Push argument 0 from last.");
|
|
|
|
backend.emitSW(node.left.dispatch(this), FP, (1 - sp_off) *wordSize, "Push argument 0 from last.");
|
|
|
|
backend.emitSW(node.right.dispatch(this), FP, ( - sp_off) *wordSize, "Push argument 1 from last.");
|
|
|
|
backend.emitSW(node.right.dispatch(this), FP, ( - sp_off) *wordSize, "Push argument 1 from last.");
|
|
|
|
backend.emitADDI(SP, FP, -sp_off * wordSize, "Set SP to last argument.");
|
|
|
|
backend.emitADDI(SP, FP, -sp_off * wordSize, "Set SP to last argument.");
|
|
|
|
backend.emitJAL(streqlLablel, "Invoke method:streql");
|
|
|
|
backend.emitJAL(streqlLabel, "Invoke method:streql");
|
|
|
|
sp_off -= 2;
|
|
|
|
sp_off -= 2;
|
|
|
|
backend.emitADDI(SP, FP, -sp_off*wordSize, "restore sp");
|
|
|
|
backend.emitADDI(SP, FP, -sp_off*wordSize, "restore sp");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if(operator.equals("+"))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
backend.emitJAL(errorNI, "Operator not implemented for String operands");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(operator.equals("is"))
|
|
|
|
else if(operator.equals("is"))
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -808,25 +826,33 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public Register analyze(ListExpr node) {
|
|
|
|
public Register analyze(ListExpr node) {
|
|
|
|
int l = node.elements.size();
|
|
|
|
int l = node.elements.size();
|
|
|
|
backend.emitLI(Register.A1, l+1, "Load length of list+1 in words");
|
|
|
|
int i=l;
|
|
|
|
backend.emitLA(Register.A0, listClass.getPrototypeLabel(), "Load empty list");
|
|
|
|
|
|
|
|
backend.emitJAL(objectAllocResizeLabel, "Allocate list");
|
|
|
|
|
|
|
|
backend.emitMV(Register.A1, Register.A0, "Store address of allocated space");
|
|
|
|
|
|
|
|
backend.emitMV(Register.T0, Register.A1, "Make a copy of address of allocated space");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int i = l;
|
|
|
|
|
|
|
|
backend.emitLI(Register.A0,l,"Load length of list in words");
|
|
|
|
|
|
|
|
backend.emitSW(Register.A0,Register.T0,0,"Store length of list: "+i);
|
|
|
|
|
|
|
|
backend.emitADDI(Register.T0,Register.T0,wordSize,"Increment address");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(Expr exp:node.elements)
|
|
|
|
for(Expr exp:node.elements)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Register r = exp.dispatch(this);
|
|
|
|
Register r = exp.dispatch(this);
|
|
|
|
backend.emitSW(r,Register.T0,0,"Store element "+i+" from last.");
|
|
|
|
if (exp.getInferredType().equals(Type.INT_TYPE) && !node.elements.get(0).getInferredType().equals(Type.INT_TYPE))
|
|
|
|
backend.emitADDI(Register.T0,Register.T0,wordSize,"Increment address");
|
|
|
|
{
|
|
|
|
|
|
|
|
if(r!=Register.A0)
|
|
|
|
|
|
|
|
backend.emitMV(r, Register.A0, "Copy to Register A0");
|
|
|
|
|
|
|
|
backend.emitJAL(makeintLabel, "Box integer");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (exp.getInferredType().equals(Type.BOOL_TYPE) && !node.elements.get(0).getInferredType().equals(Type.BOOL_TYPE))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if(r!=Register.A0)
|
|
|
|
|
|
|
|
backend.emitMV(r, Register.A0, "Copy to Register A0");
|
|
|
|
|
|
|
|
backend.emitJAL(makeboolLabel, "Box boolean");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
backend.emitSW(Register.A0, Register.FP, -sp_off*wordSize, "Push argument "+i+" from last");
|
|
|
|
|
|
|
|
incSp(1);
|
|
|
|
i--;
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
backend.emitMV(Register.A0,Register.A1,"Load address of list");
|
|
|
|
backend.emitLI(Register.A0, l, "Pass list length");
|
|
|
|
|
|
|
|
backend.emitSW(Register.A0, Register.FP, -sp_off*wordSize, "Push length of list");
|
|
|
|
|
|
|
|
incSp(1);
|
|
|
|
|
|
|
|
backend.emitADDI(Register.SP, Register.FP, -(sp_off-1)*wordSize, "Set SP to last argument");
|
|
|
|
|
|
|
|
backend.emitJAL(conslistLabel, "Move values to new list object");
|
|
|
|
|
|
|
|
backend.emitADDI(Register.SP, Register.FP, "-"+size_label, "Set SP to stack frame");
|
|
|
|
|
|
|
|
sp_off-=l;
|
|
|
|
return Register.A0;
|
|
|
|
return Register.A0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|