📄 codegen.h
字号:
/* File: codegen.h
* ---------------
* The CodeGenerator class defines an object that will build TAC
* instructions (using the Tac class and its subclasses) and store the
* instructions in a sequential list, ready for further processing or
* translation to MIPS as part of final code generation.
*
* pp4: The class as given supports the basic Tac instructions,
* you will need to extend it to handle the more complex
* operations (accessing instance variables, dynamic method
* dispatch, array length(), etc.)
*/
#ifndef _H_codegen
#define _H_codegen
#include <stdlib.h>
#include "typelist.h"
#include "taclist.h"
#include "decllist.h"
class Declaration;
class Type;
#define OffsetToFirstLocal -4
#define OffsetToFirstParam 8
#define OffsetToFirstGlobal 0
#define OffsetToFirstIvar 4
#define OffsetToFirstMethod 0
#define VarSize 4
#define LENGTH 32
// These codes are used to identify the built-in functions
typedef enum { Alloc, ReadLine, ReadInteger, StringEqual,
PrintInt, PrintString, PrintBool, Halt, NumBuiltIns } BuiltIn;
typedef enum{LocalStackSize, ParaStackSize, ClassStackSize}StackSize;
class CodeGenerator {
private:
TacList *code;
//标签栈
char *labelStack[LENGTH];
//为了处理函数中间的return所添加的一个标签栈,它在EndFunction前设置一个标签
//中间有return的话,return完,就跳到相应的EndFunction前的那个标签。
char *retLabelStack[LENGTH];
//当前各local域偏移地址指针
int topLocalOffset;
//参数的offset指针
int topParaOffset;
int topGlobalOffset;
//类中成员变量的offset指针
int topIvarOffset;
//类中成员方法的offset指针
int topMethodOffset;
public:
//得到retLabelStack栈顶的标签
char * GetRetTopLabel();
//得到第retTop-index处的标签
char * GetRetLabel(int index);
//弹出栈顶count个标签
void PopRetLabel(int count);
//向栈顶压入一个标签
void PushRetLabel(char *retLabel);
//设置当前类中最大的变量和方法的offset指针
void SetTopIVarOffset(int offset);
void SetTopMethodOffset(int offset);
//设置变量和方法的decl的offset
void SetMethodOffset(Declaration *decl);
void SetIVarOffset(Declaration *decl);
//初始化变量和方法的offset指针
void InitMethodOffset();
void InitIVarOffset();
//得到当前域中变量空间的大小的函数
int GetStackFrameSize(StackSize temp);
//初始化局部和参数的offset指针
void InitParaOffset();
void InitLocalOffset();
//设置局部和参数decl的offset
void SetParaOffset(Declaration *decl);
void SetLocalOffset(Declaration * decl);
void GenGVar(Declaration * decl);
// Here are some class constants to remind you of the offsets
// used for globals, locals, and parameters. You will be
// responsible for setting these for all the various declarations.
// In a MIPS stack frame, first local is at fp-8, subsequent locals
// are at fp-12, fp-16, and so on. The first param is at fp+4,
// subsequent ones as fp+8, fp+12, etc. (Because methods have secret
// "this" passed in first param slot at fp+4, all normal params
// are shifted up by 4.) First global is at offset 0 from global
// pointer, all subsequent at +4, +8, etc.
// Conveniently, all vars are 4 bytes in size for code generation
CodeGenerator();
// Assigns a new unique label name and returns it. Does not
// generate any Tac instructions (see GenLabel below if needed)
char *NewLabel();
// Creates and returns a Declaration for a new uniquely named
// temp variable of given type. Does not generate any Tac
// instructions
Declaration *GenTempVar(Type *type);
// Generates Tac instructions to load a constant value. Creates
// a new temp var to hold the result. Although the constant
// value is passed as an integer, the type parameter dictates
// dictates how to properly interpret that value (i.e. 0 could
// be integer zero or NULL for an object or false for bool).
// The second overloaded version is used for string constants.
// The LoadLabel method loads a label into a temporary.
// Each of the methods returns a Declaration for the temp var
// where the constant was loaded.
Declaration *GenLoadConstant(int value, Type *type);
Declaration *GenLoadConstant(const char *str);
Declaration *GenLoadLabel(const char *label);
// Generates Tac instructions to copy value from one var to another
void GenAssign(Declaration *dst, Declaration *src);
// Generates Tac instructions to dereference addr and store value
// into that memory location. addr should hold a valid memory
// address (most likely computed from an array or field offset
// calculation) and the type stored at that location should match
// the type of val being stored. The optional offset argument can
// be used to offset the addr by a positive/negative number of
// bytes. If not given, 0 is assumed.
void GenStore(Declaration *addr, Declaration *val, int offset = 0);
// Generates Tac instructions to dereference addr and load contents
// from a memory location into a new temp var. addr should hold a
// valid memory address (most likely computed from an array or
// field offset calculation). Returns the Declaration for the new
// temporary variable where the result was stored. The Declaration
// will be of the type you pass as the resultType. The optional
// offset argument can be used to offset the addr by a positive or
// negative number of bytes. If not given, 0 is assumed.
Declaration *GenLoad(Declaration *addr, Type *resultType, int offset = 0);
// Generates Tac instructions to perform one of the binary ops
// identified by string name, such as "+" or "==". Returns a
// a Declaration object for the new temporary where the result
// was stored. The new temp var will be of the type you pass
// as the resultType
Declaration *GenBinaryOp(const char *opName, Declaration *op1,
Declaration *op2, Type *resultType);
// Generates the Tac instruction for pushing a single
// parameter. Used to set up for ACall and LCall instructions.
// The Decaf convention is that parameters are pushed right
// to left (so the first argument is pushed last)
void GenPushParam(Declaration *param);
// Generates the Tac instructions for a LCall, a jump to
// a compile-time label. The params to the target routine
// should already have been pushed. The numParamBytes is
// the total number of bytes of parameters pushed on the stack
// (this is needed to clean up after the call). The resultType
// you pass indicates what the return type of the function is.
// If non-void, a new temp var of the correct type is created
// and the result is stored there and that Declaration is
// returned. If fn returns void, pass voidType, no temp is
// created and NULL is returned
Declaration *GenLCall(const char *label, int numParamBytes,
Type *resultType);
// Generates the Tac instructions for ACall, a jump to an
// address computed at runtime. Works similarly to LCall,
// described above, in terms of parameter size (be sure to
// count the receiver hidden parameter) and return type.
// The fnAddr Declaration is expected to be the address of
// the code to jump to (typically it was read from the vtable)
Declaration *GenACall(Declaration *fnAddr, int numParamBytes,
Type *resultType);
// Generates the Tac instructions to call one of
// the built-in functions (Read, Print, Alloc, etc.) Although
// you could just make a call to GenLCall above, this cover
// is a little more convenient to use. The arguments to the
// builtin should be given as arg1 and arg2, NULL is used if
// fewer than 2 args to pass. The method returns a Declaration
// for the new temp var holding the result. The Declaration will
// will be of the type you pass as the resultType. For those
// built-ins with no return value (Print/Halt), pass voidType
// as resultType, no temporary is created and NULL is returned.
Declaration *GenBuiltInCall(BuiltIn b, Type *resultType,
Declaration *arg1 = NULL, Declaration *arg2 = NULL);
// These methods generate the Tac instructions for various
// control flow (branches, jumps, returns, labels)
// One minor detail to mention is that you can pass NULL
// (or omit arg) to GenReturn for a return that does not
// return a value
void GenIfZ(Declaration *test, const char *label);
void GenGoto(const char *label);
void GenReturn(Declaration *val = NULL);
void GenLabel(const char *label,bool isfunlabel=false);
// These methods generate the Tac instructions that mark the start
// and end of a function/method definition. The Begin method
// generates the label for the function (so you don't need to do
// this separately).
void GenBeginFunc(Declaration *fn);
void GenEndFunc(Declaration *fn);
// Generates the Tac instructions for defining vtable for a
// The methods parameter is expected to contain the vtable
// methods in the order they should be laid out. The vtable
// is tagged with a label of the class name, so when you later
// need access to the vtable, you use LoadLabel of class name.
void GenVTable(const char *className, DeclList *methods);
// Emits the final "object code" for the program by
// translating the sequence of Tac instructions into their mips
// equivalent and printing them out to stdout. If the debug
// flag tac is on (-d tac), it will not translate to MIPS,
// but instead just print the untranslated Tac. It may be
// useful in debugging to first make sure your Tac is correct.
void Emit();
/*新添加的功能函数*/
//向labelStack中压入一个label
void PushLabel(char * label);
//从labelStack栈顶开始中弹出count个label
void PopLabel(int count);
//得到第myTop-index个label
char * GetLabel(int index);
//得到栈顶的label
char * GetTopLabel();
};
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -