编译器实现之旅——第十章 实现代码生成器前的准备
从这一章开始,我们将进入代码生成器的世界。代码生成器是整个编译器中最复杂,但也最为精彩的部分。话不多说,就让我们开始吧。
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) {}
这些周边函数的实现都很简单,这里就不讨论了。
接下来,我们就要开始逐步讨论代码生成器的各个分派函数的实现了。让我们首先从最简单的部分开始。请看下一章:《一些较为顶层的代码生成器分派函数的实现》。