|
|
@ -1,5 +1,6 @@
|
|
|
|
package chocopy.pa3;
|
|
|
|
package chocopy.pa3;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
@ -146,7 +147,6 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
varSlotMap.put(var.getVarName(), requiredStackSpace-emptySlotNum*wordSize);
|
|
|
|
varSlotMap.put(var.getVarName(), requiredStackSpace-emptySlotNum*wordSize);
|
|
|
|
emptySlotNum++;
|
|
|
|
emptySlotNum++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// --- Function Body ---
|
|
|
|
// --- Function Body ---
|
|
|
|
// statements load all the variables that caller put on stack
|
|
|
|
// statements load all the variables that caller put on stack
|
|
|
|
// statements use fp to load the variables
|
|
|
|
// statements use fp to load the variables
|
|
|
@ -208,9 +208,6 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
/** Label of code that exits from block. */
|
|
|
|
/** Label of code that exits from block. */
|
|
|
|
protected Label elseBlock;
|
|
|
|
protected Label elseBlock;
|
|
|
|
|
|
|
|
|
|
|
|
/** Variable to keep track of offsets of stored variables */
|
|
|
|
|
|
|
|
private Map<SymbolInfo, Integer> offsetMap = new HashMap<>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** 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
|
|
|
|
private Map<String, Integer> varSlotMap = new HashMap<>();
|
|
|
|
private Map<String, Integer> varSlotMap = new HashMap<>();
|
|
|
@ -223,7 +220,7 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
private int max_sp;
|
|
|
|
private int max_sp;
|
|
|
|
private final Register[] registerPool = {T2,T3, T4, T5, T6, A2, A3, A4, A5, A6};
|
|
|
|
private final Register[] registerPool = {T2,T3, T4, T5, T6, A2, A3, A4, A5, A6};
|
|
|
|
private final boolean[] registerAvilMap = {true, true, true, true, true, true, true, true, true, true};
|
|
|
|
private final boolean[] registerAvilMap = {true, true, true, true, true, true, true, true, true, true};
|
|
|
|
private int getRegister(){ //return a handle of a vacant reg
|
|
|
|
private int getRegister(){ //return a handle of a vacant register
|
|
|
|
for(int i = 0; i < 10; ++i)
|
|
|
|
for(int i = 0; i < 10; ++i)
|
|
|
|
if(registerAvilMap[i])
|
|
|
|
if(registerAvilMap[i])
|
|
|
|
return i;
|
|
|
|
return i;
|
|
|
@ -231,9 +228,10 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
registerAvilMap[i] = true; //freeall;
|
|
|
|
registerAvilMap[i] = true; //freeall;
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private void freeRegister(int handle){ //handle used to free the reg
|
|
|
|
private void freeRegister(int handle){ //handle used to free the register
|
|
|
|
registerAvilMap[handle] = false;
|
|
|
|
registerAvilMap[handle] = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* An analyzer for the function described by FUNCINFO0, which is null for the
|
|
|
|
* An analyzer for the function described by FUNCINFO0, which is null for the
|
|
|
|
* top level.
|
|
|
|
* top level.
|
|
|
@ -428,9 +426,9 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
{
|
|
|
|
{
|
|
|
|
System.out.println("Inside AssignStmt: ");
|
|
|
|
System.out.println("Inside AssignStmt: ");
|
|
|
|
backend.emitLW(T6, FP, 0, "Inside AssignStmt: ");
|
|
|
|
backend.emitLW(T6, FP, 0, "Inside AssignStmt: ");
|
|
|
|
Type t = node.value.getInferredType();
|
|
|
|
//Type t = node.value.getInferredType();
|
|
|
|
// if(t.isSpecialType() || t.isListType())
|
|
|
|
// if(t.isSpecialType() || t.isListType())
|
|
|
|
{
|
|
|
|
//{
|
|
|
|
Register reg = node.value.dispatch(this);
|
|
|
|
Register reg = node.value.dispatch(this);
|
|
|
|
if (reg == null)
|
|
|
|
if (reg == null)
|
|
|
|
reg = A0;
|
|
|
|
reg = A0;
|
|
|
@ -455,19 +453,18 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
for(Expr target: node.targets)
|
|
|
|
for(Expr target: node.targets)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
StackVarInfo svi = (StackVarInfo) sym.get(((Identifier)target).name);
|
|
|
|
StackVarInfo svi = (StackVarInfo) sym.get(((Identifier)target).name);
|
|
|
|
int loc = offsetMap.get(svi);
|
|
|
|
backend.emitLW(reg, SP, varSlotMap.get(svi.getVarName()),"Load local variable: "+svi.getVarName());
|
|
|
|
backend.emitSW(reg, Register.FP, -loc*4, "Load local variable: "+svi.getVarName());
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//}
|
|
|
|
return Register.A0;
|
|
|
|
return reg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public Register analyze(ExprStmt node)
|
|
|
|
public Register analyze(ExprStmt node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
System.out.println("Inside ExprStmt: ");
|
|
|
|
System.out.println("Inside ExprStmt: ");
|
|
|
|
backend.emitLW(T6, FP, 0, "Inside ExprStmt: ");
|
|
|
|
backend.emitLW(T6, FP, 0, "Inside ExprStmt: ");
|
|
|
|
node.expr.dispatch(this);
|
|
|
|
node.expr.dispatch(this);
|
|
|
|
return null;
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -479,7 +476,7 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
System.out.println("Inside IfExpr: ");
|
|
|
|
System.out.println("Inside IfExpr: ");
|
|
|
|
Register result = node.condition.dispatch(this);
|
|
|
|
Register result = node.condition.dispatch(this);
|
|
|
|
Label ln = generateLocalLabel();
|
|
|
|
Label ln = generateLocalLabel();
|
|
|
|
backend.emitBEQZ(result, ln,"Jump to beginning 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");
|
|
|
|
backend.emitLocalLabel(elseBlock, "Else part of if expression");
|
|
|
@ -491,12 +488,11 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public Register analyze(IfStmt node)
|
|
|
|
public Register analyze(IfStmt node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
System.out.println("Inside IfStmt: ");
|
|
|
|
System.out.println("Inside IfStmt: ");
|
|
|
|
Register result = node.condition.dispatch(this);
|
|
|
|
Register result = node.condition.dispatch(this);
|
|
|
|
|
|
|
|
|
|
|
|
Label ln = generateLocalLabel();
|
|
|
|
Label ln = generateLocalLabel();
|
|
|
|
backend.emitBEQZ(result, ln,"Jump to beginning of loop");
|
|
|
|
backend.emitBEQZ(result, ln,"Jump to end of loop");
|
|
|
|
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");
|
|
|
@ -573,7 +569,7 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public Register analyze(BinaryExpr node)
|
|
|
|
public Register analyze(BinaryExpr node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
System.out.println("Inside BinaryExpr: ");
|
|
|
|
System.out.println("Inside BinaryExpr: ");
|
|
|
|
String operator = node.operator;
|
|
|
|
String operator = node.operator;
|
|
|
|
backend.emitLW(T6, FP, 0, "Inside BinaryExpr: ");
|
|
|
|
backend.emitLW(T6, FP, 0, "Inside BinaryExpr: ");
|
|
|
|
|
|
|
|
|
|
|
@ -753,7 +749,7 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
backend.emitSEQZ(Register.T0, Register.A0, "Not operation on Register A0");
|
|
|
|
backend.emitSEQZ(Register.T0, Register.A0, "Not operation on Register A0");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
System.err.println("return null!");
|
|
|
|
backend.emitJAL(errorNI, "Operator not implemented");
|
|
|
|
return Register.A0;
|
|
|
|
return Register.A0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -768,22 +764,23 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// FIXME: This breaks, so had to comment it
|
|
|
|
VarInfo svi = (VarInfo) sym.get(node.name);
|
|
|
|
// VarInfo svi = (VarInfo) sym.get(node.name);
|
|
|
|
backend.emitLW(Register.A0, SP, varSlotMap.get(svi.getVarName()),"Load local variable: "+svi.getVarName());
|
|
|
|
// int loc = offsetMap.get(svi);
|
|
|
|
|
|
|
|
// backend.emitLW(Register.A0, Register.FP, -loc*4, "Load local variable: "+svi.getVarName());
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return A0;
|
|
|
|
return Register.A0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public Register analyze(VarDef node)
|
|
|
|
public Register analyze(VarDef node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
/*
|
|
|
|
StackVarInfo svi = (StackVarInfo) sym.get(node.var.identifier.name);
|
|
|
|
StackVarInfo svi = (StackVarInfo) sym.get(node.var.identifier.name);
|
|
|
|
node.value.dispatch(this);
|
|
|
|
node.value.dispatch(this);
|
|
|
|
backend.emitSW(Register.A0, Register.FP, -sp_off*wordSize, "Store variable "+node.var.identifier.name+" value in Stack");
|
|
|
|
backend.emitSW(Register.A0, Register.FP, -sp_off*wordSize, "Store variable "+node.var.identifier.name+" value in Stack");
|
|
|
|
|
|
|
|
varSlotMap.put(node.var.identifier.name, requiredStackSpace-emptySlotNum*wordSize);
|
|
|
|
|
|
|
|
|
|
|
|
offsetMap.put(svi, sp_off);
|
|
|
|
offsetMap.put(svi, sp_off);
|
|
|
|
incSp(1);
|
|
|
|
incSp(1);*/
|
|
|
|
return null;
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -842,22 +839,99 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public Register analyze(ForStmt node) {
|
|
|
|
public Register analyze(ForStmt node)
|
|
|
|
//System.out.println(node);
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
int r;
|
|
|
|
node.
|
|
|
|
List<Integer> regs= new ArrayList<Integer>();
|
|
|
|
Label startLoop = generateLocalLabel();
|
|
|
|
if (node.iterable.getInferredType().isListType())
|
|
|
|
backend.emitLocalLabel(startLoop, "Beginning of while loop");
|
|
|
|
{
|
|
|
|
node.condition.dispatch(this);
|
|
|
|
Label startLoop = generateLocalLabel();
|
|
|
|
Label endLoop = elseBlock;
|
|
|
|
Label endLoop = generateLocalLabel();
|
|
|
|
for(Stmt stmt:node.body)
|
|
|
|
r=getRegister();
|
|
|
|
stmt.dispatch(this);
|
|
|
|
regs.add(r);
|
|
|
|
backend.emitJ(startLoop, "Jump to beginning of loop");
|
|
|
|
Register iden = registerPool[r];
|
|
|
|
backend.emitLocalLabel(endLoop, "End of while loop");*/
|
|
|
|
node.iterable.dispatch(this);
|
|
|
|
|
|
|
|
r=getRegister();
|
|
|
|
|
|
|
|
regs.add(r);
|
|
|
|
|
|
|
|
Register l = registerPool[r];
|
|
|
|
|
|
|
|
r=getRegister();
|
|
|
|
|
|
|
|
regs.add(r);
|
|
|
|
|
|
|
|
Register ln = registerPool[r];
|
|
|
|
|
|
|
|
backend.emitMV(l,Register.A0,"Location of list");
|
|
|
|
|
|
|
|
r=getRegister();
|
|
|
|
|
|
|
|
regs.add(r);
|
|
|
|
|
|
|
|
Register iter = registerPool[r];
|
|
|
|
|
|
|
|
backend.emitMV(iter, Register.ZERO, "Initialize index variable");
|
|
|
|
|
|
|
|
backend.emitLocalLabel(startLoop, "Start for loop");
|
|
|
|
|
|
|
|
backend.emitLW(ln, l, getAttrOffset(listClass, "__len__"), "Get attribute __len__");
|
|
|
|
|
|
|
|
backend.emitBGE(iter, ln, endLoop, "Jump to end loop if counter exceeds length");
|
|
|
|
|
|
|
|
backend.emitADDI(iden, iter, 4, "Compute list element offset in words");
|
|
|
|
|
|
|
|
backend.emitLI(ln, wordSize, "Word size in bytes");
|
|
|
|
|
|
|
|
backend.emitMUL(iden, iden, ln, "Compute list element offset in bytes");
|
|
|
|
|
|
|
|
backend.emitADD(iden, l, iden, "Pointer to list element");
|
|
|
|
|
|
|
|
backend.emitLW(iden, iden, 0, "Set list element");
|
|
|
|
|
|
|
|
if(sym.getParent() == null)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
GlobalVarInfo gvi=(GlobalVarInfo) sym.get(node.identifier.name);
|
|
|
|
|
|
|
|
backend.emitSW(iden, gvi.getLabel(), Register.T0, "Assign global: "+node.identifier.name+"(using tmp register)");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
backend.emitSW(iden, SP, varSlotMap.get(node.identifier.name),"Store local variable: "+node.identifier.name);
|
|
|
|
|
|
|
|
for(Stmt stmt:node.body)
|
|
|
|
|
|
|
|
stmt.dispatch(this);
|
|
|
|
|
|
|
|
backend.emitADDI(iter, iter, 1, "Increment counter");
|
|
|
|
|
|
|
|
backend.emitJ(startLoop, "Jump to beginning of loop");
|
|
|
|
|
|
|
|
backend.emitLocalLabel(endLoop, "End of for loop");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (node.iterable.getInferredType().equals(Type.STR_TYPE))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
Label startLoop = generateLocalLabel();
|
|
|
|
|
|
|
|
Label endLoop = generateLocalLabel();
|
|
|
|
|
|
|
|
r=getRegister();
|
|
|
|
|
|
|
|
regs.add(r);
|
|
|
|
|
|
|
|
Register iden = registerPool[r];
|
|
|
|
|
|
|
|
node.iterable.dispatch(this);
|
|
|
|
|
|
|
|
r=getRegister();
|
|
|
|
|
|
|
|
regs.add(r);
|
|
|
|
|
|
|
|
Register l = registerPool[r];
|
|
|
|
|
|
|
|
r=getRegister();
|
|
|
|
|
|
|
|
regs.add(r);
|
|
|
|
|
|
|
|
Register ln = registerPool[r];
|
|
|
|
|
|
|
|
backend.emitMV(l,Register.A0,"Location of String");
|
|
|
|
|
|
|
|
r=getRegister();
|
|
|
|
|
|
|
|
regs.add(r);
|
|
|
|
|
|
|
|
Register iter = registerPool[r];
|
|
|
|
|
|
|
|
backend.emitMV(iter, Register.ZERO, "Initialize index variable");
|
|
|
|
|
|
|
|
backend.emitLocalLabel(startLoop, "Start for loop");
|
|
|
|
|
|
|
|
backend.emitLW(ln, l, getAttrOffset(strClass, "__len__"), "Get attribute __len__");
|
|
|
|
|
|
|
|
backend.emitBGE(iter, ln, endLoop, "Jump to end loop if counter exceeds length");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend.emitADDI(iden, iter, 4 * wordSize, "Convert index to offset to char in bytes");
|
|
|
|
|
|
|
|
backend.emitLBU(iden, iden, 0, "Load character");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(sym.getParent() == null)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
GlobalVarInfo gvi=(GlobalVarInfo) sym.get(node.identifier.name);
|
|
|
|
|
|
|
|
backend.emitSW(iden, gvi.getLabel(), Register.T0, "Assign global: "+node.identifier.name+"(using tmp register)");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
backend.emitSW(iden, SP, varSlotMap.get(node.identifier.name),"Store local variable: "+node.identifier.name);
|
|
|
|
|
|
|
|
for(Stmt stmt:node.body)
|
|
|
|
|
|
|
|
stmt.dispatch(this);
|
|
|
|
|
|
|
|
backend.emitADDI(iter, iter, 1, "Increment counter");
|
|
|
|
|
|
|
|
backend.emitJ(startLoop, "Jump to beginning of loop");
|
|
|
|
|
|
|
|
backend.emitLocalLabel(endLoop, "End of for loop");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
System.out.println("Iterable not a list or a string");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
for(int n:regs)
|
|
|
|
|
|
|
|
freeRegister(n);
|
|
|
|
return null;
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public Register analyze(IndexExpr node)
|
|
|
|
public Register analyze(IndexExpr node)
|
|
|
@ -870,7 +944,8 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
int tmpHandle = getRegister();
|
|
|
|
int tmpHandle = getRegister();
|
|
|
|
Register temp= registerPool[tmpHandle];
|
|
|
|
Register temp= registerPool[tmpHandle];
|
|
|
|
|
|
|
|
|
|
|
|
if (node.list.getInferredType().isListType()) {
|
|
|
|
if (node.list.getInferredType().isListType())
|
|
|
|
|
|
|
|
{
|
|
|
|
backend.emitLW(vacantReg, FP, -sp_off * wordSize, String.format("Pop stack slot %d", sp_off));
|
|
|
|
backend.emitLW(vacantReg, FP, -sp_off * wordSize, String.format("Pop stack slot %d", sp_off));
|
|
|
|
final Label bp = generateLocalLabel();
|
|
|
|
final Label bp = generateLocalLabel();
|
|
|
|
backend.emitBNEZ(listObj, bp, "Ensure not None");
|
|
|
|
backend.emitBNEZ(listObj, bp, "Ensure not None");
|
|
|
@ -886,7 +961,9 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
backend.emitMUL(index, index, temp, "Compute list element offset in bytes");
|
|
|
|
backend.emitMUL(index, index, temp, "Compute list element offset in bytes");
|
|
|
|
backend.emitADD(index, listObj, index, "Pointer to list element");
|
|
|
|
backend.emitADD(index, listObj, index, "Pointer to list element");
|
|
|
|
backend.emitLW(vacantReg, index, 0, "Set list element");
|
|
|
|
backend.emitLW(vacantReg, index, 0, "Set list element");
|
|
|
|
} else {
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
backend.emitLW(vacantReg, FP, - sp_off * wordSize, String.format("Peek stack slot %d", sp_off- 1));
|
|
|
|
backend.emitLW(vacantReg, FP, - sp_off * wordSize, String.format("Peek stack slot %d", sp_off- 1));
|
|
|
|
Label boundchk = generateLocalLabel();
|
|
|
|
Label boundchk = generateLocalLabel();
|
|
|
|
backend.emitLW(temp, vacantReg, getAttrOffset(strClass, "__len__"), "Load attribute: __len__");
|
|
|
|
backend.emitLW(temp, vacantReg, getAttrOffset(strClass, "__len__"), "Load attribute: __len__");
|
|
|
|