fixed conflicts

master
Sanjar Ahmadov 4 years ago
commit 0a5c6f1aa6

@ -1,20 +0,0 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "java",
"name": "Launch Current File",
"request": "launch",
"classPaths": ["chocopy-ref.jar:target/assignment.jar"],
"mainClass": "chocopy.ChocoPy",
//"args": [ "--pass=rrs", "--test","--dir", "src/test/data/pa3/sample/list_set_element_oob_1.py"],
"args": [ "--pass=rrs", "--test","--dir", "test.py"],
"sourcePaths": []
}
]
}

@ -1,3 +0,0 @@
{
"java.configuration.updateBuildConfiguration": "interactive"
}

@ -1,27 +0,0 @@
addi sp, sp, -8
sw ra, 4(sp)
sw fp, 0(sp)
addi fp, sp, 8
lw a1, 0(fp)
la a0, $.list$prototype
beqz a1, conslist_done
addi a1, a1, @listHeaderWords
jal alloc2
lw t0, 0(fp)
sw t0, @.__len__(a0)
slli t1, t0, 2
add t1, t1, fp
addi t2, a0, @.__elts__
conslist_1:
lw t3, 0(t1)
sw t3, 0(t2)
addi t1, t1, -4
addi t2, t2, 4
addi t0, t0, -1
bnez t0, conslist_1
conslist_done:
lw ra, -4(fp)
lw fp, -8(fp)
addi sp, sp, 8
jr ra

