|
|
@ -80,7 +80,7 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
protected void emitTopLevel(List<Stmt> statements)
|
|
|
|
protected void emitTopLevel(List<Stmt> statements)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
String mainlabel = "@..main.size";
|
|
|
|
String mainlabel = "@..main.size";
|
|
|
|
StmtAnalyzer stmtAnalyzer = new StmtAnalyzer(null);
|
|
|
|
StmtAnalyzer stmtAnalyzer = new StmtAnalyzer(null);
|
|
|
|
backend.emitADDI(SP, SP, "-"+mainlabel, "Saved FP and saved RA (unused at top level).");
|
|
|
|
backend.emitADDI(SP, SP, "-"+mainlabel, "Saved FP and saved RA (unused at top level).");
|
|
|
|
backend.emitSW(ZERO, SP, mainlabel+"-4", "Top saved FP is 0.");
|
|
|
|
backend.emitSW(ZERO, SP, mainlabel+"-4", "Top saved FP is 0.");
|
|
|
@ -263,18 +263,6 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
{
|
|
|
|
{
|
|
|
|
//object create
|
|
|
|
//object create
|
|
|
|
ClassInfo cls = (ClassInfo) ty;
|
|
|
|
ClassInfo cls = (ClassInfo) ty;
|
|
|
|
/**
|
|
|
|
|
|
|
|
la a0, $DoublingVector$prototype # Load pointer to prototype of: DoublingVector
|
|
|
|
|
|
|
|
jal alloc # Allocate new object in A0
|
|
|
|
|
|
|
|
sw a0, -12(fp) # Push on stack slot 3
|
|
|
|
|
|
|
|
sw a0, -16(fp) # Push argument 0 from last.
|
|
|
|
|
|
|
|
addi sp, fp, -16 # Set SP to last argument.
|
|
|
|
|
|
|
|
lw a1, 8(a0) # Load address of object's dispatch table
|
|
|
|
|
|
|
|
lw a1, 0(a1) # Load address of method: DoublingVector.__init__
|
|
|
|
|
|
|
|
jalr a1 # Invoke method: DoublingVector.__init__
|
|
|
|
|
|
|
|
addi sp, fp, -@..main.size # Set SP to stack frame top.
|
|
|
|
|
|
|
|
lw a0, -12(fp) # Pop stack slot 3
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
backend.emitLA(A0, cls.getPrototypeLabel(), String.format("Load pointer to prototype of: %s", cls.getClassName()));
|
|
|
|
backend.emitLA(A0, cls.getPrototypeLabel(), String.format("Load pointer to prototype of: %s", cls.getClassName()));
|
|
|
|
backend.emitJAL(objectAllocLabel, "Allocate new object in A0");
|
|
|
|
backend.emitJAL(objectAllocLabel, "Allocate new object in A0");
|
|
|
|
backend.emitSW(A0, FP, -sp_off*wordSize, String.format("Push on stack slot %d", sp_off));
|
|
|
|
backend.emitSW(A0, FP, -sp_off*wordSize, String.format("Push on stack slot %d", sp_off));
|
|
|
@ -319,21 +307,18 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
{
|
|
|
|
{
|
|
|
|
backend.emitSW(FP, FP, -(sp_off+1) * wordSize, "Push static link onto active frame.");
|
|
|
|
backend.emitSW(FP, FP, -(sp_off+1) * wordSize, "Push static link onto active frame.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int origsp = sp_off;
|
|
|
|
|
|
|
|
incSp(1);
|
|
|
|
incSp(1);
|
|
|
|
|
|
|
|
|
|
|
|
List<Expr> args = node.args;
|
|
|
|
List<Expr> args = node.args;
|
|
|
|
int spaceRequiredForArgs = (args.size() + 1)*4;
|
|
|
|
int spaceRequiredForArgs = (args.size() + 1)*4;
|
|
|
|
for (int i = 0; i < args.size(); i++)
|
|
|
|
for (int i = 0; i < args.size(); i++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
incSp(1);
|
|
|
|
incSp(1);
|
|
|
|
int argNum = i + 1;
|
|
|
|
Expr expr = args.get(i);
|
|
|
|
int slotNum = argNum + 1; // We have extra slot for static link
|
|
|
|
expr.dispatch(this);
|
|
|
|
Expr expr = args.get(i);
|
|
|
|
|
|
|
|
expr.dispatch(this);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String formalParamName = calleeFunctionInfo.getParams().get(i);
|
|
|
|
String formalParamName = calleeFunctionInfo.getParams().get(i);
|
|
|
|
StackVarInfo formalParamInfo = (StackVarInfo) calleeFunctionInfo.getSymbolTable().get(formalParamName);
|
|
|
|
StackVarInfo formalParamInfo = (StackVarInfo) calleeFunctionInfo.getSymbolTable().get(formalParamName);
|
|
|
|
|
|
|
|
|
|
|
|
if (expr.getInferredType().equals(Type.INT_TYPE))
|
|
|
|
if (expr.getInferredType().equals(Type.INT_TYPE))
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -355,7 +340,7 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if(!formalParamInfo.getVarType().equals(Type.OBJECT_TYPE) && !formalParamInfo.getVarType().equals(Type.BOOL_TYPE))
|
|
|
|
if(!formalParamInfo.getVarType().equals(Type.OBJECT_TYPE) && !formalParamInfo.getVarType().equals(Type.BOOL_TYPE))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
backend.emitJAL(errorNI, "Passed argument does not match formal parameter");
|
|
|
|
backend.emitJAL(errorNI, "Passed argument does not match formal parameter");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((functionId.name.equals("print"))&&(formalParamInfo.getVarType().equals(Type.OBJECT_TYPE) || formalParamInfo.getVarType().equals(Type.BOOL_TYPE)))
|
|
|
|
else if ((functionId.name.equals("print"))&&(formalParamInfo.getVarType().equals(Type.OBJECT_TYPE) || formalParamInfo.getVarType().equals(Type.BOOL_TYPE)))
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -365,21 +350,22 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// All expressions should save their end result in A0
|
|
|
|
// All expressions should save their end result in A0
|
|
|
|
// So, once expr is evaluated add value inside A0 onto stack as an actual argument
|
|
|
|
// So, once expr is evaluated add value inside A0 onto stack as an actual argument
|
|
|
|
backend.emitSW(A0, FP, -(sp_off) * wordSize, "Push actual argument for " + formalParamName + " onto stack");
|
|
|
|
backend.emitSW(A0, FP, -(sp_off) * wordSize, "Push actual argument for " + formalParamName + " onto stack");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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(calleeFunctionInfo.getCodeLabel(), "Invoke function: " + functionId.name);
|
|
|
|
backend.emitJAL(calleeFunctionInfo.getCodeLabel(), "Invoke function: " + functionId.name);
|
|
|
|
backend.emitADDI(SP, FP, "-"+size_label, "Set SP to stack frame top.");
|
|
|
|
backend.emitADDI(SP, FP, "-"+size_label, "Set SP to stack frame top.");
|
|
|
|
sp_off-=spaceRequiredForArgs/wordSize;
|
|
|
|
sp_off-=spaceRequiredForArgs/wordSize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return A0;
|
|
|
|
return A0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public Register analyze(MethodCallExpr node)
|
|
|
|
public Register analyze(MethodCallExpr node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Register obj = node.method.object.dispatch(this);
|
|
|
|
Register obj = node.method.object.dispatch(this);
|
|
|
|
int n_args = node.args.size();
|
|
|
|
int n_args = node.args.size();
|
|
|
|
|
|
|
|
|
|
|
|
Label label = generateLocalLabel();
|
|
|
|
Label label = generateLocalLabel();
|
|
|
@ -404,7 +390,7 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
String.format("Load address of method: %s.%s", objectClass.getClassName(), node.method.member.name));
|
|
|
|
String.format("Load address of method: %s.%s", objectClass.getClassName(), node.method.member.name));
|
|
|
|
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.emitJALR(A1, String.format("Invoke method: %s.%s", objectClass.getClassName(), node.method.member.name));
|
|
|
|
backend.emitJALR(A1, String.format("Invoke method: %s.%s", objectClass.getClassName(), node.method.member.name));
|
|
|
|
backend.emitInsn(String.format("addi sp, fp, -%s", size_label), "Set SP to stack frame top.");
|
|
|
|
backend.emitADDI(SP, FP, "-" + size_label, "Set SP to stack frame top");
|
|
|
|
sp_off -= n_args+1;
|
|
|
|
sp_off -= n_args+1;
|
|
|
|
|
|
|
|
|
|
|
|
return A0;
|
|
|
|
return A0;
|
|
|
@ -414,13 +400,15 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public Register analyze(ReturnStmt stmt)
|
|
|
|
public Register analyze(ReturnStmt stmt)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Expr expr = stmt.value;
|
|
|
|
Expr expr = stmt.value;
|
|
|
|
if(expr == null)
|
|
|
|
if (expr == null) {
|
|
|
|
backend.emitMV(A0, ZERO, "Return None");
|
|
|
|
backend.emitMV(A0, ZERO, "Return None");
|
|
|
|
else
|
|
|
|
} else {
|
|
|
|
// All expressions should save their end result in A0
|
|
|
|
// All expressions should save their end result in A0
|
|
|
|
expr.dispatch(this);
|
|
|
|
expr.dispatch(this);
|
|
|
|
backend.emitJ(this.epilogue, "Jump to function epilogue");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend.emitJ(this.epilogue, "Jump to function epilogue");
|
|
|
|
return A0;
|
|
|
|
return A0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -906,28 +894,37 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
Label startLoop = generateLocalLabel();
|
|
|
|
Label startLoop = generateLocalLabel();
|
|
|
|
Label endLoop = generateLocalLabel();
|
|
|
|
Label endLoop = generateLocalLabel();
|
|
|
|
Label temp = generateLocalLabel();
|
|
|
|
Label temp = generateLocalLabel();
|
|
|
|
|
|
|
|
|
|
|
|
r=getRegister();
|
|
|
|
r=getRegister();
|
|
|
|
regs.add(r);
|
|
|
|
regs.add(r);
|
|
|
|
Register iden = registerPool[r];
|
|
|
|
Register iden = registerPool[r];
|
|
|
|
|
|
|
|
|
|
|
|
node.iterable.dispatch(this);
|
|
|
|
node.iterable.dispatch(this);
|
|
|
|
|
|
|
|
|
|
|
|
r=getRegister();
|
|
|
|
r=getRegister();
|
|
|
|
regs.add(r);
|
|
|
|
regs.add(r);
|
|
|
|
Register l = registerPool[r];
|
|
|
|
Register l = registerPool[r];
|
|
|
|
|
|
|
|
|
|
|
|
r=getRegister();
|
|
|
|
r=getRegister();
|
|
|
|
regs.add(r);
|
|
|
|
regs.add(r);
|
|
|
|
Register ln = registerPool[r];
|
|
|
|
Register ln = registerPool[r];
|
|
|
|
|
|
|
|
|
|
|
|
backend.emitBNEZ(Register.A0, temp, "Ensure not none");
|
|
|
|
backend.emitBNEZ(Register.A0, temp, "Ensure not none");
|
|
|
|
backend.emitJ(errorNone, "Empty List");
|
|
|
|
backend.emitJ(errorNone, "Empty List");
|
|
|
|
backend.emitLocalLabel(temp, "Continue execution for for-loop");
|
|
|
|
backend.emitLocalLabel(temp, "Continue execution for for-loop");
|
|
|
|
backend.emitMV(l,Register.A0,"Location of list");
|
|
|
|
backend.emitMV(l,Register.A0,"Location of list");
|
|
|
|
|
|
|
|
|
|
|
|
r=getRegister();
|
|
|
|
r=getRegister();
|
|
|
|
regs.add(r);
|
|
|
|
regs.add(r);
|
|
|
|
Register iter = registerPool[r];
|
|
|
|
Register iter = registerPool[r];
|
|
|
|
|
|
|
|
|
|
|
|
backend.emitSW(l, Register.FP, -sp_off*wordSize, "Store location on stack");
|
|
|
|
backend.emitSW(l, Register.FP, -sp_off*wordSize, "Store location on stack");
|
|
|
|
incSp(1);
|
|
|
|
incSp(1);
|
|
|
|
|
|
|
|
|
|
|
|
backend.emitMV(iter, Register.ZERO, "Initialize index variable");
|
|
|
|
backend.emitMV(iter, Register.ZERO, "Initialize index variable");
|
|
|
|
backend.emitSW(iter, Register.FP, -sp_off*wordSize, "Store index on stack");
|
|
|
|
backend.emitSW(iter, Register.FP, -sp_off*wordSize, "Store index on stack");
|
|
|
|
incSp(1);
|
|
|
|
incSp(1);
|
|
|
|
|
|
|
|
|
|
|
|
backend.emitLocalLabel(startLoop, "Start for loop");
|
|
|
|
backend.emitLocalLabel(startLoop, "Start for loop");
|
|
|
|
backend.emitLW(iter, Register.FP, -(sp_off-1)*wordSize, "Load index from stack");
|
|
|
|
backend.emitLW(iter, Register.FP, -(sp_off-1)*wordSize, "Load index from stack");
|
|
|
|
backend.emitLW(l, Register.FP, -(sp_off-2)*wordSize, "Store list location from stack");
|
|
|
|
backend.emitLW(l, Register.FP, -(sp_off-2)*wordSize, "Store list location from stack");
|
|
|
@ -946,7 +943,7 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
GlobalVarInfo gvi=(GlobalVarInfo) info;
|
|
|
|
GlobalVarInfo gvi=(GlobalVarInfo) info;
|
|
|
|
backend.emitSW(iden, gvi.getLabel(), Register.T0, "Assign global: "+node.identifier.name+"(using tmp register)");
|
|
|
|
backend.emitSW(iden, gvi.getLabel(), Register.T0, "Assign global: "+node.identifier.name+"(using tmp register)");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
StackVarRuntimeInfo rtinfo = (StackVarRuntimeInfo) getVar(node.identifier);
|
|
|
|
StackVarRuntimeInfo rtinfo = (StackVarRuntimeInfo) getVar(node.identifier);
|
|
|
|
backend.emitSW(iden, rtinfo.sl, rtinfo.off,"Store local variable: "+node.identifier.name);
|
|
|
|
backend.emitSW(iden, rtinfo.sl, rtinfo.off,"Store local variable: "+node.identifier.name);
|
|
|
@ -957,8 +954,8 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
sp_off -= 2;
|
|
|
|
sp_off -= 2;
|
|
|
|
backend.emitJ(startLoop, "Jump to beginning of loop");
|
|
|
|
backend.emitJ(startLoop, "Jump to beginning of loop");
|
|
|
|
backend.emitLocalLabel(endLoop, "End of for loop");
|
|
|
|
backend.emitLocalLabel(endLoop, "End of for loop");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (node.iterable.getInferredType().equals(Type.STR_TYPE))
|
|
|
|
else if (node.iterable.getInferredType().equals(Type.STR_TYPE))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Label startLoop = generateLocalLabel();
|
|
|
|
Label startLoop = generateLocalLabel();
|
|
|
|
Label endLoop = generateLocalLabel();
|
|
|
|
Label endLoop = generateLocalLabel();
|
|
|
@ -1018,10 +1015,10 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
{
|
|
|
|
{
|
|
|
|
backend.emitJAL(errorNI, "Operator not implemented");
|
|
|
|
backend.emitJAL(errorNI, "Operator not implemented");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for(int n:regs)
|
|
|
|
for(int n:regs) {
|
|
|
|
freeRegister(n);
|
|
|
|
freeRegister(n);
|
|
|
|
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|