classnameTab

This commit is contained in:
ridethepig 2023-03-29 19:04:28 +08:00
parent b2142969f8
commit d4aeee16cc
4 changed files with 86 additions and 26 deletions

View File

@ -262,3 +262,7 @@ PA 2-5 正式写编译器。PA2 写词法分析器,首先读一遍 README 和
- 栈和寄存器约定:方法调用参数放在栈上、从左到右依次压栈,`a0` 寄存器里面放 `self` 对象指针。指定了一组 Scratch registers 供 runtime routine 存放临时数据,因此需要调用者保存;还有堆指针和堆界限两个寄存器,完全由 runtime 控制。其他的都可以用。 - 栈和寄存器约定:方法调用参数放在栈上、从左到右依次压栈,`a0` 寄存器里面放 `self` 对象指针。指定了一组 Scratch registers 供 runtime routine 存放临时数据,因此需要调用者保存;还有堆指针和堆界限两个寄存器,完全由 runtime 控制。其他的都可以用。
- Label生成的代码需要和 runtime 一起变成最后执行的机器码,因此有一些 label 是指定的,就类似于接口一样的东西。有些 label 是 runtime 提供给我们使用的,也有一些需要我们生成供 runtime 使用。有一句话 `There is no need for code that initializes an object of class Bool if the generated code contains definitions of both Bool objects in the static data area.` 没看懂 - Label生成的代码需要和 runtime 一起变成最后执行的机器码,因此有一些 label 是指定的,就类似于接口一样的东西。有些 label 是 runtime 提供给我们使用的,也有一些需要我们生成供 runtime 使用。有一句话 `There is no need for code that initializes an object of class Bool if the generated code contains definitions of both Bool objects in the static data area.` 没看懂
- 执行初始化:需要生成一些代码来调用 main 方法。首先通过 Main prototype 生成一个 Main 类的对象并用 `Main_init` 初始化,该初始化方法依次执行 Main 的基类的初始化最后初始化 Main然后调用 `Main.main`,在 `a0` 里面放上 `Main` 的指针并设置 `ra`;执行结束后,`Main.main` 返回,这里打印出提示信息并终止执行。 - 执行初始化:需要生成一些代码来调用 main 方法。首先通过 Main prototype 生成一个 Main 类的对象并用 `Main_init` 初始化,该初始化方法依次执行 Main 的基类的初始化最后初始化 Main然后调用 `Main.main`,在 `a0` 里面放上 `Main` 的指针并设置 `ra`;执行结束后,`Main.main` 返回,这里打印出提示信息并终止执行。
#### 读框架
这次的框架代码非常的多,而且写的很抽象,因此讲一讲。其实最好的方法是自己写个测试代码,然后用参考编译器生成出来看一看具体是啥样子的,光看他的 skeleton 是真的要绕半天。

View File

@ -26,7 +26,7 @@ FFLAGS = -d8 -ocool-lex.cc
BFLAGS = -d -v -y -b cool --debug -p cool_yy BFLAGS = -d -v -y -b cool --debug -p cool_yy
CC=g++ CC=g++
CFLAGS=-g -Wall -Wno-unused -Wno-write-strings -Wno-deprecated ${CPPINCLUDE} -DDEBUG -std=c++11 CFLAGS=-g -Wall -Wno-unused -Wno-write-strings -Wno-deprecated ${CPPINCLUDE} -DDEBUG -std=c++11 -Wno-unknown-pragmas
FLEX=flex ${FFLAGS} FLEX=flex ${FFLAGS}
BISON= bison ${BFLAGS} BISON= bison ${BFLAGS}
DEPEND = ${CC} -MM ${CPPINCLUDE} DEPEND = ${CC} -MM ${CPPINCLUDE}

View File

