Classes/Objects/Methods
This commit is contained in:
@@ -2,12 +2,14 @@ package chocopy.pa3;
|
||||
|
||||
import chocopy.common.analysis.AbstractNodeAnalyzer;
|
||||
import chocopy.common.analysis.SymbolTable;
|
||||
import chocopy.common.astnodes.ReturnStmt;
|
||||
import chocopy.common.astnodes.Stmt;
|
||||
import chocopy.common.analysis.types.FuncType;
|
||||
import chocopy.common.analysis.types.Type;
|
||||
import chocopy.common.astnodes.*;
|
||||
import chocopy.common.codegen.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import chocopy.common.codegen.RiscVBackend.Register;
|
||||
import static chocopy.common.codegen.RiscVBackend.Register.*;
|
||||
|
||||
/**
|
||||
@@ -84,7 +86,7 @@ public class CodeGenImpl extends CodeGenBase {
|
||||
}
|
||||
|
||||
/** An analyzer that encapsulates code generation for statements. */
|
||||
private class StmtAnalyzer extends AbstractNodeAnalyzer<Void> {
|
||||
private class StmtAnalyzer extends AbstractNodeAnalyzer<Register> {
|
||||
/*
|
||||
* The symbol table has all the info you need to determine
|
||||
* what a given identifier 'x' in the current scope is. You can
|
||||
@@ -124,29 +126,171 @@ public class CodeGenImpl extends CodeGenBase {
|
||||
|
||||
/** The descriptor for the current function, or null at the top level. */
|
||||
private final FuncInfo funcInfo;
|
||||
private final String size_label;
|
||||
private int sp_off, max_sp;
|
||||
|
||||
/** An analyzer for the function described by FUNCINFO0, which is null for the top level. */
|
||||
StmtAnalyzer(FuncInfo funcInfo0) {
|
||||
funcInfo = funcInfo0;
|
||||
if (funcInfo == null) {
|
||||
sym = globalSymbols;
|
||||
sp_off = max_sp = 2;
|
||||
size_label = "@..main.size";
|
||||
} else {
|
||||
sym = funcInfo.getSymbolTable();
|
||||
sp_off = max_sp = funcInfo0.getLocals().size() + 2;
|
||||
size_label = "@"+funcInfo0.getFuncName()+".size";
|
||||
}
|
||||
epilogue = generateLocalLabel();
|
||||
}
|
||||
|
||||
// FIXME: Example of statement.
|
||||
@Override
|
||||
public Void analyze(ReturnStmt stmt) {
|
||||
// FIXME: Here, we emit an instruction that does nothing. Clearly,
|
||||
// this is wrong, and you'll have to fix it.
|
||||
// This is here just to demonstrate how to emit a
|
||||
// RISC-V instruction.
|
||||
backend.emitMV(ZERO, ZERO, "No-op");
|
||||
public Register analyze(AssignStmt node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Register analyze(BinaryExpr node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Register analyze(BooleanLiteral node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Register analyze(CallExpr node) {
|
||||
SymbolInfo Ty = globalSymbols.get(node.function.name);
|
||||
if(Ty instanceof ClassInfo){
|
||||
//object create
|
||||
ClassInfo cls = (ClassInfo) Ty;
|
||||
/**
|
||||
la a0, $DoublingVector$prototype # Load pointer to prototype of: DoublingVector
|
||||
jal alloc # Allocate new object in A0
|
||||
sw a0, -12(fp) # Push on stack slot 3
|
||||
sw a0, -16(fp) # Push argument 0 from last.
|
||||
addi sp, fp, -16 # Set SP to last argument.
|
||||
lw a1, 8(a0) # Load address of object's dispatch table
|
||||
lw a1, 0(a1) # Load address of method: DoublingVector.__init__
|
||||
jalr a1 # Invoke method: DoublingVector.__init__
|
||||
addi sp, fp, -@..main.size # Set SP to stack frame top.
|
||||
lw a0, -12(fp) # Pop stack slot 3
|
||||
*/
|
||||
backend.emitLA(A0, cls.getPrototypeLabel(),
|
||||
String.format("Load pointer to prototype of: %s", cls.getClassName()));
|
||||
backend.emitJAL(objectAllocLabel, "Allocate new object in A0");
|
||||
backend.emitSW(A0, FP, -sp_off*wordSize, String.format("Push on stack slot %d", sp_off));
|
||||
if(sp_off>max_sp)
|
||||
max_sp = sp_off;
|
||||
sp_off++;
|
||||
backend.emitSW(A0, FP, -sp_off*wordSize, "Push argument 0 from last.");
|
||||
backend.emitADDI(SP, FP, sp_off, "Set SP to last argument.");
|
||||
backend.emitLW(A1, A0, getDispatchTableOffset(), "Load address of object's dispatch table");
|
||||
backend.emitLW(A1, A1, getMethodOffset(cls, "__init__"), String.format("Load address of method: %s.__init__", cls.getClassName()));
|
||||
backend.emitJALR(A1, String.format("Invoke method: %s.__init", cls.getClassName()));
|
||||
backend.emitADDI(SP, FP, "-"+size_label, "Set SP to stack frame top.");
|
||||
sp_off--;
|
||||
backend.emitLW(A0, FP, -sp_off*wordSize, String.format("Pop stack slot %d", sp_off));
|
||||
} else {
|
||||
//func call
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Register analyze(ExprStmt node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Register analyze(ForStmt node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Register analyze(Identifier node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Register analyze(IfExpr node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Register analyze(IfStmt node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Register analyze(IndexExpr node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Register analyze(IntegerLiteral node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Register analyze(ListExpr node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Register analyze(MemberExpr node) {
|
||||
ClassInfo objectClass = (ClassInfo) globalSymbols.get(node.object.getInferredType().className());
|
||||
Label label = generateLocalLabel();
|
||||
Register obj = node.object.dispatch(this);
|
||||
|
||||
backend.emitBNEZ(obj, label, "Ensure not None");
|
||||
backend.emitJ(errorNone, "Go to error handler");
|
||||
backend.emitLocalLabel(label, "Not None");
|
||||
backend.emitLW(A0, obj, getAttrOffset(objectClass, node.member.name),
|
||||
String.format("Get attribute: %s.%s", objectClass.getClassName(), node.member.name));
|
||||
return A0;
|
||||
}
|
||||
|
||||
public Register analyze(MethodCallExpr node) {
|
||||
Register obj = node.method.object.dispatch(this);
|
||||
int n_args = node.args.size();
|
||||
|
||||
Label label = generateLocalLabel();
|
||||
backend.emitBNEZ(obj, label, "Ensure not None");
|
||||
backend.emitJ(errorNone, "Go to error handler");
|
||||
backend.emitLocalLabel(label, "Not None");
|
||||
if(sp_off>max_sp)
|
||||
max_sp = sp_off;
|
||||
sp_off += (n_args+1)*wordSize;
|
||||
backend.emitSW(obj, FP, (n_args - sp_off) *wordSize, String.format("Push argument %d from last.", n_args));
|
||||
|
||||
for (int i = 0; i < n_args; ++i)
|
||||
backend.emitSW(node.args.get(i).dispatch(this), FP, (n_args - i - 1 - sp_off) * wordSize,
|
||||
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)));
|
||||
ClassInfo objectClass = (ClassInfo)sym.get(((Identifier)node.method.object).name);
|
||||
|
||||
backend.emitLW(A1, A0, getDispatchTableOffset(), "Load address of object's dispatch table");
|
||||
backend.emitLW(A1, A1, getMethodOffset(objectClass, node.method.member.name),
|
||||
String.format("Load address of method: %s.%s", objectClass.getClassName(), node.method.member.name));
|
||||
backend.emitADDI(SP, FP, -sp_off * wordSize, "Set SP to last argument.");
|
||||
backend.emitJALR(A1, String.format("Invoke method: %s.%s", objectClass.getClassName(), node.method.member.name));
|
||||
backend.emitInsn(String.format("addi sp, fp, -%s", size_label), "Set SP to stack frame top.");
|
||||
sp_off -= (n_args+1)*wordSize;
|
||||
|
||||
return A0;
|
||||
}
|
||||
|
||||
public Register analyze(NoneLiteral node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Register analyze(ReturnStmt node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Register analyze(StringLiteral node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Register analyze(UnaryExpr node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Register analyze(WhileStmt node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// FIXME: More, of course.
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user