编译器实现之旅——第十章 实现代码生成器前的准备

从这一章开始,我们将进入代码生成器的世界。代码生成器是整个编译器中最复杂,但也最为精彩的部分。话不多说,就让我们开始吧。

1. 代码生成器概观

顾名思义,代码生成器就是用来生成代码的编译器组件。这里的"代码"一词,指的是我们已经实现了的CMM指令集中的指令。代码生成器通过解析抽象语法树,并利用符号表中的信息,最终生成一串可供虚拟机执行的低级指令。需要注意的是:正如语法分析器中,我们忽略了许多无用的记号一样,在代码生成器中,我们也会忽略一些抽象语法树节点,这主要指的是"声明类"节点。为什么要忽略这些节点呢?不难想到,声明类节点是"不做实事"的,其存在的意义只是为了提供一些信息。说到这可能你已经明白了:这些信息,我们早已将其存入了符号表中,代码生成器自然也就不需要了。我们将在后续的旅程中看到这类忽略抽象语法树节点的现象。

事实上,代码生成器的实现思路和前面的语法分析器的实现思路是类似的,都是利用了递归的力量,通过各个代码生成器分派函数的通力合作,最终得到完整的代码。由此我们不难想象:在代码生成器中也含有许多分派函数,这些分派函数对应着抽象语法树中的各种节点,并可为这些节点产生代码。所以首先,就让我们来看看代码生成器的类定义,看看其中到底有哪些函数吧。

2. 代码生成器的类定义

代码生成器的类定义如下:

class __CodeGenerator
{
    // Friend
    friend class Core;


public:

    // Constructor
    __CodeGenerator(__AST *root = nullptr, const unordered_map<string, unordered_map<string, pair<int, int>>> &symbolTable = {});


private:

    // Attribute
    __AST *__root;
    unordered_map<string, unordered_map<string, pair<int, int>>> __symbolTable;


    // Generate Number Code
    vector<pair<__Instruction, string>> __generateNumberCode(__AST *root, const string &) const;


    // Generate StmtList Code
    vector<pair<__Instruction, string>> __generateStmtListCode(__AST *root, const string &curFuncName) const;


    // Generate Stmt Code
    vector<pair<__Instruction, string>> __generateStmtCode(__AST *root, const string &curFuncName) const;


    // Generate IfStmt Code
    vector<pair<__Instruction, string>> __generateIfStmtCode(__AST *root, const string &curFuncName) const;


    // Generate WhileStmt Code
    vector<pair<__Instruction, string>> __generateWhileStmtCode(__AST *root, const string &curFuncName) const;


    // Generate ReturnStmt Code
    vector<pair<__Instruction, string>> __generateReturnStmtCode(__AST *root, const string &curFuncName) const;


    // Generate Expr Code
    vector<pair<__Instruction, string>> __generateExprCode(__AST *root, const string &curFuncName) const;


    // Generate Var Code
    vector<pair<__Instruction, string>> __generateVarCode(__AST *root, const string &curFuncName) const;


    // Generate SimpleExpr Code
    vector<pair<__Instruction, string>> __generateSimpleExprCode(__AST *root, const string &curFuncName) const;


    // Generate RelOp Code
    vector<pair<__Instruction, string>> __generateRelOpCode(__AST *root, const string &) const;


    // Generate AddExpr Code
    vector<pair<__Instruction, string>> __generateAddExprCode(__AST *root, const string &curFuncName) const;


    // Generate AddOp Code
    vector<pair<__Instruction, string>> __generateAddOpCode(__AST *root, const string &) const;


    // Generate Term Code
    vector<pair<__Instruction, string>> __generateTermCode(__AST *root, const string &curFuncName) const;


    // Generate MulOp Code
    vector<pair<__Instruction, string>> __generateMulOpCode(__AST *root, const string &) const;


    // Generate Factor Code
    vector<pair<__Instruction, string>> __generateFactorCode(__AST *root, const string &curFuncName) const;


    // Generate Call Code
    vector<pair<__Instruction, string>> __generateCallCode(__AST *root, const string &curFuncName) const;


    // Generate ArgList Code
    vector<pair<__Instruction, string>> __generateArgListCode(__AST *root, const string &curFuncName) const;


    // Generate Assign Code
    vector<pair<__Instruction, string>> __generateAssignCode(__AST *root, const string &curFuncName) const;


    // Generate Global Variable Code
    vector<pair<__Instruction, string>> __generateGlobalVariableCode() const;


    // Generate Main Prepare Code
    vector<pair<__Instruction, string>> __generateMainPrepareCode() const;


    // Generate Global Code
    vector<pair<__Instruction, string>> __generateGlobalCode() const;


    // Create CodeMap
    unordered_map<string, vector<pair<__Instruction, string>>> __createCodeMap() const;


    // Merge CodeMap
    static pair<vector<pair<__Instruction, string>>, unordered_map<string, int>> __mergeCodeMap(
        const unordered_map<string, vector<pair<__Instruction, string>>> &codeMap);


    // Translate Call
    static void __translateCall(vector<pair<__Instruction, string>> &codeList, const unordered_map<string, int> &funcJmpMap);


    // Generate Code
    vector<pair<__Instruction, string>> __generateCode() const;
};

在这个类定义中,我们看到了许多熟悉的身影,如CompoundStmt、IfStmt等,同时,我们也看到了许多陌生的函数。但总体上,我们发现代码生成器中确实存储了抽象语法树以及符号表,并且还存储了当前函数的名称,这些变量的使用我们都将在接下来的旅程中见到;此外,我们发现,代码生成器的每个分派函数都返回vector<pair<Instruction, string>>,不难猜到,这个vector<pair<Instruction, string>>里面装的正是这个函数生成的代码。

3. 各个周边函数的实现

在这一章的末尾,让我们暂且先来看看代码生成器的各个周边函数的实现:

__CodeGenerator::__CodeGenerator(__AST *root, const unordered_map<string, unordered_map<string, pair<int, int>>> &symbolTable):
    __root       (root),
    __symbolTable(symbolTable) {}

这些周边函数的实现都很简单,这里就不讨论了。

接下来,我们就要开始逐步讨论代码生成器的各个分派函数的实现了。让我们首先从最简单的部分开始。请看下一章:《一些较为顶层的代码生成器分派函数的实现》。

posted @ 2021-02-19 16:39  樱雨楼  阅读(219)  评论(0编辑  收藏  举报