@ -24,6 +24,7 @@
#include "cgen.h" #include "cgen.h"
#include "cgen_gc.h" #include "cgen_gc.h"
#include <cassert>
#include <iostream> #include <iostream>
extern void emit_string_constant(ostream &str, char *s); extern void emit_string_constant(ostream &str, char *s);
@ -127,6 +128,8 @@ void program_class::cgen(ostream &os) {
// //
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
#pragma region StaticEmitProcedures
static void emit_load(char *dest_reg, int offset, char *source_reg, static void emit_load(char *dest_reg, int offset, char *source_reg,
ostream &s) { ostream &s) {
s << LW << dest_reg << " " << offset * WORD_SIZE << "(" << source_reg << ")" s << LW << dest_reg << " " << offset * WORD_SIZE << "(" << source_reg << ")"
@ -326,6 +329,8 @@ static void emit_gc_check(char *source, ostream &s) {
s << JAL << "_gc_check" << endl; s << JAL << "_gc_check" << endl;
} }
#pragma endregion
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// //
// coding strings, ints, and booleans // coding strings, ints, and booleans
@ -347,6 +352,8 @@ static void emit_gc_check(char *source, ostream &s) {
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#pragma region ConstantCoding
// //
// Strings // Strings
// //
@ -454,6 +461,8 @@ void BoolConst::code_def(ostream &s, int boolclasstag) {
s << WORD << val << endl; // value (0 or 1) s << WORD << val << endl; // value (0 or 1)
} }
#pragma endregion
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
// CgenClassTable methods // CgenClassTable methods
@ -575,12 +584,22 @@ void CgenClassTable::code_constants() {
code_bools(boolclasstag); code_bools(boolclasstag);
} }
CgenClassTable::CgenClassTable(Classes classes, ostream &s) void CgenClassTable::code_class_nameTable() {
: nds(NULL), str(s) { str << CLASSNAMETAB << LABEL;
stringclasstag = 1 /* Change to your String class tag here */;
intclasstag = 2 /* Change to your Int class tag here */;
boolclasstag = 3 /* Change to your Bool class tag here */;
for (auto node : nodes) {
auto name_entry = stringtable.lookup_string(node->name->get_string());
str << WORD;
name_entry->code_ref(str);
str << "\n";
}
}
void CgenClassTable::code_dispatchTable() {}
void CgenClassTable::code_prototypeObject() {}
CgenClassTable::CgenClassTable(Classes classes, ostream &s) : str(s) {
enterscope(); enterscope();
if (cgen_debug) if (cgen_debug)
cout << "Building CgenClassTable" << endl; cout << "Building CgenClassTable" << endl;
@ -606,6 +625,7 @@ void CgenClassTable::install_basic_classes() {
// No_class serves as the parent of Object and the other special classes. // No_class serves as the parent of Object and the other special classes.
// SELF_TYPE is the self class; it cannot be redefined or inherited. // SELF_TYPE is the self class; it cannot be redefined or inherited.
// prim_slot is a class known to the code generator. // prim_slot is a class known to the code generator.
// it serves as the value type of Int, Boolean, String
// //
addid(No_class, addid(No_class,
new CgenNode(class_(No_class, No_class, nil_Features(), filename), new CgenNode(class_(No_class, No_class, nil_Features(), filename),
@ -710,6 +730,10 @@ void CgenClassTable::install_basic_classes() {
Str, no_expr()))), Str, no_expr()))),
filename), filename),
Basic, this)); Basic, this));
stringclasstag = get_node(Str)->get_class_tag();
intclasstag = get_node(Int)->get_class_tag();
boolclasstag = get_node(Bool)->get_class_tag();
} }
// CgenClassTable::install_class // CgenClassTable::install_class
@ -726,7 +750,8 @@ void CgenClassTable::install_class(CgenNodeP nd) {
// The class name is legal, so add it to the list of classes // The class name is legal, so add it to the list of classes
// and the symbol table. // and the symbol table.
nds = new List<CgenNode>(nd, nds); nodes.push_back(nd);
nd->set_class_tag(nodes.size());
addid(name, nd); addid(name, nd);
} }
@ -739,8 +764,8 @@ void CgenClassTable::install_classes(Classes cs) {
// CgenClassTable::build_inheritance_tree // CgenClassTable::build_inheritance_tree
// //
void CgenClassTable::build_inheritance_tree() { void CgenClassTable::build_inheritance_tree() {
for (List<CgenNode> *l = nds; l; l = l->tl()) for (auto node : nodes)
set_relations(l->hd()); set_relations(node);
} }
// //
@ -755,9 +780,7 @@ void CgenClassTable::set_relations(CgenNodeP nd) {
parent_node->add_child(nd); parent_node->add_child(nd);
} }
void CgenNode::add_child(CgenNodeP n) { void CgenNode::add_child(CgenNodeP n) { children.push_back(n); }
children = new List<CgenNode>(n, children);
}
void CgenNode::set_parentnd(CgenNodeP p) { void CgenNode::set_parentnd(CgenNodeP p) {
assert(parentnd == NULL); assert(parentnd == NULL);
@ -765,11 +788,19 @@ void CgenNode::set_parentnd(CgenNodeP p) {
parentnd = p; parentnd = p;
} }
void CgenNode::traverse_dump(int pad) {
for (int i = 0; i < pad; ++i)
std::cerr << " ";
std::cerr << this->name << ":" << this->_class_tag << "\n";
for (auto child : children) {
child->traverse_dump(pad + 2);
}
}
void CgenClassTable::dump_inheritance_tree() { void CgenClassTable::dump_inheritance_tree() {
CgenNode *object_node = nullptr; CgenNode *object_node = nullptr;
for (auto l = nds; l; l = l->tl()) { for (auto cur_node : nodes) {
auto cur_node = l->hd();
if (cur_node->name == Object) { if (cur_node->name == Object) {
object_node = cur_node; object_node = cur_node;
break; break;
@ -778,6 +809,18 @@ void CgenClassTable::dump_inheritance_tree() {
object_node->traverse_dump(0); object_node->traverse_dump(0);
} }
CgenNode *CgenClassTable::get_node(Symbol class_name) {
for (auto node : nodes) {
if (node->name == class_name) {
return node;
}
}
if (cgen_debug)
std::cerr << "get_node " << class_name << " not found\n";
assert(0);
return nullptr;
}
void CgenClassTable::code() { void CgenClassTable::code() {
if (cgen_debug) if (cgen_debug)
cout << "coding global data" << endl; cout << "coding global data" << endl;
@ -791,6 +834,10 @@ void CgenClassTable::code() {
cout << "coding constants" << endl; cout << "coding constants" << endl;
code_constants(); code_constants();
if (cgen_debug)
cout << "coding class_nameTab" << endl;
code_class_nameTable();
// Add your code to emit // Add your code to emit
// - prototype objects // - prototype objects
// - class_nameTab // - class_nameTab
@ -816,7 +863,7 @@ CgenNodeP CgenClassTable::root() { return probe(Object); }
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
CgenNode::CgenNode(Class_ nd, Basicness bstatus, CgenClassTableP ct) CgenNode::CgenNode(Class_ nd, Basicness bstatus, CgenClassTableP ct)
: class__class((const class__class &)*nd), parentnd(NULL), children(NULL), : class__class((const class__class &)*nd), parentnd(NULL),
basic_status(bstatus) { basic_status(bstatus) {
stringtable.add_string(name->get_string()); // Add class name to string table stringtable.add_string(name->get_string()); // Add class name to string table
} }
@ -831,6 +878,8 @@ CgenNode::CgenNode(Class_ nd, Basicness bstatus, CgenClassTableP ct)
// //
//***************************************************************** //*****************************************************************
#pragma region ExpressionCoding
void assign_class::code(ostream &s) {} void assign_class::code(ostream &s) {}
void static_dispatch_class::code(ostream &s) {} void static_dispatch_class::code(ostream &s) {}
@ -887,3 +936,5 @@ void isvoid_class::code(ostream &s) {}
void no_expr_class::code(ostream &s) {} void no_expr_class::code(ostream &s) {}
void object_class::code(ostream &s) {} void object_class::code(ostream &s) {}
#pragma endregion

View File

@ -2,6 +2,8 @@
#include "emit.h" #include "emit.h"
#include "symtab.h" #include "symtab.h"
#include <assert.h> #include <assert.h>
#include <cstdint>
#include <vector>
#include <iostream> #include <iostream>
#include <stdio.h> #include <stdio.h>
@ -17,7 +19,7 @@ typedef CgenNode *CgenNodeP;
class CgenClassTable : public SymbolTable<Symbol, CgenNode> { class CgenClassTable : public SymbolTable<Symbol, CgenNode> {
private: private:
List<CgenNode> *nds; std::vector<CgenNode*> nodes;
ostream &str; ostream &str;
int stringclasstag; int stringclasstag;
int intclasstag; int intclasstag;
@ -44,6 +46,10 @@ private:
void set_relations(CgenNodeP nd); void set_relations(CgenNodeP nd);
//* New Methods //* New Methods
void dump_inheritance_tree(); void dump_inheritance_tree();
void code_class_nameTable();
void code_dispatchTable();
void code_prototypeObject();
CgenNode* get_node(Symbol);
public: public:
CgenClassTable(Classes, ostream &str); CgenClassTable(Classes, ostream &str);
@ -54,26 +60,25 @@ public:
class CgenNode : public class__class { class CgenNode : public class__class {
private: private:
CgenNodeP parentnd; // Parent of class CgenNodeP parentnd; // Parent of class
List<CgenNode> *children; // Children of class std::vector<CgenNode*> children; // Children of class
Basicness basic_status; // `Basic' if class is basic Basicness basic_status; // `Basic' if class is basic
// `NotBasic' otherwise // `NotBasic' otherwise
uint32_t _class_tag = 0;
/* Allocate a class_tag on first scan increase in scanning order,
starting from 1, so 0 is actually invalid by design
*/
public: public:
CgenNode(Class_ c, Basicness bstatus, CgenClassTableP class_table); CgenNode(Class_ c, Basicness bstatus, CgenClassTableP class_table);
void add_child(CgenNodeP child); void add_child(CgenNodeP child);
List<CgenNode> *get_children() { return children; } std::vector<CgenNode*>& get_children() { return children; }
void set_parentnd(CgenNodeP p); void set_parentnd(CgenNodeP p);
CgenNodeP get_parentnd() { return parentnd; } CgenNodeP get_parentnd() { return parentnd; }
int basic() { return (basic_status == Basic); } int basic() { return (basic_status == Basic); }
void traverse_dump(int pad) { uint32_t get_class_tag() { return _class_tag; }
for (int i = 0; i < pad; ++i) void set_class_tag(uint32_t val) { _class_tag = val; }
std::cerr << " "; void traverse_dump(int pad);
std::cerr << this->name << "\n";
for (auto l = children; l; l = l->tl()) {
l->hd()->traverse_dump(pad + 2);
}
}
}; };
class BoolConst { class BoolConst {