classnameTab
This commit is contained in:
parent
b2142969f8
commit
d4aeee16cc
@ -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 是真的要绕半天。
|
||||||
@ -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}
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user