diff --git a/assignments/PA5/cgen.cc b/assignments/PA5/cgen.cc index 36887e0..5046abf 100644 --- a/assignments/PA5/cgen.cc +++ b/assignments/PA5/cgen.cc @@ -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) { diff --git a/assignments/PA5/cgen.h b/assignments/PA5/cgen.h index 4f71f27..6ef275e 100644 --- a/assignments/PA5/cgen.h +++ b/assignments/PA5/cgen.h @@ -9,7 +9,9 @@ #include #include -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> MethodListT; typedef std::vector 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 table; + std::vector 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 { private: std::vector 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 *get_children() { return &children; } diff --git a/assignments/PA5/example.cl b/assignments/PA5/example.cl index fbf83ba..84d148e 100644 --- a/assignments/PA5/example.cl +++ b/assignments/PA5/example.cl @@ -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 {