Classes/Objects/Methods

This commit is contained in:
bill
2021-04-30 16:45:30 +08:00
parent 9f1681bb23
commit 9786fbbc69
89 changed files with 63620 additions and 11 deletions
+155 -11
View File
@@ -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.
}