Merge branch 'bill/class' into apoorva/conditional
This commit is contained in:
@@ -13,36 +13,15 @@ import java.util.Map;
|
||||
|
||||
import chocopy.common.analysis.AbstractNodeAnalyzer;
|
||||
import chocopy.common.analysis.SymbolTable;
|
||||
import chocopy.common.analysis.types.Type;
|
||||
import chocopy.common.astnodes.AssignStmt;
|
||||
import chocopy.common.astnodes.BinaryExpr;
|
||||
import chocopy.common.astnodes.BooleanLiteral;
|
||||
import chocopy.common.astnodes.Expr;
|
||||
import chocopy.common.astnodes.ExprStmt;
|
||||
import chocopy.common.astnodes.ForStmt;
|
||||
import chocopy.common.astnodes.Identifier;
|
||||
import chocopy.common.astnodes.IfExpr;
|
||||
import chocopy.common.astnodes.IfStmt;
|
||||
import chocopy.common.astnodes.IndexExpr;
|
||||
import chocopy.common.astnodes.IntegerLiteral;
|
||||
import chocopy.common.astnodes.ListExpr;
|
||||
import chocopy.common.astnodes.ListType;
|
||||
import chocopy.common.astnodes.NoneLiteral;
|
||||
import chocopy.common.astnodes.ReturnStmt;
|
||||
import chocopy.common.astnodes.Stmt;
|
||||
import chocopy.common.astnodes.StringLiteral;
|
||||
import chocopy.common.astnodes.TypedVar;
|
||||
import chocopy.common.astnodes.UnaryExpr;
|
||||
import chocopy.common.astnodes.VarDef;
|
||||
import chocopy.common.astnodes.WhileStmt;
|
||||
import chocopy.common.codegen.CodeGenBase;
|
||||
import chocopy.common.codegen.FuncInfo;
|
||||
import chocopy.common.codegen.GlobalVarInfo;
|
||||
import chocopy.common.codegen.Label;
|
||||
import chocopy.common.codegen.RiscVBackend;
|
||||
import chocopy.common.codegen.StackVarInfo;
|
||||
import chocopy.common.astnodes.*;
|
||||
import chocopy.common.analysis.types.*;
|
||||
import chocopy.common.codegen.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import chocopy.common.codegen.RiscVBackend.Register;
|
||||
import chocopy.common.codegen.SymbolInfo;
|
||||
|
||||
/**
|
||||
* This is where the main implementation of PA3 will live.
|
||||
@@ -130,8 +109,7 @@ public class CodeGenImpl extends CodeGenBase
|
||||
}
|
||||
|
||||
/** An analyzer that encapsulates code generation for statements. */
|
||||
private class StmtAnalyzer extends AbstractNodeAnalyzer<Register>
|
||||
{
|
||||
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 use it as follows: SymbolInfo
|
||||
@@ -178,28 +156,67 @@ public class CodeGenImpl extends CodeGenBase
|
||||
* An analyzer for the function described by FUNCINFO0, which is null for the
|
||||
* top level.
|
||||
*/
|
||||
StmtAnalyzer(FuncInfo funcInfo0)
|
||||
{
|
||||
private final String size_label;
|
||||
private int sp_off, max_sp;
|
||||
/** Variable to store offset from frame pointer to identify next
|
||||
* empty space on stack frame to store variable*/
|
||||
|
||||
/** 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 Register 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");
|
||||
return null;
|
||||
private void incSp(int i){
|
||||
sp_off+=i+1;
|
||||
max_sp = max_sp >= sp_off?max_sp:sp_off;
|
||||
}
|
||||
|
||||
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));
|
||||
incSp(0);
|
||||
|
||||
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 A0;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Register analyze(NoneLiteral node)
|
||||
@@ -376,11 +393,7 @@ public class CodeGenImpl extends CodeGenBase
|
||||
offset++;
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public Register analyze(TypedVar node)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Register analyze(WhileStmt node)
|
||||
{
|
||||
@@ -430,29 +443,64 @@ public class CodeGenImpl extends CodeGenBase
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Register analyze(IndexExpr node) {
|
||||
System.out.println(node);
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
|
||||
return defaultAction(node);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Register analyze(ListType node) {
|
||||
System.out.println(node);
|
||||
return defaultAction(node);
|
||||
}
|
||||
Label label = generateLocalLabel();
|
||||
backend.emitBNEZ(obj, label, "Ensure not None");
|
||||
backend.emitJ(errorNone, "Go to error handler");
|
||||
backend.emitLocalLabel(label, "Not None");
|
||||
incSp(n_args+1);
|
||||
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;
|
||||
|
||||
return A0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Register analyze(ReturnStmt node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// FIXME: More, of course.
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user