⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 codegen.h

📁 一个面向对像语言的编译器
💻 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 + -