@ -1,18 +1,18 @@
package chocopy.pa3; package chocopy.pa3;
import java.net.Socket; 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.AbstractNodeAnalyzer; import chocopy.common.analysis.*;
import chocopy.common.analysis.SymbolTable;
import chocopy.common.astnodes.*; import chocopy.common.astnodes.*;
import chocopy.common.analysis.types.*; import chocopy.common.analysis.types.*;
import chocopy.common.codegen.*; import chocopy.common.codegen.*;
import static chocopy.common.codegen.RiscVBackend.Register.*;
import chocopy.common.codegen.RiscVBackend.Register; import chocopy.common.codegen.RiscVBackend.Register;
import static chocopy.common.codegen.RiscVBackend.Register.*;
/** /**
@ -33,12 +33,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");
@ -91,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);
} }
@ -148,7 +150,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
@ -157,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");
@ -208,11 +207,8 @@ 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 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,6 +219,19 @@ public class CodeGenImpl extends CodeGenBase
private int sp_off; private int sp_off;
/** Variable to store maximum possible offset depending on stack size.*/ /** Variable to store maximum possible offset depending on stack size.*/
private int max_sp; private int max_sp;
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 int getRegister(){ //return a handle of a vacant register
for(int i = 0; i < 10; ++i)
if(registerAvilMap[i])
return i;
for(int i = 0; i < 10; ++i)
registerAvilMap[i] = true; //freeall;
return 0;
}
private void freeRegister(int handle){ //handle used to free the register
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
@ -242,11 +251,13 @@ public class CodeGenImpl extends CodeGenBase
epilogue = generateLocalLabel(); epilogue = generateLocalLabel();
} }
private void incSp(int i){ private void incSp(int i){
sp_off+=i+1; sp_off+=i;
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 ***********
@ -255,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;
@ -276,7 +286,7 @@ public class CodeGenImpl extends CodeGenBase
String.format("Load pointer to prototype of: %s", cls.getClassName())); 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));
incSp(0); incSp(1);
backend.emitSW(A0, FP, -sp_off*wordSize, "Push argument 0 from last."); backend.emitSW(A0, FP, -sp_off*wordSize, "Push argument 0 from last.");
backend.emitADDI(SP, FP, sp_off, "Set SP to last argument."); backend.emitADDI(SP, FP, sp_off, "Set SP to last argument.");
@ -293,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;
@ -304,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
@ -347,8 +369,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));
@ -411,53 +436,95 @@ 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)
{ {
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;
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)
{ {
StackVarInfo svi = (StackVarInfo) sym.get(((Identifier)target).name); Register ret = target.dispatch(this);
int loc = offsetMap.get(svi); backend.emitSW(T1, ret, 0, "Set list element");
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;
} }
@ -469,11 +536,13 @@ 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"); 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;
} }
@ -481,18 +550,19 @@ 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");
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;
} }
@ -526,11 +596,11 @@ public class CodeGenImpl extends CodeGenBase
//Store address and length of lists on stack //Store address and length of lists on stack
backend.emitSW(Register.A0, Register.FP, -sp_off*wordSize, "Store address of first list"); backend.emitSW(Register.A0, Register.FP, -sp_off*wordSize, "Store address of first list");
sp_off++; incSp(1);
backend.emitSW(Register.T0, Register.FP, -sp_off*wordSize, "Store address of second list"); backend.emitSW(Register.T0, Register.FP, -sp_off*wordSize, "Store address of second list");
sp_off++; incSp(1);
backend.emitSW(Register.T3, Register.FP, -sp_off*wordSize, "Store length of combined list"); backend.emitSW(Register.T3, Register.FP, -sp_off*wordSize, "Store length of combined list");
sp_off++; incSp(1);
//Allocate space on heap //Allocate space on heap
backend.emitLA(Register.A0, listClass.getPrototypeLabel(), "Load empty list"); backend.emitLA(Register.A0, listClass.getPrototypeLabel(), "Load empty list");
@ -563,7 +633,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: ");
@ -571,7 +641,7 @@ public class CodeGenImpl extends CodeGenBase
{ {
node.right.dispatch(this); node.right.dispatch(this);
backend.emitSW(Register.A0, Register.FP, -sp_off*wordSize, "Push on stack slot "+sp_off); backend.emitSW(Register.A0, Register.FP, -sp_off*wordSize, "Push on stack slot "+sp_off);
sp_off++; incSp(1);
node.left.dispatch(this); node.left.dispatch(this);
sp_off--; sp_off--;
backend.emitLW(Register.T0, Register.FP, -sp_off*wordSize, "Pop stack slot "+sp_off); backend.emitLW(Register.T0, Register.FP, -sp_off*wordSize, "Pop stack slot "+sp_off);
@ -625,12 +695,13 @@ public class CodeGenImpl extends CodeGenBase
{ {
backend.emitADDI(Register.A0,Register.A0, 1, "Increment by 1"); backend.emitADDI(Register.A0,Register.A0, 1, "Increment by 1");
backend.emitSLT(Register.A0, Register.A0, Register.T0, comment); backend.emitSLT(Register.A0, Register.A0, Register.T0, comment);
} }
/* Maybe NA
else if(operator.equals("is")) else if(operator.equals("is"))
{ {
backend.emitXOR(Register.A0, Register.A0, Register.T0, comment); backend.emitXOR(Register.A0, Register.A0, Register.T0, comment);
backend.emitSEQZ(Register.A0, Register.A0, "Result is True if XOR equals 0"); backend.emitSEQZ(Register.A0, Register.A0, "Result is True if XOR equals 0");
} }*/
else else
{ {
backend.emitJAL(errorNI, "Operator not implemented for integer operands"); backend.emitJAL(errorNI, "Operator not implemented for integer operands");
@ -646,7 +717,7 @@ public class CodeGenImpl extends CodeGenBase
{ {
node.right.dispatch(this); node.right.dispatch(this);
backend.emitSW(Register.A0, Register.FP, -sp_off*wordSize, "Push on stack slot "+sp_off); backend.emitSW(Register.A0, Register.FP, -sp_off*wordSize, "Push on stack slot "+sp_off);
sp_off++; incSp(1);
node.left.dispatch(this); node.left.dispatch(this);
sp_off--; sp_off--;
backend.emitLW(Register.T0, Register.FP, -sp_off*wordSize, "Pop stack slot "+sp_off); backend.emitLW(Register.T0, Register.FP, -sp_off*wordSize, "Pop stack slot "+sp_off);
@ -657,7 +728,7 @@ public class CodeGenImpl extends CodeGenBase
{ {
node.right.dispatch(this); node.right.dispatch(this);
backend.emitSW(Register.A0, Register.FP, -sp_off*wordSize, "Push on stack slot "+sp_off); backend.emitSW(Register.A0, Register.FP, -sp_off*wordSize, "Push on stack slot "+sp_off);
sp_off++; incSp(1);
node.left.dispatch(this); node.left.dispatch(this);
sp_off--; sp_off--;
backend.emitLW(Register.T0, Register.FP, -sp_off*wordSize, "Pop stack slot "+sp_off); backend.emitLW(Register.T0, Register.FP, -sp_off*wordSize, "Pop stack slot "+sp_off);
@ -669,7 +740,7 @@ public class CodeGenImpl extends CodeGenBase
Label label = generateLocalLabel(); Label label = generateLocalLabel();
node.left.dispatch(this); node.left.dispatch(this);
backend.emitSW(Register.A0, Register.FP, -sp_off*wordSize, "Push on stack slot "+sp_off); backend.emitSW(Register.A0, Register.FP, -sp_off*wordSize, "Push on stack slot "+sp_off);
sp_off++; incSp(1);
backend.emitBEQZ(Register.A0, label, "If first operand is false, don't check second"); backend.emitBEQZ(Register.A0, label, "If first operand is false, don't check second");
node.right.dispatch(this); node.right.dispatch(this);
sp_off--; sp_off--;
@ -682,38 +753,90 @@ public class CodeGenImpl extends CodeGenBase
Label label = generateLocalLabel(); Label label = generateLocalLabel();
node.left.dispatch(this); node.left.dispatch(this);
backend.emitSW(Register.A0, Register.FP, -sp_off*wordSize, "Push on stack slot "+sp_off); backend.emitSW(Register.A0, Register.FP, -sp_off*wordSize, "Push on stack slot "+sp_off);
sp_off++; incSp(1);
backend.emitBNEZ(Register.A0, label, "If first operand is true, don't check second"); backend.emitBNEZ(Register.A0, label, "If first operand is true, don't check second");
node.right.dispatch(this); node.right.dispatch(this);
sp_off--; sp_off--;
backend.emitLW(Register.T0, Register.FP, -sp_off*wordSize, "Pop stack slot "+sp_off); backend.emitLW(Register.T0, Register.FP, -sp_off*wordSize, "Pop stack slot "+sp_off);
backend.emitOR(Register.A0, Register.A0, Register.T0, "OR operation"); backend.emitOR(Register.A0, Register.A0, Register.T0, "OR operation");
backend.emitLocalLabel(label, "Next step after OR"); backend.emitLocalLabel(label, "Next step after OR");
} }
/*Maybe NA
else if(operator.equals("is")) else if(operator.equals("is"))
{ {
backend.emitXOR(Register.A0, Register.A0, Register.T0, comment); backend.emitXOR(Register.A0, Register.A0, Register.T0, comment);
backend.emitSEQZ(Register.A0, Register.A0, "Result is True if XOR equals 0"); backend.emitSEQZ(Register.A0, Register.A0, "Result is True if XOR equals 0");
} }*/
else else
{ {
backend.emitJAL(errorNI, "Operator not implemented for boolean operands"); backend.emitJAL(errorNI, "Operator not implemented for boolean operands");
} }
} }
else if(node.left.getInferredType().isListType() && node.right.getInferredType().isListType()) else if(node.left.getInferredType().isListType() && node.right.getInferredType().isListType())
{
if(operator.equals("+"))
{
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))
{
if(operator.equals("=="))
{
incSp(2);
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.emitADDI(SP, FP, -sp_off * wordSize, "Set SP to last argument.");
backend.emitJAL(streqlLabel, "Invoke method:streql");
sp_off -= 2;
backend.emitADDI(SP, FP, -sp_off*wordSize, "restore sp");
}
else if(operator.equals("!="))
{
incSp(2);
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.emitADDI(SP, FP, -sp_off * wordSize, "Set SP to last argument.");
backend.emitJAL(strneqlLabel, "Invoke method:strneql");
sp_off -= 2;
backend.emitADDI(SP, FP, -sp_off*wordSize, "restore sp");
}
else if(operator.equals("+"))
{
incSp(2);
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.emitADDI(SP, FP, -sp_off * wordSize, "Set SP to last argument.");
backend.emitJAL(strcatLabel, "Invoke method:strcat");
sp_off -= 2;
backend.emitADDI(SP, FP, -sp_off*wordSize, "restore sp");
}
else
backend.emitJAL(errorNI, "Operator not implemented for String operands");
}
else if(operator.equals("is"))
{ {
node.right.dispatch(this); node.right.dispatch(this);
backend.emitSW(Register.A0, Register.FP, -sp_off*wordSize, "Push on stack slot "+sp_off); backend.emitSW(Register.A0, Register.FP, -sp_off*wordSize, "Push on stack slot "+sp_off);
sp_off++; incSp(1);
node.left.dispatch(this); node.left.dispatch(this);
sp_off--; sp_off--;
backend.emitLW(Register.T0, Register.FP, -sp_off*wordSize, "Pop stack slot "+sp_off); backend.emitLW(Register.T0, Register.FP, -sp_off*wordSize, "Pop stack slot "+sp_off);
if(operator.equals("+")) backend.emitXOR(Register.A0, Register.A0, Register.T0, "Operator: is");
addLists(); backend.emitSEQZ(Register.A0, Register.A0, "Result is True if XOR equals 0");
}
else if(node.left.getInferredType().equals(Type.STR_TYPE) && node.right.getInferredType().equals(Type.STR_TYPE))
{
} }
else else
{ {
@ -737,40 +860,40 @@ 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
return null; 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;
else backend.emitLW(A0, rtinfo.sl, rtinfo.off,"Load local variable: "+node.name);
{ rtinfo.free();
// FIXME: This breaks, so had to comment it
// VarInfo svi = (VarInfo) sym.get(node.name);
// int loc = offsetMap.get(svi);
// backend.emitLW(Register.A0, Register.FP, -loc*4, "Load local variable: "+svi.getVarName());
} }
return null; else
backend.emitLW(A0, (Label) var, "Load local variable: "+node.name);
return Register.A0;
} }
@Override
public Register analyze(VarDef node)
{
StackVarInfo svi = (StackVarInfo) sym.get(node.var.identifier.name);
node.value.dispatch(this);
backend.emitSW(Register.A0, Register.FP, -sp_off*wordSize, "Store variable "+node.var.identifier.name+" value in Stack");
offsetMap.put(svi, sp_off);
sp_off++;
return null;
}
@Override @Override
public Register analyze(WhileStmt node) public Register analyze(WhileStmt node)
{ {
@ -778,7 +901,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)
@ -792,25 +915,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;
} }
@ -826,52 +957,166 @@ 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");
SymbolInfo info = sym.get(node.identifier.name);
if(info instanceof GlobalVarInfo)
{
GlobalVarInfo gvi=(GlobalVarInfo) info;
backend.emitSW(iden, gvi.getLabel(), Register.T0, "Assign global: "+node.identifier.name+"(using tmp register)");
}
else
{
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)
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");
SymbolInfo info = sym.get(node.identifier.name);
if(info instanceof GlobalVarInfo)
{
GlobalVarInfo gvi=(GlobalVarInfo) info;
backend.emitSW(iden, gvi.getLabel(), Register.T0, "Assign global: "+node.identifier.name+"(using tmp register)");
}
else
{
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)
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)
{
incSp(1);
Register listObj = node.list.dispatch(this);
backend.emitSW(listObj, FP, -sp_off * wordSize, String.format("Push on stack slot %d", sp_off));
Register index = node.index.dispatch(this);
Register vacantReg = (index != A0) ? A0 : A1;
int tmpHandle = getRegister();
Register temp= registerPool[tmpHandle];
if (node.list.getInferredType().isListType())
{
backend.emitLW(vacantReg, FP, -sp_off * wordSize, String.format("Pop stack slot %d", sp_off));
final Label bp = generateLocalLabel();
backend.emitBNEZ(listObj, bp, "Ensure not None");
backend.emitJ(errorNone, "Go to error handler");
backend.emitLocalLabel(bp, "Not None");
final Label bt = generateLocalLabel();
backend.emitLW(temp, listObj, getAttrOffset(listClass, "__len__"), "Load attribute: __len__");
backend.emitBLTU(index, temp, bt, "Ensure 0 <= index < len");
backend.emitJ(errorOob, "Go to error handler");
backend.emitLocalLabel(bt, "Index within bounds");
backend.emitADDI(index, index, 4, "Compute list element offset in words");
backend.emitLI(temp, wordSize, "Word size in bytes");
backend.emitMUL(index, index, temp, "Compute list element offset in bytes");
backend.emitADD(index, listObj, index, "Pointer to list element");
backend.emitLW(vacantReg, index, 0, "Set list element");
}
else
{ {
// incSp(1); backend.emitLW(vacantReg, FP, - sp_off * wordSize, String.format("Peek stack slot %d", sp_off- 1));
// Register listObj = node.list.dispatch(this); Label boundchk = generateLocalLabel();
// backend.emitSW(listObj, FP, -sp_off * wordSize, String.format("Push on stack slot %d", sp_off)); backend.emitLW(temp, vacantReg, getAttrOffset(strClass, "__len__"), "Load attribute: __len__");
// Register index = node.index.dispatch(this); backend.emitBLTU(index, temp, boundchk, "Ensure 0 <= idx < len");
// Register vacantReg = (index != A0) ? A0 : A1; backend.emitJ(errorOob, "Go to error handler");
// backend.emitLocalLabel(boundchk, "Index within bounds");
// if (node.list.getInferredType().isListType()) { incSp(1);
// backend.emitLW(vacantReg, FP, -sp_off * wordSize, String.format("Pop stack slot %d", sp_off)); backend.emitSW(index, RiscVBackend.Register.FP, -sp_off * wordSize, String.format("Push on stack slot %d",sp_off));
//
// this.d(vacantReg); getAttrOffset(strClass, "__len__");
// return this.a(vacantReg, index, A0, false); backend.emitLW(T0, FP, -sp_off * wordSize, String.format("Pop stack slot %d", sp_off));
// }else{ --sp_off;
// this.a(0, vacantReg); backend.emitSW(A1, FP, -sp_off*wordSize, String.format("Push Argument %d", sp_off));
// Register a = a(index);
// Label ch = generateLocalLabel(); backend.emitADDI(T0, T0, 4 * wordSize, "Convert index to offset to char in bytes");
// backend.emitLW(a, vacantReg, getAttrOffset(strClass, "__len__"), "Load attribute: __len__"); backend.emitLBU(T0, T0, 0, "Load character");
// backend.emitBLTU(index, a, ch, "Ensure 0 <= idx < len"); backend.emitLA(vacantReg, strClass.getPrototypeLabel(), "Create Str for char");
// backend.emitJ(f, "Go to error handler"); backend.emitJAL(objectAllocLabel, "Alloc char");
// backend.emitLocalLabel(ch, "Index within bounds"); backend.emitLI(T1, 1, "str size");
// this.c(index); backend.emitSW(T1, vacantReg, 3*wordSize, "len");
// Register a2 = this.a(false); backend.emitSW(T0, vacantReg, 4*wordSize, "ch");
// this.a(1);
// return a2;
// }
return null;
} }
freeRegister(tmpHandle);
-- sp_off;
return vacantReg;
}
public Register analyze(MemberExpr node) public Register analyze(MemberExpr node)
{ {

Loading…
Cancel
Save