add a simple vector based symtab for location

This commit is contained in:
ridethepig 2023-03-31 18:04:51 +08:00
parent 2db8b1f4e7
commit d279a73fb5
3 changed files with 214 additions and 94 deletions

View File

@ -93,6 +93,7 @@ static char *gc_collect_names[] = {"_NoGC_Collect", "_GenGC_Collect",
BoolConst falsebool(FALSE);
BoolConst truebool(TRUE);
static int rel_stack_depth;
//*********************************************************
//
// Define method for code generation
@ -297,6 +298,17 @@ static void emit_branch(int l, ostream &s) {
static void emit_push(char *reg, ostream &str) {
emit_store(reg, 0, SP, str);
emit_addiu(SP, SP, -4, str);
rel_stack_depth++;
}
static void emit_pop(ostream &str) {
emit_addiu(SP, SP, 4, str);
rel_stack_depth--;
}
static void emit_pop(size_t count, ostream &str) {
emit_addiu(SP, SP, 4 * count, str);
rel_stack_depth -= count;
}
//
@ -674,13 +686,13 @@ void CgenClassTable::install_basic_classes() {
//
addid(No_class,
new CgenNode(class_(No_class, No_class, nil_Features(), filename),
Basic, this));
Trivial));
addid(SELF_TYPE,
new CgenNode(class_(SELF_TYPE, No_class, nil_Features(), filename),
Basic, this));
Trivial));
addid(prim_slot,
new CgenNode(class_(prim_slot, No_class, nil_Features(), filename),
Basic, this));
Trivial));
//
// The Object class has no parent class. Its methods are
@ -702,7 +714,7 @@ void CgenClassTable::install_basic_classes() {
single_Features(
method(copy, nil_Formals(), SELF_TYPE, no_expr()))),
filename),
Basic, this));
Basic));
//
// The IO class inherits from Object. Its methods are
@ -727,7 +739,7 @@ void CgenClassTable::install_basic_classes() {
method(in_string, nil_Formals(), Str, no_expr()))),
single_Features(method(in_int, nil_Formals(), Int, no_expr()))),
filename),
Basic, this));
Basic));
//
// The Int class has no methods and only a single attribute, the
@ -736,7 +748,7 @@ void CgenClassTable::install_basic_classes() {
install_class(new CgenNode(
class_(Int, Object, single_Features(attr(val, prim_slot, no_expr())),
filename),
Basic, this));
Basic));
//
// Bool also has only the "val" slot.
@ -744,7 +756,7 @@ void CgenClassTable::install_basic_classes() {
install_class(new CgenNode(
class_(Bool, Object, single_Features(attr(val, prim_slot, no_expr())),
filename),
Basic, this));
Basic));
//
// The class Str has a number of slots and operations:
@ -774,7 +786,7 @@ void CgenClassTable::install_basic_classes() {
single_Formals(formal(arg2, Int))),
Str, no_expr()))),
filename),
Basic, this));
Basic));
stringclasstag = get_node(Str)->get_class_tag();
intclasstag = get_node(Int)->get_class_tag();
@ -802,7 +814,7 @@ void CgenClassTable::install_class(CgenNodeP nd) {
void CgenClassTable::install_classes(Classes cs) {
for (int i = cs->first(); cs->more(i); i = cs->next(i))
install_class(new CgenNode(cs->nth(i), NotBasic, this));
install_class(new CgenNode(cs->nth(i), NotBasic));
}
//
@ -825,6 +837,127 @@ void CgenClassTable::set_relations(CgenNodeP nd) {
parent_node->add_child(nd);
}
void CgenClassTable::dump_inheritance_tree() {
CgenNode *object_node = nullptr;
for (auto cur_node : nodes) {
if (cur_node->name == Object) {
object_node = cur_node;
break;
}
}
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;
code_global_data();
if (cgen_debug)
cout << "choosing gc" << endl;
code_select_gc();
if (cgen_debug)
cout << "coding constants" << endl;
code_constants();
if (cgen_debug)
cout << "coding class_nameTab" << endl;
code_class_nameTable();
if (cgen_debug)
cout << "coding dispatch tables" << endl;
nodes[0]->traverse_generate_object();
// nodes[0] is the Object class
code_dispatchTable();
if (cgen_debug)
cout << "coding prototype objects" << endl;
code_prototypeObject();
if (cgen_debug)
cout << "coding global text" << endl;
code_global_text();
#if 0
// test my symtab impl
for (auto node : nodes) {
auto attrs = *node->get_attributes();
auto methods = *node->get_methods();
std::cerr << node->name << std::endl;
loctab.enterscope();
for (size_t i = 0; i < attrs.size(); ++ i) {
auto attr = attrs[i];
loctab.add(LocationTableItem(attr->name, Attribute, i));
}
loctab.enterscope();
for (size_t i = 0; i < methods.size(); ++ i) {
auto method = methods[i];
loctab.add(LocationTableItem(method.second->name, Attribute, i));
}
loctab.enterscope();
for (size_t i = 0; i < attrs.size(); ++ i) {
auto attr = attrs[i];
loctab.add(LocationTableItem(attr->name, Attribute, i + 10000));
}
// loctab.dump();
for (size_t i = 0; i < attrs.size(); ++ i) {
auto attr = attrs[i];
assert(loctab.lookup(attr->name));
assert(loctab.lookup(attr->name)->offset == i + 10000);
}
loctab.exitscope();
for (size_t i = 0; i < attrs.size(); ++ i) {
auto attr = attrs[i];
assert(loctab.lookup(attr->name) && loctab.lookup(attr->name)->offset == i);
}
loctab.exitscope();
for (size_t i = 0; i < attrs.size(); ++ i) {
auto attr = attrs[i];
assert(loctab.lookup(attr->name) && loctab.lookup(attr->name)->offset == i);
}
loctab.exitscope();
for (size_t i = 0; i < attrs.size(); ++ i) {
auto attr = attrs[i];
assert(loctab.lookup(attr->name) == nullptr);
}
}
#endif
// Add your code to emit
// - object initializer
// - the class methods
// - etc...
}
///////////////////////////////////////////////////////////////////////
//
// CgenNode methods
//
///////////////////////////////////////////////////////////////////////
#pragma region CgenNode
CgenNode::CgenNode(Class_ nd, Basicness bstatus)
: class__class((const class__class &)*nd), parentnd(NULL),
basic_status(bstatus) {
if (!(bstatus == Trivial))
stringtable.add_string(
name->get_string()); // Add class name to string table
}
void CgenNode::add_child(CgenNodeP n) { children.push_back(n); }
void CgenNode::set_parentnd(CgenNodeP p) {
@ -898,80 +1031,7 @@ void CgenNode::traverse_generate_object() {
}
}
void CgenClassTable::dump_inheritance_tree() {
CgenNode *object_node = nullptr;
for (auto cur_node : nodes) {
if (cur_node->name == Object) {
object_node = cur_node;
break;
}
}
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;
code_global_data();
if (cgen_debug)
cout << "choosing gc" << endl;
code_select_gc();
if (cgen_debug)
cout << "coding constants" << endl;
code_constants();
if (cgen_debug)
cout << "coding class_nameTab" << endl;
code_class_nameTable();
if (cgen_debug)
cout << "coding dispatch tables" << endl;
nodes[0]->traverse_generate_object();
// nodes[0] is the Object class
code_dispatchTable();
if (cgen_debug)
cout << "coding prototype objects" << endl;
code_prototypeObject();
if (cgen_debug)
cout << "coding global text" << endl;
code_global_text();
// Add your code to emit
// - object initializer
// - the class methods
// - etc...
}
CgenNodeP CgenClassTable::root() { return probe(Object); }
///////////////////////////////////////////////////////////////////////
//
// CgenNode methods
//
///////////////////////////////////////////////////////////////////////
CgenNode::CgenNode(Class_ nd, Basicness bstatus, CgenClassTableP ct)
: class__class((const class__class &)*nd), parentnd(NULL),
basic_status(bstatus) {
stringtable.add_string(name->get_string()); // Add class name to string table
}
#pragma endregion
//******************************************************************
//
@ -1041,7 +1101,11 @@ void block_class::code(ostream &s, CgenClassTable *classtab) {
}
}
void let_class::code(ostream &s, CgenClassTable *classtab) {}
void let_class::code(ostream &s, CgenClassTable *classtab) {
this->init->code(s, classtab);
emit_push(ZERO, s); // make space for let's new object
}
/*
Operations for Int objects is the most simple one, let's start here
@ -1073,7 +1137,7 @@ void plus_class::code(ostream &s, CgenClassTable *classtab) {
emit_add(T1, T1, ACC, s); // $t1 <- val(e1) + val(e2)
emit_load(ACC, 1, SP, s); // load new object addr
emit_store_int(T1, ACC, s); // store result(now in $t1) to the object
emit_addiu(SP, SP, 8, s); // maintain stack balance
emit_pop(2, s); // maintain stack balance
}
/*
@ -1092,7 +1156,7 @@ void sub_class::code(ostream &s, CgenClassTable *classtab) {
emit_sub(T1, T1, ACC, s); // $t1 <- val(e1),$t1 + val(e2),$a0
emit_load(ACC, 1, SP, s);
emit_store_int(T1, ACC, s);
emit_addiu(SP, SP, 8, s);
emit_pop(2, s);
}
/*
@ -1111,7 +1175,7 @@ void mul_class::code(ostream &s, CgenClassTable *classtab) {
emit_mul(T1, T1, ACC, s); // $t1 <- val(e1),$t1 + val(e2),$a0
emit_load(ACC, 1, SP, s);
emit_store_int(T1, ACC, s);
emit_addiu(SP, SP, 8, s);
emit_pop(2, s);
}
void divide_class::code(ostream &s, CgenClassTable *classtab) {
@ -1126,7 +1190,7 @@ void divide_class::code(ostream &s, CgenClassTable *classtab) {
emit_div(T1, T1, ACC, s); // $t1 <- val(e1),$t1 + val(e2),$a0
emit_load(ACC, 1, SP, s);
emit_store_int(T1, ACC, s);
emit_addiu(SP, SP, 8, s);
emit_pop(2, s);
}
/*
@ -1179,7 +1243,7 @@ void lt_class::code(ostream &s, CgenClassTable *classtab) {
emit_label_def(label_index_true, s); // first branch goes to here
emit_load_bool(ACC, truebool, s); // branch means true
emit_label_def(label_index_exit, s); // second jump goes to here
emit_addiu(SP, SP, 4, s); // cleanup anyway, only one push is made
emit_pop(1, s); // cleanup anyway, only one push is made
}
/*
@ -1200,7 +1264,7 @@ void leq_class::code(ostream &s, CgenClassTable *classtab) {
emit_label_def(label_index_true, s);
emit_load_bool(ACC, truebool, s);
emit_label_def(label_index_exit, s);
emit_addiu(SP, SP, 4, s);
emit_pop(1, s);
}
/*
@ -1250,7 +1314,7 @@ void eq_class::code(ostream &s, CgenClassTable *classtab) {
// at this point, $t1=&e1, $t2=&e2, $a0=true, $a1=false. ready to call
// $a0 will be either true or false, so just keep it as the result
emit_label_def(label_index_exit, s);
emit_addiu(SP, SP, 4, s); // balance stack, 1 push in this expression
emit_pop(1, s); // balance stack, 1 push in this expression
}
void int_const_class::code(ostream &s, CgenClassTable *classtab) {

View File

@ -9,7 +9,9 @@
#include <utility>
#include <vector>
enum Basicness { Basic, NotBasic };
enum Basicness { Basic, NotBasic, Trivial };
enum VariableLocation { Attribute, Stack };
#define TRUE 1
#define FALSE 0
@ -22,6 +24,51 @@ typedef CgenNode *CgenNodeP;
typedef std::vector<std::pair<class__class *, method_class *>> MethodListT;
typedef std::vector<attr_class *> AttrListT;
struct LocationTableItem {
LocationTableItem(Symbol id, VariableLocation loc, int off)
: id(id), location(loc), offset(off) {}
Symbol id;
VariableLocation location;
int offset;
};
class LocationTable {
private:
std::vector<LocationTableItem> table;
std::vector<size_t> scope;
public:
// lookup the inner-most item with the same id as name
LocationTableItem* lookup(Symbol name) {
for (auto itr = table.rbegin(); itr != table.rend(); ++ itr) {
if (itr->id == name) {
return &*itr;
}
}
return nullptr;
}
void add(LocationTableItem item) {
table.push_back(item);
};
void enterscope() {
scope.push_back(table.size());
}
void exitscope() {
auto end = scope.back();
scope.pop_back();
table.erase(table.begin() + end, table.end());
}
void dump() {
scope.push_back(table.size());
for (size_t i = 0; i < scope.size() - 1; ++ i) {
std::cerr << "scope" << i << "\n";
for (size_t j = scope[i]; j < scope[i+1]; j ++) {
std::cerr << table[j].id << ", " << table[j].location << ", " << table[j].offset << "\n";
}
}
scope.pop_back();
}
};
class CgenClassTable : public SymbolTable<Symbol, CgenNode> {
private:
std::vector<CgenNode *> nodes;
@ -59,9 +106,10 @@ private:
void gen_init_code();
public:
LocationTable loctab;
CgenClassTable(Classes, ostream &str);
void code();
CgenNodeP root();
CgenNode* root() { return nodes[0]; }
/* aquire an unused label index */
int alloc_label_index() { return label_count++; }
};
@ -82,7 +130,7 @@ private:
// method list including inherited and overidden methods
public:
CgenNode(Class_ c, Basicness bstatus, CgenClassTableP class_table);
CgenNode(Class_ c, Basicness bstatus);
void add_child(CgenNodeP child);
std::vector<CgenNode *> *get_children() { return &children; }

View File

@ -71,6 +71,14 @@ class E {
method_isvoid(x1: Object) : Bool {
isvoid x1
};
method_let1(x1: Int) : Object {
let x2 : Int <- x1 + 10 in
x2 <- x1
};
method_let2(x1: Int) : Object {
let x2 : Int <- x1 in
x2 <- x1 + 100
};
};
class Main inherits IO {