simple_spillgen.cc

Go to the documentation of this file.
00001 #include <lestes/backend_v2/structs/func_data.g.hh>
00002 #include <lestes/backend_v2/intercode/ge.g.hh>
00003 #include <lestes/backend_v2/intercode/pi.g.hh>
00004 #include <lestes/backend_v2/workers/simple_spillgen.g.hh>
00005 #include <lestes/md/mem/mem_alloc_manager.g.hh>
00006 #include <lestes/md/registers/tm_register.g.hh>
00007 #include <lestes/md/registers/move_generator.g.hh>
00008 #include <lestes/md/instructions/tm_instr.g.hh>
00009 #include <lestes/md/types/tm_data_type.g.hh>
00010 #include <lestes/lang/cplus/sem/ss_declaration.g.hh>
00011 #include <lestes/backend_v2/debug/debug.hh>
00012 #include <sstream>
00013 
00014 package(lestes);
00015 package(backend_v2);
00016 package(workers);
00017 
00018 using namespace ::lestes::backend_v2::debug;
00019 using namespace ::lestes::backend_v2::structs;
00020 using namespace ::lestes::backend_v2::intercode;
00021 using namespace ::lestes::md::instructions;
00022 using namespace ::lestes::md::mem;
00023 using namespace ::lestes::md::types;
00024 using namespace ::lestes::md::registers;
00025 using namespace ::lestes::lang::cplus::sem;
00026 
00027 typedef set< srp<ge_pi> > ge_pi_set__type;
00028 typedef set<ulint> ulint_set__type;
00029 typedef list< srp<ge_pi> > ge_pi_list__type;
00030 typedef vector< srp<ge_pi> > ge_pi_vector__type;
00031 typedef vector< srp<ge_operand> > ge_operand_vector__type;
00032 typedef list<srp<pi_mem_factory> > mf_list__type;
00033 typedef map<srp<ge_operand_reg>,srp<pi_mem_factory> > op2mf__type;
00034 typedef map<ulint,lstring> id2lstring__type;
00035 
00036 /*!
00037         \brief Performs spill-code generation.
00038 */
00039 void simple_spillgen::process() {
00040 
00041         ptr<ge_pi_list__type> body = data_get()->ge_body_get();
00042         
00043         ptr<move_generator> move_gen = move_generator::create();
00044         
00045         ptr<mf_list__type> free_spill_places = mf_list__type::create();
00046         ptr<mf_list__type> spill_places_to_free = mf_list__type::create();
00047         ptr<op2mf__type> used_spill_places = op2mf__type::create();
00048         
00049         for(ge_pi_list__type::iterator it = body->begin(); it!=body->end(); ++it) {
00050                 ptr<ge_pi> ge = *it;
00051                 ptr<tm_instr_base> tm = ge->instruction_get();
00052                 
00053                 if ( !tm ) {
00054                         continue;
00055                 }
00056                 
00057                 ge_pi_list__type::iterator it_next = it;
00058                 ++it_next;
00059                 
00060                 ulint i_pos = 0;
00061                 ptr<ge_operand_vector__type> operands = ge->operands_input_get();
00062                 for(ge_operand_vector__type::iterator it_op = operands->begin(); it_op!=operands->end(); ++it_op, ++i_pos) {
00063                         if ( (*it_op)->kind_get()!=ge_operand::REGISTER ) {
00064                                 continue;
00065                         }
00066                         
00067                         ptr<ge_operand_reg> op = (*it_op).dncast<ge_operand_reg>();
00068                         
00069                         if ( op->assigned_registers_get()->find(ge)!=op->assigned_registers_get()->end() ) {
00070                                 continue;
00071                         }
00072                         
00073                         ptr<tm_instr_op_reg_base> tmop = (*tm->operands_input_get())[i_pos].dncast<tm_instr_op_reg_base>();
00074                         ptr<tm_register> reg = pick_reg_by_data_type(tmop->allowed_registers_get(),op->type_get()->id_get());
00075                         
00076                         //Backup the register's value.
00077                         ptr<ge_operand_reg> backuped_reg = ge_operand_reg::create(op->type_get(),NULL,NULL);
00078                         ptr<pi_mem_factory> backup_place = get_free_spill_place(free_spill_places,op->type_get());
00079                         ptr<ge_operand_mem> backup_mem = backup_place->get_ge_mem(NULL);
00080                         ptr<ge_pi_vector__type> code = move_gen->generate_store_to_memory(backuped_reg,reg,backup_mem);
00081                         body->insert(it,code->begin(),code->end());
00082 
00083 #ifdef BACKEND_V2_DEBUG         
00084                         ::std::ostringstream oss1;
00085                         oss1 << "backup code (ge_pi=" << ge->uid_get() << ")";
00086                         set_instruction_property(code,ge_pi::PROPERTY_SPILLGEN_INFO,oss1.str());
00087 #endif
00088                         
00089                         //Load the spilled operand's value.
00090                         ptr<pi_mem_factory> spill_place = (*used_spill_places)[op];
00091                         lassert(spill_place);
00092                         ptr<ge_operand_mem> spill_mem = spill_place->get_ge_mem(NULL);
00093                         code = move_gen->generate_load_from_memory(spill_mem,op,reg);
00094                         body->insert(it,code->begin(),code->end());
00095 
00096 #ifdef BACKEND_V2_DEBUG         
00097                         ::std::ostringstream oss2;
00098                         oss2 << "load code (ge_pi=" << ge->uid_get() << ")";
00099                         set_instruction_property(code,ge_pi::PROPERTY_SPILLGEN_INFO,oss2.str());
00100 #endif
00101                         
00102                         //Restore the register's value.
00103                         code = move_gen->generate_load_from_memory(backup_mem,backuped_reg,reg);
00104                         body->insert(it_next,code->begin(),code->end());
00105 
00106 #ifdef BACKEND_V2_DEBUG         
00107                         ::std::ostringstream oss3;
00108                         oss3 << "restore code (ge_pi=" << ge->uid_get() << ")";
00109                         set_instruction_property(code,ge_pi::PROPERTY_SPILLGEN_INFO,oss3.str());
00110 #endif
00111                         
00112                         //Free spill places
00113                         spill_places_to_free->push_back(spill_place);
00114                         (*used_spill_places)[op] = NULL;
00115                         spill_places_to_free->push_back(backup_place);
00116                         
00117                         //Assign the register to the operand.
00118                         (*op->assigned_registers_get())[ge] = reg->id_get();
00119                 }
00120                 
00121                 i_pos = 0;
00122                 operands = ge->operands_output_get();
00123                 for(ge_operand_vector__type::iterator it_op = operands->begin(); it_op!=operands->end(); ++it_op, ++i_pos) {
00124                         if ( (*it_op)->kind_get()!=ge_operand::REGISTER ) {
00125                                 continue;
00126                         }
00127                         
00128                         ptr<ge_operand_reg> op = (*it_op).dncast<ge_operand_reg>();
00129                         
00130                         if ( op->assigned_registers_get()->find(ge)!=op->assigned_registers_get()->end() ) {
00131                                 continue;
00132                         }
00133                         
00134                         ptr<tm_instr_op_reg_base> tmop = (*tm->operands_output_get())[i_pos].dncast<tm_instr_op_reg_base>();
00135                         ptr<tm_register> reg = pick_reg_by_data_type(tmop->allowed_registers_get(),op->type_get()->id_get());
00136                         
00137                         //Backup the register's value.
00138                         ptr<ge_operand_reg> backuped_reg = ge_operand_reg::create(op->type_get(),NULL,NULL);
00139                         ptr<pi_mem_factory> backup_place = get_free_spill_place(free_spill_places,op->type_get());
00140                         ptr<ge_operand_mem> backup_mem = backup_place->get_ge_mem(NULL);
00141                         ptr<ge_pi_vector__type> code = move_gen->generate_store_to_memory(backuped_reg,reg,backup_mem);
00142                         body->insert(it,code->begin(),code->end());
00143 
00144 #ifdef BACKEND_V2_DEBUG         
00145                         ::std::ostringstream oss1;
00146                         oss1 << "backup code (ge_pi=" << ge->uid_get() << ")";
00147                         set_instruction_property(code,ge_pi::PROPERTY_SPILLGEN_INFO,oss1.str());
00148 #endif
00149                         
00150                         //Store the spilled operand's value.
00151                         ptr<pi_mem_factory> spill_place = get_free_spill_place(free_spill_places,op->type_get());
00152                         (*used_spill_places)[op] = spill_place;
00153                         ptr<ge_operand_mem> spill_mem = spill_place->get_ge_mem(NULL);
00154                         code = move_gen->generate_store_to_memory(op,reg,spill_mem);
00155                         body->insert(it_next,code->begin(),code->end());
00156 
00157 #ifdef BACKEND_V2_DEBUG         
00158                         ::std::ostringstream oss2;
00159                         oss2 << "store code (ge_pi=" << ge->uid_get() << ")";
00160                         set_instruction_property(code,ge_pi::PROPERTY_SPILLGEN_INFO,oss2.str());
00161 #endif
00162                         
00163                         //Restore the register's value.
00164                         code = move_gen->generate_load_from_memory(backup_mem,backuped_reg,reg);
00165                         body->insert(it_next,code->begin(),code->end());
00166 
00167 #ifdef BACKEND_V2_DEBUG         
00168                         ::std::ostringstream oss3;
00169                         oss3 << "restore code (ge_pi=" << ge->uid_get() << ")";
00170                         set_instruction_property(code,ge_pi::PROPERTY_SPILLGEN_INFO,oss3.str());
00171 #endif
00172                         
00173                         //Free spill places
00174                         spill_places_to_free->push_back(backup_place);
00175                         
00176                         //Assign the register to the operand.
00177                         (*op->assigned_registers_get())[ge] = reg->id_get();
00178                 }
00179         
00180                 free_spill_places->insert(free_spill_places->begin(),spill_places_to_free->begin(),spill_places_to_free->end());
00181                 spill_places_to_free->clear();
00182         }
00183                 
00184 }
00185 
00186 /*!
00187         \brief Adds a custom property value to a list of pseudoinstructions.
00188         
00189         \param instrs The list.
00190         \param property_id A id of the property.
00191         \param property_Value The value.
00192 */
00193 void simple_spillgen::set_instruction_property(ptr<ge_pi_vector__type> instrs,ulint property_id,lstring property_value) {
00194         for(ge_pi_vector__type::iterator it = instrs->begin(); it!=instrs->end(); ++it) {       
00195                 ptr<ge_pi> ge = *it;
00196                 
00197                 if ( !ge->properties_get() ) {
00198                         ge->properties_set(id2lstring__type::create());
00199                 }
00200                 
00201                 (*ge->properties_get())[property_id] = property_value;
00202         }
00203 }       
00204 
00205 /*!
00206         \brief Picks a spill-place from a list of free spill-places that is compatible with a data type.
00207         
00208         If no free spill-pace is available then it allocates a new one.
00209         
00210         \param mfs The list of free spill-places.
00211         \param type The data type.
00212         \return The spill-place.
00213 */
00214 ptr<pi_mem_factory> simple_spillgen::get_free_spill_place(ptr<mf_list__type> mfs,ptr<tm_data_type_base> type) {
00215         ulint bitwidth = type->bitwidth_get();
00216         
00217         for(mf_list__type::iterator it = mfs->begin(); it!=mfs->end(); ++it) {
00218                 ptr<pi_mem_factory> mf = *it;
00219                 if ( mf->type_get()->bitwidth_get() >= bitwidth ) {
00220                         mfs->erase(it);
00221                         return mf;
00222                 }
00223         }
00224         
00225         return mem_alloc_manager::instance()->allocate_local_tmp(data_get()->function_decl_get(),type);
00226 }
00227 
00228 /*!
00229         \brief Picks a register from set of registers that is compatible with a data type.
00230         
00231         \param reg_set The set.
00232         \param type_id An id of the data type.
00233         \return The register.
00234 */
00235 ptr<tm_register> simple_spillgen::pick_reg_by_data_type(ptr<ulint_set__type> reg_set, ulint type_id) {
00236         for(ulint_set__type::iterator it = reg_set->begin(); it!=reg_set->end(); ++it) {
00237                 ptr<tm_register> reg =  tm_register::instance(*it);
00238                 
00239                 if ( reg->compatible_types_get()->find(type_id)!=reg->compatible_types_get()->end() ) {
00240                         return reg;
00241                 }
00242         }
00243         
00244         lassert(false);
00245         return NULL;
00246 }
00247 
00248 
00249 /*!
00250         \brief Returns data of the processed function with spill-code included.
00251 */
00252 ptr<func_data> simple_spillgen::get_result() {
00253         return data_get();
00254 }
00255 
00256 end_package(workers);
00257 end_package(backend_v2);
00258 end_package(lestes);
00259 

Generated on Mon Feb 12 18:23:15 2007 for lestes by doxygen 1.5.1-20070107