diff --git a/src/main/java/chocopy/pa3/CodeGenImpl.java b/src/main/java/chocopy/pa3/CodeGenImpl.java index 47a31c8..88dfde0 100644 --- a/src/main/java/chocopy/pa3/CodeGenImpl.java +++ b/src/main/java/chocopy/pa3/CodeGenImpl.java @@ -4,22 +4,38 @@ import chocopy.common.analysis.AbstractNodeAnalyzer; import chocopy.common.analysis.SymbolTable; import chocopy.common.astnodes.ReturnStmt; import chocopy.common.astnodes.Stmt; +import chocopy.common.astnodes.StringLiteral; +import chocopy.common.astnodes.AssignStmt; +import chocopy.common.astnodes.BinaryExpr; +import chocopy.common.astnodes.BooleanLiteral; +import chocopy.common.astnodes.Expr; +import chocopy.common.astnodes.Identifier; +import chocopy.common.astnodes.IntegerLiteral; +import chocopy.common.astnodes.Literal; import chocopy.common.codegen.*; +import chocopy.common.codegen.Label; +import chocopy.common.codegen.RiscVBackend.Register; import java.util.List; + +import chocopy.common.analysis.types.Type; + import static chocopy.common.codegen.RiscVBackend.Register.*; /** * This is where the main implementation of PA3 will live. * - *

A large part of the functionality has already been implemented in the base class, CodeGenBase. - * Make sure to read through that class, since you will want to use many of its fields and utility - * methods in this class when emitting code. + *

+ * A large part of the functionality has already been implemented in the base + * class, CodeGenBase. Make sure to read through that class, since you will want + * to use many of its fields and utility methods in this class when emitting + * code. * - *

Also read the PDF spec for details on what the base class does and what APIs it exposes for - * its sub-class (this one). Of particular importance is knowing what all the SymbolInfo classes - * contain. + *

+ * Also read the PDF spec for details on what the base class does and what APIs + * it exposes for its sub-class (this one). Of particular importance is knowing + * what all the SymbolInfo classes contain. */ public class CodeGenImpl extends CodeGenBase { @@ -38,17 +54,19 @@ public class CodeGenImpl extends CodeGenBase { /** * Emits the top level of the program. * - *

This method is invoked exactly once, and is surrounded by some boilerplate code that: (1) - * initializes the heap before the top-level begins and (2) exits after the top-level ends. + *

+ * This method is invoked exactly once, and is surrounded by some boilerplate + * code that: (1) initializes the heap before the top-level begins and (2) exits + * after the top-level ends. * - *

You only need to generate code for statements. + *

+ * You only need to generate code for statements. * * @param statements top level statements */ protected void emitTopLevel(List statements) { StmtAnalyzer stmtAnalyzer = new StmtAnalyzer(null); - backend.emitADDI( - SP, SP, -2 * backend.getWordSize(), "Saved FP and saved RA (unused at top level)."); + backend.emitADDI(SP, SP, -2 * backend.getWordSize(), "Saved FP and saved RA (unused at top level)."); backend.emitSW(ZERO, SP, 0, "Top saved FP is 0."); backend.emitSW(ZERO, SP, 4, "Top saved RA is 0."); backend.emitADDI(FP, SP, 2 * backend.getWordSize(), "Set FP to previous SP."); @@ -63,10 +81,11 @@ public class CodeGenImpl extends CodeGenBase { /** * Emits the code for a function described by FUNCINFO. * - *

This method is invoked once per function and method definition. At the code generation - * stage, nested functions are emitted as separate functions of their own. So if function `bar` - * is nested within function `foo`, you only emit `foo`'s code for `foo` and only emit `bar`'s - * code for `bar`. + *

+ * This method is invoked once per function and method definition. At the code + * generation stage, nested functions are emitted as separate functions of their + * own. So if function `bar` is nested within function `foo`, you only emit + * `foo`'s code for `foo` and only emit `bar`'s code for `bar`. */ protected void emitUserDefinedFunction(FuncInfo funcInfo) { backend.emitGlobalLabel(funcInfo.getCodeLabel()); @@ -86,34 +105,30 @@ public class CodeGenImpl extends CodeGenBase { /** An analyzer that encapsulates code generation for statements. */ private class StmtAnalyzer extends AbstractNodeAnalyzer { /* - * 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 x = sym.get("x"); + * 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 + * x = sym.get("x"); * - * A SymbolInfo can be one the following: - * - ClassInfo: a descriptor for classes - * - FuncInfo: a descriptor for functions/methods - * - AttrInfo: a descriptor for attributes - * - GlobalVarInfo: a descriptor for global variables - * - StackVarInfo: a descriptor for variables allocated on the stack, - * such as locals and parameters + * A SymbolInfo can be one the following: - ClassInfo: a descriptor for classes + * - FuncInfo: a descriptor for functions/methods - AttrInfo: a descriptor for + * attributes - GlobalVarInfo: a descriptor for global variables - StackVarInfo: + * a descriptor for variables allocated on the stack, such as locals and + * parameters * - * Since the input program is assumed to be semantically - * valid and well-typed at this stage, you can always assume that - * the symbol table contains valid information. For example, in - * an expression `foo()` you KNOW that sym.get("foo") will either be - * a FuncInfo or ClassInfo, but not any of the other infos - * and never null. + * Since the input program is assumed to be semantically valid and well-typed at + * this stage, you can always assume that the symbol table contains valid + * information. For example, in an expression `foo()` you KNOW that + * sym.get("foo") will either be a FuncInfo or ClassInfo, but not any of the + * other infos and never null. * - * The symbol table in funcInfo has already been populated in - * the base class: CodeGenBase. You do not need to add anything to - * the symbol table. Simply query it with an identifier name to - * get a descriptor for a function, class, variable, etc. + * The symbol table in funcInfo has already been populated in the base class: + * CodeGenBase. You do not need to add anything to the symbol table. Simply + * query it with an identifier name to get a descriptor for a function, class, + * variable, etc. * - * The symbol table also maps nonlocal and global vars, so you - * only need to lookup one symbol table and it will fetch the - * appropriate info for the var that is currently in scope. + * The symbol table also maps nonlocal and global vars, so you only need to + * lookup one symbol table and it will fetch the appropriate info for the var + * that is currently in scope. */ /** Symbol table for my statements. */ @@ -125,7 +140,10 @@ public class CodeGenImpl extends CodeGenBase { /** The descriptor for the current function, or null at the top level. */ private final FuncInfo funcInfo; - /** An analyzer for the function described by FUNCINFO0, which is null for the top level. */ + /** + * An analyzer for the function described by FUNCINFO0, which is null for the + * top level. + */ StmtAnalyzer(FuncInfo funcInfo0) { funcInfo = funcInfo0; if (funcInfo == null) { @@ -148,6 +166,56 @@ public class CodeGenImpl extends CodeGenBase { } // FIXME: More, of course. + @Override + public Void analyze(AssignStmt node) { + if (sym.getParent() == null) { + Type t = node.value.getInferredType(); + for(Expr target: node.targets) + { + + GlobalVarInfo gvi=(GlobalVarInfo)sym.get(((Identifier)target).name); + if(t==Type.INT_TYPE) + { + IntegerLiteral lt = (IntegerLiteral)node.value; + backend.emitLI(Register.A0, lt.value, "Load integer literal "+lt.value); + } + else if(t==Type.BOOL_TYPE) + { + BooleanLiteral lt = (BooleanLiteral)node.value; + if(lt.value==true) + backend.emitLI(Register.A0, 1, "Load boolean literal "+1); + else + backend.emitLI(Register.A0, 0, "Load boolean literal "+0); + } + else + { + StringLiteral lt = (StringLiteral)node.value; + System.out.println(strClass.getClassName()+" "+strClass.getTypeTag()+" "+strClass.getDispatchTableLabel().labelName); + Label l = constants.getStrConstant(lt.value); + backend.emitLA(Register.A0, l, "Load string literal"); + } + backend.emitSW(Register.A0, gvi.getLabel(), Register.T0, "Assign global: "+gvi.getVarName()+"(using tmp register)"); + + } + } + else + {/* TODO: Assignments inside functions + for(Expr target: node.targets) + { + + backend.emitGlobalLabel("$"+target.kind); + backend.emitWordLiteral(node.value); + }*/ + } + return null; + } + + @Override + public Void analyze(BinaryExpr node) { + // statement + return defaultAction(node); + } + }