Added more default functions

This commit is contained in:
bill
2021-05-02 21:18:30 +08:00
parent b8600746cf
commit df398e608a
11 changed files with 329 additions and 131 deletions
+77 -130
View File
@@ -1,5 +1,6 @@
package chocopy.pa3;
import java.net.Socket;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -30,74 +31,17 @@ import chocopy.common.codegen.RiscVBackend.Register;
*/
public class CodeGenImpl extends CodeGenBase
{
/** Label for built-in routines. */
protected final Label makeintLabel = new Label("makeint");
protected final Label strneqlLablel = new Label("strneql");
protected final Label streqlLablel = new Label("streql");
protected final Label makeboolLablel = new Label("makebool");
protected final Label strcatLablel = new Label("strcat");
protected final Label concatLablel = new Label("concat");
protected final Label conslistLablel = new Label("conslist");
/** A code generator emitting instructions to BACKEND. */
public CodeGenImpl(RiscVBackend backend)
{
super(backend);
}
/**
* Generates assembly code for PROGRAM.
*
* <p>This is the main driver that calls internal methods for emitting DATA section (globals,
* constants, prototypes, etc) as well as the the CODE section (predefined functions, built-in
* routines, and user-defined functions).
*/
@Override
public void generate(Program program) {
System.out.println("Inside generate");
analyzeProgram(program);
backend.startData();
for (ClassInfo classInfo : this.classes) {
emitPrototype(classInfo);
}
for (ClassInfo classInfo : this.classes) {
emitDispatchTable(classInfo);
}
for (GlobalVarInfo global : this.globalVars) {
backend.emitGlobalLabel(global.getLabel());
emitConstant(
global.getInitialValue(),
global.getVarType(),
String.format("Initial value of global var: %s", global.getVarName()));
}
backend.startCode();
Label mainLabel = new Label("main");
backend.emitGlobalLabel(mainLabel);
backend.emitLUI(A0, HEAP_SIZE_BYTES >> 12, "Initialize heap size (in multiples of 4KB)");
backend.emitADD(S11, S11, A0, "Save heap size");
backend.emitJAL(heapInitLabel, "Call heap.init routine");
backend.emitMV(GP, A0, "Initialize heap pointer");
backend.emitMV(S10, GP, "Set beginning of heap");
backend.emitADD(S11, S10, S11, "Set end of heap (= start of heap + heap size)");
backend.emitMV(RA, ZERO, "No normal return from main program.");
backend.emitMV(FP, ZERO, "No preceding frame.");
emitTopLevel(program.statements);
for (FuncInfo funcInfo : this.functions) {
funcInfo.emitBody();
}
emitStdFunc("alloc");
emitStdFunc("alloc2");
emitStdFunc("abort");
emitStdFunc("heap.init");
emitStdFunc("makeint");
emitCustomCode();
backend.startData();
emitConstants();
}
/** Operation on None. */
private final Label errorNone = new Label("error.None");
@@ -106,12 +50,15 @@ public class CodeGenImpl extends CodeGenBase
/** Index out of bounds. */
private final Label errorOob = new Label("error.OOB");
/** Not implemented. */
/** Let's try to implement everything first.*/
private final Label errorNI = new Label("error.NI");
/** Label for built-in routine: makeint. */
protected final Label makeIntLabel = new Label("makeint");
/** A code generator emitting instructions to BACKEND. */
public CodeGenImpl(RiscVBackend backend)
{
super(backend);
}
/**
@@ -339,36 +286,6 @@ public class CodeGenImpl extends CodeGenBase
return A0;
}
@Override
public Register analyze(FuncDef node) {
backend.emitLW(T6, FP, 0, "Inside FuncDef: " + node.name);
// function
return null;
}
@Override
public Register analyze(GlobalDecl node) {
backend.emitLW(T6, FP, 0, "Inside GlobalDecl: ");
// function
return null;
}
@Override
public Register analyze(NonLocalDecl node) {
backend.emitLW(T6, FP, 0, "Inside NonLocalDecl: ");
// function
return null;
}
public Register analyze(MethodCallExpr node) {
backend.emitLW(T6, FP, 0, "Inside MethodCallExpr: " + node.method.member.name);
Register obj = node.method.object.dispatch(this);
@@ -411,6 +328,7 @@ public class CodeGenImpl extends CodeGenBase
// All expressions should save their end result in A0
expr.dispatch(this);
return A0;
}
@@ -435,15 +353,6 @@ public class CodeGenImpl extends CodeGenBase
return Register.A0;
}
// FIXME: This is not correct. We need to use $int$prototype to create an integer literal, so commenting it
// @Override
// public Register analyze(IntegerLiteral node)
// {
// backend.emitLI(Register.A0, node.value, "Load integer literal "+node.value);
// return Register.A0;
// }
@Override
public Register analyze(BooleanLiteral node)
{
@@ -454,21 +363,32 @@ public class CodeGenImpl extends CodeGenBase
backend.emitLI(Register.A0, 0, "Load boolean literal: false ");
return Register.A0;
}
@Override
public Register analyze(AssignStmt node)
{
backend.emitLW(T6, FP, 0, "Inside AssignStmt: ");
backend.emitLW(T6, FP, 0, "Inside AssignStmt: ");
Type t = node.value.getInferredType();
if(t.isSpecialType() || t.isListType())
// if(t.isSpecialType() || t.isListType())
{
node.value.dispatch(this);
Register reg = node.value.dispatch(this);
if (reg == null)
reg = A0;
if (sym.getParent() == null)
{
for(Expr target: node.targets)
{
GlobalVarInfo gvi=(GlobalVarInfo)sym.get(((Identifier)target).name);
backend.emitSW(Register.A0, gvi.getLabel(), Register.T0, "Assign global: "+gvi.getVarName()+"(using tmp register)");
if(target instanceof Identifier)
{
GlobalVarInfo gvi=(GlobalVarInfo)sym.get(((Identifier)target).name);
backend.emitSW(reg, gvi.getLabel(), Register.T0, "Assign global: "+gvi.getVarName()+"(using tmp register)");
}
else
{
Register ret = target.dispatch(this);
backend.emitSW(T1, ret, 0, "Set list element");
}
}
}
else
@@ -477,13 +397,9 @@ public class CodeGenImpl extends CodeGenBase
{
StackVarInfo svi = (StackVarInfo) sym.get(((Identifier)target).name);
int loc = offsetMap.get(svi);
backend.emitSW(Register.A0, Register.FP, -loc*4, "Load local variable: "+svi.getVarName());
backend.emitSW(reg, Register.FP, -loc*4, "Load local variable: "+svi.getVarName());
}
}
}
else
{//TODO: Object Assignment
}
return Register.A0;
}
@@ -506,7 +422,7 @@ public class CodeGenImpl extends CodeGenBase
backend.emitLocalLabel(elseBlock, "Else part of if expression");
node.elseExpr.dispatch(this);
backend.emitLocalLabel(ln, "End of if expression");
return null;
return A0;
}
@Override
@@ -601,9 +517,9 @@ public class CodeGenImpl extends CodeGenBase
}
else if(node.left.getInferredType().equals(Type.STR_TYPE) && node.right.getInferredType().equals(Type.STR_TYPE))
{
}
return null;
return A0;
}
@Override
@@ -695,7 +611,7 @@ public class CodeGenImpl extends CodeGenBase
public Register analyze(IntegerLiteral node) {
backend.emitLW(T6, FP, 0, "Inside IntegerLiteral: " + node.value);
backend.emitLI(A0, node.value, "Load integer literal " + node.value);
backend.emitJAL(makeIntLabel, "Box integer");
backend.emitJAL(makeintLabel, "Box integer");
// System.out.println("+++ Inside IntegerLiteral");
// backend.emitLA(A0, new Label("$int$prototype"), "Load prototype");
// backend.emitJAL(new Label("ra, alloc"), "");
@@ -723,12 +639,34 @@ public class CodeGenImpl extends CodeGenBase
}
@Override
public Register analyze(IndexExpr node)
{
//System.out.println(node);
return defaultAction(node);
}
@Override
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;
if (node.list.getInferredType().isListType()) {
backend.emitLW(vacantReg, FP, -sp_off * wordSize, String.format("Pop stack slot %d", sp_off));
this.d(vacantReg);
return this.a(vacantReg, index, A0, false);
}else{
this.a(0, vacantReg);
Register a = a(index);
Label ch = generateLocalLabel();
backend.emitLW(a, vacantReg, getAttrOffset(strClass, "__len__"), "Load attribute: __len__");
backend.emitBLTU(index, a, ch, "Ensure 0 <= idx < len");
backend.emitJ(f, "Go to error handler");
backend.emitLocalLabel(ch, "Index within bounds");
this.c(index);
Register a2 = this.a(false);
this.a(1);
return a2;
}
}
public Register analyze(MemberExpr node)
{
@@ -764,10 +702,19 @@ public class CodeGenImpl extends CodeGenBase
* to out-of-bounds error and abort");
*/
protected void emitCustomCode() {
emitStdFunc("concat");
emitStdFunc("conslist");
emitStdFunc("strcat");
emitStdFunc("streql");
emitStdFunc("strneql");
emitStdFunc("makeint");
emitStdFunc("makebool");
emitErrorFunc(errorNone, "Operation on None");
emitErrorFunc(errorDiv, "Division by zero");
emitErrorFunc(errorOob, "Index out of bounds");
emitErrorFunc(errorNI, "Not Implemented");
// emitErrorFunc(errorNI, "Not Implemented.");
}
/** Emit an error routine labeled ERRLABEL that aborts with message MSG. */