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
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
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
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
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
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
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
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
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
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
00174 spill_places_to_free->push_back(backup_place);
00175
00176
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
00188
00189
00190
00191
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
00207
00208
00209
00210
00211
00212
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
00230
00231
00232
00233
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
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