diff --git a/CS143体验报告.md b/CS143体验报告.md index 2bebfec..4ac7efc 100644 --- a/CS143体验报告.md +++ b/CS143体验报告.md @@ -262,3 +262,7 @@ PA 2-5 正式写编译器。PA2 写词法分析器,首先读一遍 README 和 - 栈和寄存器约定:方法调用参数放在栈上、从左到右依次压栈,`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.` 没看懂 - 执行初始化:需要生成一些代码来调用 main 方法。首先通过 Main prototype 生成一个 Main 类的对象并用 `Main_init` 初始化,该初始化方法依次执行 Main 的基类的初始化最后初始化 Main;然后调用 `Main.main`,在 `a0` 里面放上 `Main` 的指针并设置 `ra`;执行结束后,`Main.main` 返回,这里打印出提示信息并终止执行。 + +#### 读框架 + +这次的框架代码非常的多,而且写的很抽象,因此讲一讲。其实最好的方法是自己写个测试代码,然后用参考编译器生成出来看一看具体是啥样子的,光看他的 skeleton 是真的要绕半天。 \ No newline at end of file diff --git a/assignments/PA5/Makefile b/assignments/PA5/Makefile index f81164f..5aeb353 100644 --- a/assignments/PA5/Makefile +++ b/assignments/PA5/Makefile @@ -26,7 +26,7 @@ FFLAGS = -d8 -ocool-lex.cc BFLAGS = -d -v -y -b cool --debug -p cool_yy 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} BISON= bison ${BFLAGS} DEPEND = ${CC} -MM ${CPPINCLUDE} diff --git a/assignments/PA5/cgen.cc b/assignments/PA5/cgen.cc index 45624d8..bad2b89 100644 --- a/assignments/PA5/cgen.cc +++ b/assignments/PA5/cgen.cc @@ -24,6 +24,7 @@ #include "cgen.h" #include "cgen_gc.h" +#include #include 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, ostream &s) { 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; } +#pragma endregion + /////////////////////////////////////////////////////////////////////////////// // // coding strings, ints, and booleans @@ -347,6 +352,8 @@ static void emit_gc_check(char *source, ostream &s) { // /////////////////////////////////////////////////////////////////////////////// +#pragma region ConstantCoding + // // Strings // @@ -454,6 +461,8 @@ void BoolConst::code_def(ostream &s, int boolclasstag) { s << WORD << val << endl; // value (0 or 1) } +#pragma endregion + ////////////////////////////////////////////////////////////////////////////// // // CgenClassTable methods @@ -575,12 +584,22 @@ void CgenClassTable::code_constants() { code_bools(boolclasstag); } -CgenClassTable::CgenClassTable(Classes classes, ostream &s) - : nds(NULL), str(s) { - 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 */; +void CgenClassTable::code_class_nameTable() { + str << CLASSNAMETAB << LABEL; + 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(); if (cgen_debug) 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. // SELF_TYPE is the self class; it cannot be redefined or inherited. // prim_slot is a class known to the code generator. + // it serves as the value type of Int, Boolean, String // addid(No_class, new CgenNode(class_(No_class, No_class, nil_Features(), filename), @@ -710,6 +730,10 @@ void CgenClassTable::install_basic_classes() { Str, no_expr()))), filename), 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 @@ -726,7 +750,8 @@ void CgenClassTable::install_class(CgenNodeP nd) { // The class name is legal, so add it to the list of classes // and the symbol table. - nds = new List(nd, nds); + nodes.push_back(nd); + nd->set_class_tag(nodes.size()); addid(name, nd); } @@ -739,8 +764,8 @@ void CgenClassTable::install_classes(Classes cs) { // CgenClassTable::build_inheritance_tree // void CgenClassTable::build_inheritance_tree() { - for (List *l = nds; l; l = l->tl()) - set_relations(l->hd()); + for (auto node : nodes) + set_relations(node); } // @@ -755,9 +780,7 @@ void CgenClassTable::set_relations(CgenNodeP nd) { parent_node->add_child(nd); } -void CgenNode::add_child(CgenNodeP n) { - children = new List(n, children); -} +void CgenNode::add_child(CgenNodeP n) { children.push_back(n); } void CgenNode::set_parentnd(CgenNodeP p) { assert(parentnd == NULL); @@ -765,11 +788,19 @@ void CgenNode::set_parentnd(CgenNodeP 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() { CgenNode *object_node = nullptr; - for (auto l = nds; l; l = l->tl()) { - auto cur_node = l->hd(); + for (auto cur_node : nodes) { if (cur_node->name == Object) { object_node = cur_node; break; @@ -778,6 +809,18 @@ void CgenClassTable::dump_inheritance_tree() { 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() { if (cgen_debug) cout << "coding global data" << endl; @@ -791,6 +834,10 @@ void CgenClassTable::code() { cout << "coding constants" << endl; code_constants(); + if (cgen_debug) + cout << "coding class_nameTab" << endl; + code_class_nameTable(); + // Add your code to emit // - prototype objects // - class_nameTab @@ -816,7 +863,7 @@ CgenNodeP CgenClassTable::root() { return probe(Object); } /////////////////////////////////////////////////////////////////////// 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) { 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 static_dispatch_class::code(ostream &s) {} @@ -887,3 +936,5 @@ void isvoid_class::code(ostream &s) {} void no_expr_class::code(ostream &s) {} void object_class::code(ostream &s) {} + +#pragma endregion diff --git a/assignments/PA5/cgen.h b/assignments/PA5/cgen.h index 923c121..4b0d955 100644 --- a/assignments/PA5/cgen.h +++ b/assignments/PA5/cgen.h @@ -2,6 +2,8 @@ #include "emit.h" #include "symtab.h" #include +#include +#include #include #include @@ -17,7 +19,7 @@ typedef CgenNode *CgenNodeP; class CgenClassTable : public SymbolTable { private: - List *nds; + std::vector nodes; ostream &str; int stringclasstag; int intclasstag; @@ -44,6 +46,10 @@ private: void set_relations(CgenNodeP nd); //* New Methods void dump_inheritance_tree(); + void code_class_nameTable(); + void code_dispatchTable(); + void code_prototypeObject(); + CgenNode* get_node(Symbol); public: CgenClassTable(Classes, ostream &str); @@ -54,26 +60,25 @@ public: class CgenNode : public class__class { private: CgenNodeP parentnd; // Parent of class - List *children; // Children of class + std::vector children; // Children of class Basicness basic_status; // `Basic' if class is basic // `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: CgenNode(Class_ c, Basicness bstatus, CgenClassTableP class_table); void add_child(CgenNodeP child); - List *get_children() { return children; } + std::vector& get_children() { return children; } void set_parentnd(CgenNodeP p); CgenNodeP get_parentnd() { return parentnd; } int basic() { return (basic_status == Basic); } - void traverse_dump(int pad) { - for (int i = 0; i < pad; ++i) - std::cerr << " "; - std::cerr << this->name << "\n"; - for (auto l = children; l; l = l->tl()) { - l->hd()->traverse_dump(pad + 2); - } - } + uint32_t get_class_tag() { return _class_tag; } + void set_class_tag(uint32_t val) { _class_tag = val; } + void traverse_dump(int pad); }; class BoolConst {