// Integer arithmetic compiler value (avalue) // definition. // // File: cavalue.cc // Author: course // Version: 2 // // This file defines the arithmetic compiler value type, // or avalue. #include "lexeme.h" // Defines lexemes, includes // avalue.h. // `Zero' avalue, which becomes value of empty program. // avalue zero_avalue; // The zero register $0. bool avalue::temporary_reg_usage [MAX_TEMPORARY_REGS]; bool avalue::permanent_reg_usage [MAX_PERMANENT_REGS]; // Allocate a temporary register: // static avalue allocate_temporary_reg () { for (int i = 0; i < MAX_TEMPORARY_REGS; i++) { if (! avalue::temporary_reg_usage[i]) { avalue::temporary_reg_usage[i] = true; avalue result; result.reg_type = avalue::TEMPORARY; result.reg_number = i; return result; } } error ("Out of Temporary Registers"); } // Free temporary register. Does nothing if called // with non-temporary register. // static void free_temporary_reg (avalue reg) { if (reg.reg_type == avalue::TEMPORARY) avalue::temporary_reg_usage[reg.reg_number] = false; } // Allocate a permanent register: // static avalue allocate_permanent_reg () { for (int i = 0; i < MAX_PERMANENT_REGS; i++) { if (! avalue::permanent_reg_usage[i]) { avalue::permanent_reg_usage[i] = true; avalue result; result.reg_type = avalue::PERMANENT; result.reg_number = i; return result; } } error ("Out of Permanent Registers"); } // Free all registers. // static void free_all_regs (void) { int i; for (i = 0; i < MAX_TEMPORARY_REGS; i++) avalue::temporary_reg_usage[i] = false; for (i = 0; i < MAX_PERMANENT_REGS; i++) avalue::permanent_reg_usage[i] = false; } // Produce an avalue from a lexeme, which must be a // LEX_NUMBER or a LEX_SYMBOL. // avalue evaluate (lexeme lex) { if (lex->type == LEX_NUMBER) return lex->value; else if (lex->type == LEX_SYMBOL) { if (lex->inited) return lex->value; else error ("Undefined symbol: ", lex->pname); } else assert (false); // We should never execute // this. } // Assign to a lexeme. Returns the value assigned. // avalue assign (lexeme lex, avalue v) { assert (lex->type == LEX_SYMBOL); if (! lex->inited ) { lex->value = allocate_permanent_reg(); lex->inited = true; } cout << "\tmove " << lex->value << ", " << v << "\n"; free_temporary_reg (v); return lex->value; } // Initialize avalues. // void init_avalues (void) { free_all_regs(); } // Perform arithmetic operation. // avalue avalue_operate (char * opcode, avalue src1, avalue src2) { avalue dest = allocate_temporary_reg(); cout << "\t" << opcode << " " << dest << ", " << src1 << ", " << src2 << "\n"; free_temporary_reg (src1); free_temporary_reg (src2); return dest; } // Output: s << x where s is typically cout. // ostream& operator << (ostream& s, avalue x) { if (x.reg_type == avalue::TEMPORARY) s << "$t" << x.reg_number; else if (x.reg_type == avalue::ZERO) s << "$0"; else if (x.reg_type == avalue::PERMANENT) s << "$s" << x.reg_number; return s; } // Input: s >> x where s is a istream. // istream& operator >> (istream& s, avalue& x) { long v; s >> v; x = allocate_temporary_reg(); cout << "\tli " << x << ", " << v << "\n"; return s; }