|
|
@ -5,14 +5,13 @@ import java.util.HashMap;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.Map;
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
|
|
|
|
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.*;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
@ -207,7 +206,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 reg
|
|
|
|
|
|
|
|
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 reg
|
|
|
|
|
|
|
|
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.
|
|
|
@ -226,7 +237,7 @@ 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -257,7 +268,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.");
|
|
|
@ -687,7 +698,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
|
|
|
|
return null;
|
|
|
|
System.err.println("return null!");
|
|
|
|
return Register.A0;
|
|
|
|
return Register.A0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -792,31 +803,56 @@ public class CodeGenImpl extends CodeGenBase
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public Register analyze(IndexExpr node)
|
|
|
|
public Register analyze(IndexExpr node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// incSp(1);
|
|
|
|
incSp(1);
|
|
|
|
// Register listObj = node.list.dispatch(this);
|
|
|
|
Register listObj = node.list.dispatch(this);
|
|
|
|
// backend.emitSW(listObj, FP, -sp_off * wordSize, String.format("Push on stack slot %d", sp_off));
|
|
|
|
backend.emitSW(listObj, FP, -sp_off * wordSize, String.format("Push on stack slot %d", sp_off));
|
|
|
|
// Register index = node.index.dispatch(this);
|
|
|
|
Register index = node.index.dispatch(this);
|
|
|
|
// Register vacantReg = (index != A0) ? A0 : A1;
|
|
|
|
Register vacantReg = (index != A0) ? A0 : A1;
|
|
|
|
//
|
|
|
|
int tmpHandle = getRegister();
|
|
|
|
// if (node.list.getInferredType().isListType()) {
|
|
|
|
Register temp= registerPool[tmpHandle];
|
|
|
|
// backend.emitLW(vacantReg, FP, -sp_off * wordSize, String.format("Pop stack slot %d", sp_off));
|
|
|
|
|
|
|
|
//
|
|
|
|
if (node.list.getInferredType().isListType()) {
|
|
|
|
// this.d(vacantReg);
|
|
|
|
backend.emitLW(vacantReg, FP, -sp_off * wordSize, String.format("Pop stack slot %d", sp_off));
|
|
|
|
// return this.a(vacantReg, index, A0, false);
|
|
|
|
final Label bp = generateLocalLabel();
|
|
|
|
// }else{
|
|
|
|
backend.emitBNEZ(listObj, bp, "Ensure not None");
|
|
|
|
// this.a(0, vacantReg);
|
|
|
|
backend.emitJ(errorNone, "Go to error handler");
|
|
|
|
// Register a = a(index);
|
|
|
|
backend.emitLocalLabel(bp, "Not None");
|
|
|
|
// Label ch = generateLocalLabel();
|
|
|
|
final Label bt = generateLocalLabel();
|
|
|
|
// backend.emitLW(a, vacantReg, getAttrOffset(strClass, "__len__"), "Load attribute: __len__");
|
|
|
|
backend.emitLW(temp, listObj, getAttrOffset(listClass, "__len__"), "Load attribute: __len__");
|
|
|
|
// backend.emitBLTU(index, a, ch, "Ensure 0 <= idx < len");
|
|
|
|
backend.emitBLTU(index, temp, bt, "Ensure 0 <= index < len");
|
|
|
|
// backend.emitJ(f, "Go to error handler");
|
|
|
|
backend.emitJ(errorOob, "Go to error handler");
|
|
|
|
// backend.emitLocalLabel(ch, "Index within bounds");
|
|
|
|
backend.emitLocalLabel(bt, "Index within bounds");
|
|
|
|
// this.c(index);
|
|
|
|
backend.emitADDI(index, index, 4, "Compute list element offset in words");
|
|
|
|
// Register a2 = this.a(false);
|
|
|
|
backend.emitLI(temp, wordSize, "Word size in bytes");
|
|
|
|
// this.a(1);
|
|
|
|
backend.emitMUL(index, index, temp, "Compute list element offset in bytes");
|
|
|
|
// return a2;
|
|
|
|
backend.emitADD(index, listObj, index, "Pointer to list element");
|
|
|
|
// }
|
|
|
|
backend.emitLW(vacantReg, index, 0, "Set list element");
|
|
|
|
return null;
|
|
|
|
} else {
|
|
|
|
|
|
|
|
backend.emitLW(vacantReg, FP, - sp_off * wordSize, String.format("Peek stack slot %d", sp_off- 1));
|
|
|
|
|
|
|
|
Label boundchk = generateLocalLabel();
|
|
|
|
|
|
|
|
backend.emitLW(temp, vacantReg, getAttrOffset(strClass, "__len__"), "Load attribute: __len__");
|
|
|
|
|
|
|
|
backend.emitBLTU(index, temp, boundchk, "Ensure 0 <= idx < len");
|
|
|
|
|
|
|
|
backend.emitJ(errorOob, "Go to error handler");
|
|
|
|
|
|
|
|
backend.emitLocalLabel(boundchk, "Index within bounds");
|
|
|
|
|
|
|
|
incSp(1);
|
|
|
|
|
|
|
|
backend.emitSW(index, RiscVBackend.Register.FP, -sp_off * wordSize, String.format("Push on stack slot %d",sp_off));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getAttrOffset(strClass, "__len__");
|
|
|
|
|
|
|
|
backend.emitLW(T0, FP, -sp_off * wordSize, String.format("Pop stack slot %d", sp_off));
|
|
|
|
|
|
|
|
--sp_off;
|
|
|
|
|
|
|
|
backend.emitSW(A1, FP, -sp_off*wordSize, String.format("Push Argument %d", sp_off));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend.emitADDI(T0, T0, 4 * wordSize, "Convert index to offset to char in bytes");
|
|
|
|
|
|
|
|
backend.emitLBU(T0, T0, 0, "Load character");
|
|
|
|
|
|
|
|
backend.emitLA(vacantReg, strClass.getPrototypeLabel(), "Create Str for char");
|
|
|
|
|
|
|
|
backend.emitJAL(objectAllocLabel, "Alloc char");
|
|
|
|
|
|
|
|
backend.emitLI(T1, 1, "str size");
|
|
|
|
|
|
|
|
backend.emitSW(T1, vacantReg, 3*wordSize, "len");
|
|
|
|
|
|
|
|
backend.emitSW(T0, vacantReg, 4*wordSize, "ch");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
freeRegister(tmpHandle);
|
|
|
|
|
|
|
|
-- sp_off;
|
|
|
|
|
|
|
|
return vacantReg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public Register analyze(MemberExpr node)
|
|
|
|
public Register analyze(MemberExpr node)
|
|
|
|