Assignment for global variables

master
Apoorva Ranade 3 years ago
parent 9f1681bb23
commit 913fd45dc1

@ -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.
*
* <p>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.
* <p>
* 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.
*
* <p>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.
* <p>
* 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.
*
* <p>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.
* <p>
* 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.
*
* <p>You only need to generate code for statements.
* <p>
* You only need to generate code for statements.
*
* @param statements top level statements
*/
protected void emitTopLevel(List<Stmt> 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.
*
* <p>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`.
* <p>
* 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<Void> {
/*
* 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);
}
}

Loading…
Cancel
Save