|
|
@ -4,6 +4,7 @@ import java.util.ArrayList;
|
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.Map;
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
import java.util.Stack;
|
|
|
|
|
|
|
|
|
|
|
|
import chocopy.common.analysis.*;
|
|
|
|
import chocopy.common.analysis.*;
|
|
|
|
import chocopy.common.astnodes.*;
|
|
|
|
import chocopy.common.astnodes.*;
|
|
|
@ -90,6 +91,8 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
{
|
|
|
|
{
|
|
|
|
stmt.dispatch(stmtAnalyzer);
|
|
|
|
stmt.dispatch(stmtAnalyzer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
stmtAnalyzer.emitSizeLabel();
|
|
|
|
|
|
|
|
|
|
|
|
backend.emitLI(A0, EXIT_ECALL, "Code for ecall: exit");
|
|
|
|
backend.emitLI(A0, EXIT_ECALL, "Code for ecall: exit");
|
|
|
|
backend.emitEcall(null);
|
|
|
|
backend.emitEcall(null);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -155,10 +158,8 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
for (Stmt stmt : funcInfo.getStatements()) {
|
|
|
|
for (Stmt stmt : funcInfo.getStatements()) {
|
|
|
|
stmt.dispatch(stmtAnalyzer);
|
|
|
|
stmt.dispatch(stmtAnalyzer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
stmtAnalyzer.emitSizeLabel();
|
|
|
|
backend.emitJ(stmtAnalyzer.epilogue, "Jump to function epilogue");
|
|
|
|
backend.emitJ(stmtAnalyzer.epilogue, "Jump to function epilogue");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// --- Epilogue ---
|
|
|
|
// --- Epilogue ---
|
|
|
|
backend.emitLocalLabel(stmtAnalyzer.epilogue, "Epilogue");
|
|
|
|
backend.emitLocalLabel(stmtAnalyzer.epilogue, "Epilogue");
|
|
|
|
backend.emitLW(RA, FP, -4, "Get return address");
|
|
|
|
backend.emitLW(RA, FP, -4, "Get return address");
|
|
|
@ -206,7 +207,7 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
private final FuncInfo funcInfo;
|
|
|
|
private final FuncInfo funcInfo;
|
|
|
|
|
|
|
|
|
|
|
|
/** Label of code that exits from block. */
|
|
|
|
/** Label of code that exits from block. */
|
|
|
|
protected Label elseBlock;
|
|
|
|
protected Stack<Label> elseBlock = new Stack<Label>();
|
|
|
|
|
|
|
|
|
|
|
|
/** Variable to keep track of slots of stored variables on stack */
|
|
|
|
/** Variable to keep track of slots of stored variables on stack */
|
|
|
|
// example usage: backend.emitLW(A0, SP, varSlotMap.get(varName)) to load the variable using its name
|
|
|
|
// example usage: backend.emitLW(A0, SP, varSlotMap.get(varName)) to load the variable using its name
|
|
|
@ -254,7 +255,9 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
max_sp = max_sp >= sp_off?max_sp:sp_off;
|
|
|
|
max_sp = max_sp >= sp_off?max_sp:sp_off;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void emitSizeLabel(){
|
|
|
|
|
|
|
|
backend.defineSym(size_label, max_sp*wordSize);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// *********** functions start ***********
|
|
|
|
// *********** functions start ***********
|
|
|
@ -263,8 +266,7 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
System.out.println("Inside CallExpr: " + node.function.name);
|
|
|
|
System.out.println("Inside CallExpr: " + node.function.name);
|
|
|
|
backend.emitLW(T6, FP, 0, "Inside CallExpr: " + node.function.name);
|
|
|
|
backend.emitLW(T6, FP, 0, "Inside CallExpr: " + node.function.name);
|
|
|
|
|
|
|
|
|
|
|
|
// FIXME: Why are we using globalSymbols here but not the sym???
|
|
|
|
SymbolInfo Ty = sym.get(node.function.name);
|
|
|
|
SymbolInfo Ty = globalSymbols.get(node.function.name);
|
|
|
|
|
|
|
|
if(Ty instanceof ClassInfo){
|
|
|
|
if(Ty instanceof ClassInfo){
|
|
|
|
//object create
|
|
|
|
//object create
|
|
|
|
ClassInfo cls = (ClassInfo) Ty;
|
|
|
|
ClassInfo cls = (ClassInfo) Ty;
|
|
|
@ -301,6 +303,18 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
|
|
|
|
|
|
|
|
List<Expr> args = node.args;
|
|
|
|
List<Expr> args = node.args;
|
|
|
|
int spaceRequiredForArgs = (args.size() + 1)*4;
|
|
|
|
int spaceRequiredForArgs = (args.size() + 1)*4;
|
|
|
|
|
|
|
|
int depth = calleeFunctionInfo.getDepth();
|
|
|
|
|
|
|
|
int tmpHandle = getRegister();
|
|
|
|
|
|
|
|
Register tmp = registerPool[tmpHandle];
|
|
|
|
|
|
|
|
FuncInfo currFuncInfo = calleeFunctionInfo;
|
|
|
|
|
|
|
|
backend.emitMV(tmp, FP, "Load FP");
|
|
|
|
|
|
|
|
while (depth > 0) {
|
|
|
|
|
|
|
|
final FuncInfo parentFuncInfo = currFuncInfo.getParentFuncInfo();
|
|
|
|
|
|
|
|
backend.emitLW(tmp, tmp, parentFuncInfo.getParams().size()*wordSize, "Load static link to " + parentFuncInfo.getFuncName());
|
|
|
|
|
|
|
|
currFuncInfo = parentFuncInfo;
|
|
|
|
|
|
|
|
--depth;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
freeRegister(tmpHandle);
|
|
|
|
//backend.emitSW(A0, SP, -4, "Put static link");
|
|
|
|
//backend.emitSW(A0, SP, -4, "Put static link");
|
|
|
|
for (int i = 0; i < args.size(); i++) {
|
|
|
|
for (int i = 0; i < args.size(); i++) {
|
|
|
|
int argNum = i + 1;
|
|
|
|
int argNum = i + 1;
|
|
|
@ -312,13 +326,13 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
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)) {
|
|
|
|
if (formalParamInfo.getVarType().equals(Type.OBJECT_TYPE) || formalParamInfo.getVarType().equals(Type.INT_TYPE)) {
|
|
|
|
if ((functionId.name.equals("print")) &&(formalParamInfo.getVarType().equals(Type.OBJECT_TYPE) || formalParamInfo.getVarType().equals(Type.INT_TYPE))) {
|
|
|
|
backend.emitJAL(makeintLabel, "Box integer");
|
|
|
|
backend.emitJAL(makeintLabel, "Box integer");
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
// FIXME: passed argument does not match formal parameter
|
|
|
|
// FIXME: passed argument does not match formal parameter
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (expr.getInferredType().equals(Type.BOOL_TYPE)) {
|
|
|
|
} else if (expr.getInferredType().equals(Type.BOOL_TYPE)) {
|
|
|
|
if (formalParamInfo.getVarType().equals(Type.OBJECT_TYPE) || formalParamInfo.getVarType().equals(Type.BOOL_TYPE)) {
|
|
|
|
if ((functionId.name.equals("print"))&&(formalParamInfo.getVarType().equals(Type.OBJECT_TYPE) || formalParamInfo.getVarType().equals(Type.BOOL_TYPE))) {
|
|
|
|
backend.emitJAL(makeboolLabel, "Box boolean");
|
|
|
|
backend.emitJAL(makeboolLabel, "Box boolean");
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
// FIXME: passed argument does not match formal parameter
|
|
|
|
// FIXME: passed argument does not match formal parameter
|
|
|
@ -331,7 +345,8 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
backend.emitADDI(SP, SP, -spaceRequiredForArgs, "Set SP to last argument.");
|
|
|
|
backend.emitADDI(SP, SP, -spaceRequiredForArgs, "Set SP to last argument.");
|
|
|
|
backend.emitJAL(new Label("$"+functionId.name), "Invoke function: " + functionId.name);
|
|
|
|
String label_str = "$"+calleeFunctionInfo.getFuncName();
|
|
|
|
|
|
|
|
backend.emitJAL(new Label(label_str), "Invoke function: " + label_str);
|
|
|
|
backend.emitADDI(SP, SP, spaceRequiredForArgs, "Set SP to stack frame top.");
|
|
|
|
backend.emitADDI(SP, SP, spaceRequiredForArgs, "Set SP to stack frame top.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return A0;
|
|
|
|
return A0;
|
|
|
@ -355,8 +370,11 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
String.format("Push argument %d from last.", n_args - i - 1));
|
|
|
|
String.format("Push argument %d from last.", n_args - i - 1));
|
|
|
|
|
|
|
|
|
|
|
|
backend.emitLW(A0, FP, (n_args- sp_off) * wordSize, String.format("Peek stack slot %d", sp_off - (n_args + 1)));
|
|
|
|
backend.emitLW(A0, FP, (n_args- sp_off) * wordSize, String.format("Peek stack slot %d", sp_off - (n_args + 1)));
|
|
|
|
ClassInfo objectClass = (ClassInfo)sym.get(((Identifier)node.method.object).name);
|
|
|
|
ClassInfo objectClass = null;
|
|
|
|
|
|
|
|
if(node.method.object instanceof CallExpr)
|
|
|
|
|
|
|
|
objectClass = (ClassInfo)globalSymbols.get(((CallExpr)node.method.object).getInferredType().className());
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
objectClass = (ClassInfo)globalSymbols.get(node.method.object.getInferredType().className());
|
|
|
|
backend.emitLW(A1, A0, getDispatchTableOffset(), "Load address of object's dispatch table");
|
|
|
|
backend.emitLW(A1, A0, getDispatchTableOffset(), "Load address of object's dispatch table");
|
|
|
|
backend.emitLW(A1, A1, getMethodOffset(objectClass, node.method.member.name),
|
|
|
|
backend.emitLW(A1, A1, getMethodOffset(objectClass, node.method.member.name),
|
|
|
|
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));
|
|
|
@ -419,7 +437,54 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
backend.emitLI(Register.A0, 0, "Load boolean literal: false ");
|
|
|
|
backend.emitLI(Register.A0, 0, "Load boolean literal: false ");
|
|
|
|
return Register.A0;
|
|
|
|
return Register.A0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class StackVarRuntimeInfo {
|
|
|
|
|
|
|
|
public final int off;
|
|
|
|
|
|
|
|
public final Register sl;
|
|
|
|
|
|
|
|
public int regHandle;
|
|
|
|
|
|
|
|
StackVarRuntimeInfo(Register sl, int off){
|
|
|
|
|
|
|
|
this.off = off;
|
|
|
|
|
|
|
|
this.sl = sl;
|
|
|
|
|
|
|
|
regHandle = -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
StackVarRuntimeInfo(Register sl, int off, int regHandle){
|
|
|
|
|
|
|
|
this.off = off;
|
|
|
|
|
|
|
|
this.sl = sl;
|
|
|
|
|
|
|
|
this.regHandle = regHandle;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public void free(){
|
|
|
|
|
|
|
|
if(regHandle > 0){
|
|
|
|
|
|
|
|
freeRegister(regHandle);
|
|
|
|
|
|
|
|
regHandle = -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
private Object getVar(Identifier id){
|
|
|
|
|
|
|
|
SymbolInfo info = sym.get(id.name);
|
|
|
|
|
|
|
|
if(info instanceof StackVarInfo)
|
|
|
|
|
|
|
|
return getStackVar((StackVarInfo)info);
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
return ((GlobalVarInfo)info).getLabel();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
private StackVarRuntimeInfo getStackVar(StackVarInfo info){
|
|
|
|
|
|
|
|
int curr_depth = funcInfo.getDepth();
|
|
|
|
|
|
|
|
int d_depth = curr_depth - info.getFuncInfo().getDepth();
|
|
|
|
|
|
|
|
if(d_depth == 0)
|
|
|
|
|
|
|
|
return new StackVarRuntimeInfo(SP, varSlotMap.get(info.getVarName()));
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
FuncInfo curr = funcInfo;
|
|
|
|
|
|
|
|
int tmpHandle = getRegister();
|
|
|
|
|
|
|
|
Register tmp = registerPool[tmpHandle];
|
|
|
|
|
|
|
|
backend.emitMV(tmp, FP, "tmp = FP");
|
|
|
|
|
|
|
|
while(d_depth > 0){
|
|
|
|
|
|
|
|
curr = curr.getParentFuncInfo();
|
|
|
|
|
|
|
|
backend.emitLW(tmp, tmp, curr.getParams().size()*wordSize, "Get static link");
|
|
|
|
|
|
|
|
-- d_depth;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// UNSAFE!!!!! PLEASE FREE THE TMP_HANDLE MANUALLY
|
|
|
|
|
|
|
|
return new StackVarRuntimeInfo(tmp, -wordSize*curr.getVarIndex(info.getVarName()), tmpHandle);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public Register analyze(AssignStmt node)
|
|
|
|
public Register analyze(AssignStmt node)
|
|
|
@ -432,27 +497,24 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
Register reg = node.value.dispatch(this);
|
|
|
|
Register reg = node.value.dispatch(this);
|
|
|
|
if (reg == null)
|
|
|
|
if (reg == null)
|
|
|
|
reg = A0;
|
|
|
|
reg = A0;
|
|
|
|
if (sym.getParent() == null)
|
|
|
|
for(Expr target: node.targets)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
for(Expr target: node.targets)
|
|
|
|
if(target instanceof Identifier)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if(target instanceof Identifier)
|
|
|
|
Identifier targetID = (Identifier)target;
|
|
|
|
{
|
|
|
|
Object var = getVar(targetID);
|
|
|
|
GlobalVarInfo gvi=(GlobalVarInfo)sym.get(((Identifier)target).name);
|
|
|
|
if(var instanceof StackVarRuntimeInfo){
|
|
|
|
backend.emitSW(reg, gvi.getLabel(), Register.T0, "Assign global: "+gvi.getVarName()+"(using tmp register)");
|
|
|
|
StackVarRuntimeInfo rtinfo = (StackVarRuntimeInfo) var;
|
|
|
|
|
|
|
|
backend.emitSW(reg, rtinfo.sl, rtinfo.off ,"Store local variable: "+((Identifier)target).name);
|
|
|
|
|
|
|
|
rtinfo.free();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
backend.emitSW(reg, (Label)var, T0, "Store Global variable: " + ((Identifier)targetID).name);
|
|
|
|
Register ret = target.dispatch(this);
|
|
|
|
|
|
|
|
backend.emitSW(T1, ret, 0, "Set list element");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
for(Expr target: node.targets)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
backend.emitLW(reg, SP, varSlotMap.get(((Identifier)target).name),"Load local variable: "+((Identifier)target).name);
|
|
|
|
Register ret = target.dispatch(this);
|
|
|
|
|
|
|
|
backend.emitSW(T1, ret, 0, "Set list element");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//}
|
|
|
|
//}
|
|
|
@ -478,8 +540,10 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
backend.emitBEQZ(result, ln,"Jump to end of loop");
|
|
|
|
backend.emitBEQZ(result, ln,"Jump to end of loop");
|
|
|
|
node.thenExpr.dispatch(this);
|
|
|
|
node.thenExpr.dispatch(this);
|
|
|
|
backend.emitJ(ln, "Jump to end of if expression");
|
|
|
|
backend.emitJ(ln, "Jump to end of if expression");
|
|
|
|
backend.emitLocalLabel(elseBlock, "Else part of if expression");
|
|
|
|
elseBlock.push(generateLocalLabel());
|
|
|
|
|
|
|
|
backend.emitLocalLabel(elseBlock.peek(), "Else part of if expression");
|
|
|
|
node.elseExpr.dispatch(this);
|
|
|
|
node.elseExpr.dispatch(this);
|
|
|
|
|
|
|
|
elseBlock.pop();
|
|
|
|
backend.emitLocalLabel(ln, "End of if expression");
|
|
|
|
backend.emitLocalLabel(ln, "End of if expression");
|
|
|
|
return A0;
|
|
|
|
return A0;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -495,9 +559,11 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
for(Stmt s:node.thenBody)
|
|
|
|
for(Stmt s:node.thenBody)
|
|
|
|
s.dispatch(this);
|
|
|
|
s.dispatch(this);
|
|
|
|
backend.emitJ(ln, "Jump to end of if statement");
|
|
|
|
backend.emitJ(ln, "Jump to end of if statement");
|
|
|
|
backend.emitLocalLabel(elseBlock, "Else part of if statement");
|
|
|
|
elseBlock.push(generateLocalLabel());
|
|
|
|
|
|
|
|
backend.emitLocalLabel(elseBlock.peek(), "Else part of if statement");
|
|
|
|
for(Stmt s:node.elseBody)
|
|
|
|
for(Stmt s:node.elseBody)
|
|
|
|
s.dispatch(this);
|
|
|
|
s.dispatch(this);
|
|
|
|
|
|
|
|
elseBlock.pop();
|
|
|
|
backend.emitLocalLabel(ln, "End of if statement");
|
|
|
|
backend.emitLocalLabel(ln, "End of if statement");
|
|
|
|
return null;
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -782,28 +848,36 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
backend.emitJAL(errorNI, "Operator not implemented");
|
|
|
|
backend.emitJAL(errorNI, "Operator not implemented");
|
|
|
|
return Register.A0;
|
|
|
|
return Register.A0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private SymbolInfo getSymbolInfo(Identifier id){
|
|
|
|
|
|
|
|
SymbolTable curr_sym = sym;
|
|
|
|
|
|
|
|
SymbolInfo info = null;
|
|
|
|
|
|
|
|
String id_name = id.name;
|
|
|
|
|
|
|
|
while(curr_sym != null){
|
|
|
|
|
|
|
|
info = (SymbolInfo) curr_sym.get(id_name);
|
|
|
|
|
|
|
|
if(info != null)
|
|
|
|
|
|
|
|
return info;
|
|
|
|
|
|
|
|
curr_sym = curr_sym.getParent();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return info;
|
|
|
|
|
|
|
|
}
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public Register analyze(Identifier node)
|
|
|
|
public Register analyze(Identifier node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
backend.emitLW(T6, FP, 0, "Inside Identifier: ");
|
|
|
|
backend.emitLW(T6, FP, 0, "Inside Identifier: ");
|
|
|
|
if (sym.getParent() == null)
|
|
|
|
|
|
|
|
{
|
|
|
|
Identifier targetID = (Identifier)node;
|
|
|
|
GlobalVarInfo gvi=(GlobalVarInfo) sym.get(node.name);
|
|
|
|
Object var = getVar(targetID);
|
|
|
|
backend.emitLW(Register.A0, gvi.getLabel(), "Load global: "+gvi.getVarName());
|
|
|
|
if(var instanceof StackVarRuntimeInfo){
|
|
|
|
|
|
|
|
StackVarRuntimeInfo rtinfo = (StackVarRuntimeInfo) var;
|
|
|
|
|
|
|
|
backend.emitLW(A0, rtinfo.sl, rtinfo.off,"Load local variable: "+node.name);
|
|
|
|
|
|
|
|
rtinfo.free();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
backend.emitLW(A0, (Label) var, "Load local variable: "+node.name);
|
|
|
|
backend.emitLW(Register.A0, SP, varSlotMap.get(node.name),"Load local variable: "+node.name);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return Register.A0;
|
|
|
|
return Register.A0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
|
|
|
public Register analyze(VarDef node)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public Register analyze(WhileStmt node)
|
|
|
|
public Register analyze(WhileStmt node)
|
|
|
@ -812,7 +886,7 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
Label startLoop = generateLocalLabel();
|
|
|
|
Label startLoop = generateLocalLabel();
|
|
|
|
backend.emitLocalLabel(startLoop, "Beginning of while loop");
|
|
|
|
backend.emitLocalLabel(startLoop, "Beginning of while loop");
|
|
|
|
Register result = node.condition.dispatch(this);
|
|
|
|
Register result = node.condition.dispatch(this);
|
|
|
|
Label endLoop = elseBlock;
|
|
|
|
Label endLoop = generateLocalLabel();
|
|
|
|
|
|
|
|
|
|
|
|
backend.emitBEQZ(result, endLoop,"Jump to end of the loop");
|
|
|
|
backend.emitBEQZ(result, endLoop,"Jump to end of the loop");
|
|
|
|
for(Stmt stmt:node.body)
|
|
|
|
for(Stmt stmt:node.body)
|
|
|
@ -900,13 +974,18 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
backend.emitMUL(iden, iden, ln, "Compute list element offset in bytes");
|
|
|
|
backend.emitMUL(iden, iden, ln, "Compute list element offset in bytes");
|
|
|
|
backend.emitADD(iden, l, iden, "Pointer to list element");
|
|
|
|
backend.emitADD(iden, l, iden, "Pointer to list element");
|
|
|
|
backend.emitLW(iden, iden, 0, "Set list element");
|
|
|
|
backend.emitLW(iden, iden, 0, "Set list element");
|
|
|
|
if(sym.getParent() == null)
|
|
|
|
SymbolInfo info = sym.get(node.identifier.name);
|
|
|
|
|
|
|
|
if(info instanceof GlobalVarInfo)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
GlobalVarInfo gvi=(GlobalVarInfo) sym.get(node.identifier.name);
|
|
|
|
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
|
|
|
|
backend.emitSW(iden, SP, varSlotMap.get(node.identifier.name),"Store local variable: "+node.identifier.name);
|
|
|
|
{
|
|
|
|
|
|
|
|
StackVarRuntimeInfo rtinfo = (StackVarRuntimeInfo) getVar(node.identifier);
|
|
|
|
|
|
|
|
backend.emitSW(iden, rtinfo.sl, rtinfo.off,"Store local variable: "+node.identifier.name);
|
|
|
|
|
|
|
|
rtinfo.free();
|
|
|
|
|
|
|
|
}
|
|
|
|
for(Stmt stmt:node.body)
|
|
|
|
for(Stmt stmt:node.body)
|
|
|
|
stmt.dispatch(this);
|
|
|
|
stmt.dispatch(this);
|
|
|
|
backend.emitADDI(iter, iter, 1, "Increment counter");
|
|
|
|
backend.emitADDI(iter, iter, 1, "Increment counter");
|
|
|
@ -938,14 +1017,18 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
|
|
|
|
|
|
|
|
backend.emitADDI(iden, iter, 4 * wordSize, "Convert index to offset to char in bytes");
|
|
|
|
backend.emitADDI(iden, iter, 4 * wordSize, "Convert index to offset to char in bytes");
|
|
|
|
backend.emitLBU(iden, iden, 0, "Load character");
|
|
|
|
backend.emitLBU(iden, iden, 0, "Load character");
|
|
|
|
|
|
|
|
SymbolInfo info = sym.get(node.identifier.name);
|
|
|
|
if(sym.getParent() == null)
|
|
|
|
if(info instanceof GlobalVarInfo)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
GlobalVarInfo gvi=(GlobalVarInfo) sym.get(node.identifier.name);
|
|
|
|
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
|
|
|
|
backend.emitSW(iden, SP, varSlotMap.get(node.identifier.name),"Store local variable: "+node.identifier.name);
|
|
|
|
{
|
|
|
|
|
|
|
|
StackVarRuntimeInfo rtinfo = (StackVarRuntimeInfo) getVar(node.identifier);
|
|
|
|
|
|
|
|
backend.emitSW(iden, rtinfo.sl, rtinfo.off,"Store local variable: "+node.identifier.name);
|
|
|
|
|
|
|
|
rtinfo.free();
|
|
|
|
|
|
|
|
}
|
|
|
|
for(Stmt stmt:node.body)
|
|
|
|
for(Stmt stmt:node.body)
|
|
|
|
stmt.dispatch(this);
|
|
|
|
stmt.dispatch(this);
|
|
|
|
backend.emitADDI(iter, iter, 1, "Increment counter");
|
|
|
|
backend.emitADDI(iter, iter, 1, "Increment counter");
|
|
|
|