Added more default functions
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
|
||||
addi sp, sp, -32
|
||||
sw ra, 28(sp)
|
||||
sw fp, 24(sp)
|
||||
addi fp, sp, 32
|
||||
sw s1, -12(fp)
|
||||
sw s2, -16(fp)
|
||||
sw s3, -20(fp)
|
||||
sw s4, -24(fp)
|
||||
sw s5, -28(fp)
|
||||
lw t0, 4(fp)
|
||||
lw t1, 0(fp)
|
||||
beqz t0, concat_none
|
||||
beqz t1, concat_none
|
||||
lw t0, @.__len__(t0)
|
||||
lw t1, @.__len__(t1)
|
||||
add s5, t0, t1
|
||||
addi a1, s5, @listHeaderWords
|
||||
la a0, $.list$prototype
|
||||
jal alloc2
|
||||
sw s5, @.__len__(a0)
|
||||
mv s5, a0
|
||||
addi s3, s5, @.__elts__
|
||||
lw s1, 4(fp)
|
||||
lw s2, @.__len__(s1)
|
||||
addi s1, s1, @.__elts__
|
||||
lw s4, 12(fp)
|
||||
concat_1:
|
||||
beqz s2, concat_2
|
||||
lw a0, 0(s1)
|
||||
jalr ra, s4, 0
|
||||
sw a0, 0(s3)
|
||||
addi s2, s2, -1
|
||||
addi s1, s1, 4
|
||||
addi s3, s3, 4
|
||||
j concat_1
|
||||
concat_2:
|
||||
lw s1, 0(fp)
|
||||
lw s2, @.__len__(s1)
|
||||
addi s1, s1, @.__elts__
|
||||
lw s4, 8(fp)
|
||||
concat_3:
|
||||
beqz s2, concat_4
|
||||
lw a0, 0(s1)
|
||||
jalr ra, s4, 0
|
||||
sw a0, 0(s3)
|
||||
addi s2, s2, -1
|
||||
addi s1, s1, 4
|
||||
addi s3, s3, 4
|
||||
j concat_3
|
||||
concat_4:
|
||||
mv a0, s5
|
||||
lw s1, -12(fp)
|
||||
lw s2, -16(fp)
|
||||
lw s3, -20(fp)
|
||||
lw s4, -24(fp)
|
||||
lw s5, -28(fp)
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 32
|
||||
jr ra
|
||||
concat_none:
|
||||
j error.None
|
||||
@@ -0,0 +1,27 @@
|
||||
|
||||
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
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
slli a0, a0, 4
|
||||
la t0, @bool.False
|
||||
add a0, a0, t0
|
||||
jr ra
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw a0, 0(sp)
|
||||
la a0, $int$prototype
|
||||
jal ra, alloc
|
||||
lw t0, 0(sp)
|
||||
sw t0, @.__int__(a0)
|
||||
lw ra, 4(sp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
@@ -0,0 +1,57 @@
|
||||
|
||||
addi sp, sp, -12
|
||||
sw ra, 8(sp)
|
||||
sw fp, 4(sp)
|
||||
addi fp, sp, 12
|
||||
lw t0, 4(fp)
|
||||
lw t1, 0(fp)
|
||||
lw t0, @.__len__(t0)
|
||||
beqz t0, strcat_4
|
||||
lw t1, @.__len__(t1)
|
||||
beqz t1, strcat_5
|
||||
add t1, t0, t1
|
||||
sw t1, -12(fp)
|
||||
addi t1, t1, 4
|
||||
srli t1, t1, 2
|
||||
addi a1, t1, @listHeaderWords
|
||||
la a0, $str$prototype
|
||||
jal alloc2
|
||||
lw t0, -12(fp)
|
||||
sw t0, @.__len__(a0)
|
||||
addi t2, a0, 16
|
||||
lw t0, 4(fp)
|
||||
lw t1, @.__len__(t0)
|
||||
addi t0, t0, @.__str__
|
||||
strcat_1:
|
||||
beqz t1, strcat_2
|
||||
lbu t3, 0(t0)
|
||||
sb t3, 0(t2)
|
||||
addi t1, t1, -1
|
||||
addi t0, t0, 1
|
||||
addi t2, t2, 1
|
||||
j strcat_1
|
||||
strcat_2:
|
||||
lw t0, 0(fp)
|
||||
lw t1, 12(t0)
|
||||
addi t0, t0, 16
|
||||
strcat_3:
|
||||
beqz t1, strcat_6
|
||||
lbu t3, 0(t0)
|
||||
sb t3, 0(t2)
|
||||
addi t1, t1, -1
|
||||
addi t0, t0, 1
|
||||
addi t2, t2, 1
|
||||
j strcat_3
|
||||
strcat_4:
|
||||
lw a0, 0(fp)
|
||||
j strcat_7
|
||||
strcat_5:
|
||||
lw a0, 4(fp)
|
||||
j strcat_7
|
||||
strcat_6:
|
||||
sb zero, 0(t2)
|
||||
strcat_7:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 12
|
||||
jr ra
|
||||
@@ -0,0 +1,27 @@
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 4(fp)
|
||||
lw a2, 0(fp)
|
||||
lw t0, @.__len__(a1)
|
||||
lw t1, @.__len__(a2)
|
||||
bne t0, t1, streql_no
|
||||
streql_1:
|
||||
lbu t2, @.__str__(a1)
|
||||
lbu t3, @.__str__(a2)
|
||||
bne t2, t3, streql_no
|
||||
addi a1, a1, 1
|
||||
addi a2, a2, 1
|
||||
addi t0, t0, -1
|
||||
bgtz t0, streql_1
|
||||
li a0, 1
|
||||
j streql_end
|
||||
streql_no:
|
||||
xor a0, a0, a0
|
||||
streql_end:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
@@ -0,0 +1,27 @@
|
||||
|
||||
addi sp, sp, -8
|
||||
sw ra, 4(sp)
|
||||
sw fp, 0(sp)
|
||||
addi fp, sp, 8
|
||||
lw a1, 4(fp)
|
||||
lw a2, 0(fp)
|
||||
lw t0, @.__len__(a1)
|
||||
lw t1, @.__len__(a2)
|
||||
bne t0, t1, strneql_yes
|
||||
strneql_1:
|
||||
lbu t2, @.__str__(a1)
|
||||
lbu t3, @.__str__(a2)
|
||||
bne t2, t3, strneql_yes
|
||||
addi a1, a1, 1
|
||||
addi a2, a2, 1
|
||||
addi t0, t0, -1
|
||||
bgtz t0, strneql_1
|
||||
xor a0, a0, a0
|
||||
j strneql_end
|
||||
strneql_yes:
|
||||
li a0, 1
|
||||
strneql_end:
|
||||
lw ra, -4(fp)
|
||||
lw fp, -8(fp)
|
||||
addi sp, sp, 8
|
||||
jr ra
|
||||
@@ -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. */
|
||||
|
||||
Reference in New Issue
Block a user