move_generator.cc

Go to the documentation of this file.
00001 /*!
00002         \file
00003         \author jaz
00004 */
00005 
00006 #include <lestes/backend_v2/debug/debug.hh>
00007 #include <lestes/backend_v2/intercode/pi.g.hh>
00008 #include <lestes/backend_v2/intercode/visitor_pi_pi2pi_operands.g.hh>
00009 #include <lestes/backend_v2/structs/pi_operands.g.hh>
00010 #include <lestes/md/instructions/pi_pi2ge_pi_template.g.hh>
00011 #include <lestes/md/instructions/instruction_group.g.hh>
00012 #include <lestes/md/instructions/tm_instr.g.hh>
00013 #include <lestes/md/types/tm_data_type.g.hh>
00014 #include <lestes/md/registers/move_generator.g.hh>
00015 
00016 package(lestes);
00017 package(md);
00018 package(registers);
00019 
00020 using namespace ::lestes::backend_v2::debug;
00021 using namespace ::lestes::backend_v2::intercode;
00022 using namespace ::lestes::msg;
00023 using namespace ::lestes::md::instructions;
00024 using namespace ::lestes::md::types;
00025 
00026 
00027 typedef list< ulint > ulint_list__type;
00028 typedef vector< ulint > ulint_vector__type;
00029 typedef set< ulint > id_set__type;
00030 typedef map< ulint, srp<tm_instr_op_base> > ulint2tm_instr_op_base__type;
00031 typedef map< ulint, srp<ge_operand> > ulint2ge_operand__type;
00032 typedef map< ulint, ulint > ulint2ulint__type;
00033 typedef list< srp < instruction_group_base > > instruction_group_base_list__type;
00034 typedef vector< srp < tm_instr_op_base > > tm_instr_op_base_vector__type;
00035 typedef vector< srp < ge_operand > > ge_operand_vector__type;
00036 typedef vector< srp < ge_pi > > ge_pi_vector__type;
00037 typedef set< srp < ge_pi > > ge_pi_set__type;
00038 typedef vector< srp < ge_sp > > ge_sp_vector__type;
00039 typedef vector< srp < pi_sp > > pi_sp_vector__type;
00040 
00041 
00042 declare_logger(log1);
00043 initialize_logger( log1, "move_generator", md_logger );
00044 
00045 /*!
00046         \brief Generates code that loads a value from a memory to a register.
00047         
00048         \param op_mem A memory operand.
00049         \param op_reg A pseudoregister operand.
00050         \param reg A target-machine register allocated to the pseudoregister operand.
00051         \return A load code.
00052 */
00053 ptr<ge_pi_vector__type> move_generator::generate_load_from_memory(ptr<ge_operand_mem> op_mem, ptr<ge_operand_reg> op_reg, ptr<tm_register_base> reg) {
00054         lassert(reg);
00055         return generate_move(op_mem,NULL,op_reg,reg);
00056 }
00057 
00058 /*!
00059         \brief Generates code that stores a value from a register to a memory.
00060         
00061         \param op_reg A pseudoregister operand.
00062         \param reg A target-machine register allocated to the pseudoregister operand.
00063         \param op_mem A memory operand.
00064         \return A store code.
00065 */
00066 ptr<ge_pi_vector__type> move_generator::generate_store_to_memory(ptr<ge_operand_reg> op_reg, ptr<tm_register_base> reg, ptr<ge_operand_mem> op_mem) {
00067         lassert(reg);
00068         return generate_move(op_reg,reg,op_mem,NULL);
00069 }
00070 
00071 
00072 /*!
00073         \brief Generates code that copies a value from a register to another register.
00074         
00075         \param op_reg_src A source pseudoregister operand.
00076         \param reg_src A target-machine register allocated to the source pseudoregister operand.
00077         \param op_reg_dst A destination pseudoregister operand.
00078         \param reg_dst A target-machine register allocated to the destination pseudoregister operand.
00079         \return A copy code.
00080 */
00081 ptr<ge_pi_vector__type> move_generator::generate_copy_to_register(ptr<ge_operand_reg> op_reg_src, ptr<tm_register_base> reg_src, ptr<ge_operand_reg> op_reg_dst, ptr<tm_register_base> reg_dst) {
00082         lassert(reg_src);
00083         lassert(reg_dst);
00084         return generate_move(op_reg_src, reg_src, op_reg_dst, reg_dst);
00085 }
00086 
00087 /*!
00088         \brief Generates code that moves value from a source operand to a destination operand.
00089         
00090         One of operands has to be pseudoregister operand with a target-machine register allocated. The target-machine register contains list of templates that defines
00091         possibilities how to move value of the register to other storage spaces (register, memory). The function selects one matching template and generates output move code.
00092         
00093         \param input_operand An input operand.
00094         \param input_reg If the input operand is pseudoregister, then parameter gets register allocated to the operand. NULL otherwise.
00095         \param output_operand An output operand.
00096         \param output_reg If the output operand is pseudoregister, then parameter gets register allocated to the operand. NULL otherwise.
00097         \return A copy code.
00098 */
00099 ptr<ge_pi_vector__type> move_generator::generate_move(ptr<ge_operand> input_op, ptr<tm_register_base> input_reg, ptr<ge_operand> output_op, ptr<tm_register_base> output_reg) {
00100         log1 << "generate_move - start\n" << eolog;
00101         lassert(input_op);
00102         lassert(!input_reg || input_reg->bitwidth_get()>=input_op->type_get()->bitwidth_get());
00103         lassert(output_op);
00104         lassert(!output_reg || output_reg->bitwidth_get()>=output_op->type_get()->bitwidth_get());
00105         
00106         ptr<ulint_vector__type> selected_instrs = ulint_vector__type::create();
00107         ptr<ulint2tm_instr_op_base__type> selected_operands = ulint2tm_instr_op_base__type::create();
00108         ptr<ulint2ulint__type> selected_op_types = ulint2ulint__type::create();
00109         
00110         ptr<id_set__type> move_templates = input_reg ? input_reg->move_templates_get() : output_reg->move_templates_get();
00111         
00112         for(id_set__type::iterator it = move_templates->begin(); it!=move_templates->end(); ++it) {
00113                 ptr<pi_pi2ge_pi_template> pat = pi_pi2ge_pi_template::instance(*it);
00114                 
00115                 if ( find_consistent_instructions(input_op,input_reg,output_op,output_reg,pat,selected_instrs,selected_operands,selected_op_types,0) ) {
00116                         log1 << "generate_move - end 1 ( move generated successfuly )\n" << eolog;
00117                         return generate_ge_code(input_op,input_reg,output_op,output_reg,pat,selected_instrs,selected_op_types);
00118                 }
00119         }
00120         
00121         lassert(false);
00122         log1 << "generate_move - end ( no consistent template found )\n" << eolog;
00123         return NULL;
00124         
00125 }
00126 
00127 /*!
00128         \brief Gets list of selected target machine instruction ids for each instruction_group and generates output ge-code.
00129         
00130         \param input_operand An input operand.
00131         \param input_reg If the input operand is pseudoregister, then parameter gets register allocated to the operand. NULL otherwise.
00132         \param output_operand An output operand.
00133         \param output_reg If the output operand is pseudoregister, then parameter gets register allocated to the operand. NULL otherwise.
00134         \param pat A list of instruction_group instances.
00135         \param choosed_instructions Selected instructions.
00136         \param  choosed_op_types Types of operands used within output code.
00137         \return Vector of ge-pi instructions.
00138 */
00139 ptr<ge_pi_vector__type> move_generator::generate_ge_code(ptr<ge_operand> input_op, ptr<tm_register_base> input_reg, ptr<ge_operand> output_op, ptr<tm_register_base> output_reg, ptr<pi_pi2ge_pi_template_base> pat, ptr<ulint_vector__type> choosed_instrs,  ptr<ulint2ulint__type>) {
00140         log1 << "generate_ge_code - start\n" << eolog;
00141         
00142         ptr<ge_pi_vector__type> output = ge_pi_vector__type::create();
00143         ptr<ulint2ge_operand__type> tm_op2ge_op = ulint2ge_operand__type::create();     
00144         
00145         ptr<ge_pi> prev;
00146         
00147         /*
00148                 Go throught the pi2ge template's instruction templates and instantiate them according to the selected versions.
00149         */
00150         for(ulint i=0; i<pat->instruction_groups_get()->size(); ++i) {
00151                 //The instruction template
00152                 ptr<instruction_group_base> instr_group = (*pat->instruction_groups_get())[i];
00153                 //The selected version.
00154                 ptr<tm_instr_base> instr_version = tm_instr::instance((*choosed_instrs)[i]);
00155                                 
00156                 //Output ge-code
00157                 ptr<ge_pi> ge = ge_pi::create(instr_version,NULL);
00158                 
00159                 ptr<ge_operand_vector__type> input_ops = ge->operands_input_get();
00160                 ptr<ge_operand_vector__type> output_ops = ge->operands_output_get();
00161                 ptr<ge_pi_set__type> dependencies = ge->dependencies_get();
00162                 
00163                 if ( prev ) {
00164                         /*
00165                                 Set dependence on a preceeding output ge-pseudoinstruction of the teplate in order to force the output
00166                                 code to be ordered in the same way as instruction templates in the input template.      
00167                         */
00168                         
00169                         dependencies->insert(prev);
00170                 }
00171                 
00172                 //Input operands.
00173                 for(ulint j=0; j<instr_group->input_operand_pids_get()->size(); ++j) {  
00174                         //Pid of an output ge-operand that is passed to this input opperand from a preceeding ge-pseudoinstruction.
00175                         ulint operand_pid = (*instr_group->input_operand_pids_get())[j];
00176                         //Id of an input operand of the selected target instruction.
00177                         ulint operand_ref = (*instr_group->input_operand_refs_get())[j];
00178 
00179                         ptr<tm_instr_op_base> tm_op = (*instr_version->operands_input_get())[j];
00180                         lassert(tm_op->id_get()==operand_ref);
00181                         
00182                         ptr<ge_operand> ge_op;
00183                         
00184                         if ( operand_pid <= PIN_4 ) {
00185                                 //The operand coresponds to the input pi-operand of the input pi-pseudoinstruction.
00186                                 ulint i_op_pos = operand_pid - PIN_1;
00187                                 
00188                                 lassert(i_op_pos==0);
00189                                 
00190                                 ge_op = input_op;
00191                                 
00192                                 if ( input_reg ) {
00193                                         (*ge_op.dncast<ge_operand_reg>()->assigned_registers_get())[ge] = input_reg->id_get();
00194                                 }
00195                         } else {
00196                                 //The operand's source is an output operand of preceeding ge-pseudoinstruction. 
00197                                 //Find the output operand.
00198                                 ulint2ge_operand__type::iterator it_ge = tm_op2ge_op->find(operand_pid);
00199                                 lassert(it_ge!=tm_op2ge_op->end());
00200                                 ge_op = it_ge->second;
00201                         }
00202                         
00203                         
00204                         input_ops->push_back(ge_op);
00205                 }       
00206                 
00207                 //Output operands.
00208                 for(ulint j=0; j<instr_group->output_operand_pids_get()->size(); ++j) { 
00209                         //Pid of an output ge-operand.
00210                         ulint operand_pid = (*instr_group->output_operand_pids_get())[j];
00211                         //Id of an output operand of the selected target instruction.
00212                         ulint operand_ref = (*instr_group->output_operand_refs_get())[j];
00213 
00214                         ptr<ge_operand> ge_op;
00215                                                 
00216                         if ( operand_pid <= POUT_4 ) {
00217                                 //The operand coresponds to the output pi-operand of the input pi-pseudoinstruction.
00218                                 ulint i_op_pos = operand_pid - POUT_1;
00219                                 
00220                                 lassert(i_op_pos==0);
00221 
00222                                 //Convert pi-operand to ge-operand
00223                                 ge_op = output_op;
00224                                 
00225                                 if ( output_reg ) {
00226                                         (*ge_op.dncast<ge_operand_reg>()->assigned_registers_get())[ge] = output_reg->id_get();
00227                                 }       
00228                         } else {
00229                                 //Regular output operand need to be generated.
00230                                 ptr<tm_instr_op_base> tm_op = (*instr_version->operands_output_get())[j];
00231                                 lassert(tm_op->id_get()==operand_ref);
00232                                 
00233                                 //Data type of the operand.
00234                                 ulint type;
00235                                 
00236                                 if ( tm_op->allowed_types_get()->size()==1 ) {
00237                                         //The operand has only single type allowed.
00238                                         type = *tm_op->allowed_types_get()->begin();
00239                                 } else {
00240                                         //The operand has multiple types allowed.
00241                                         lassert(instr_group->input_operand_pids_get()->size()>0);
00242                                 
00243                                         type = input_op->type_get()->id_get();
00244                                         
00245                                         //Check that the type is among allowed ones.
00246                                         lassert(tm_op->allowed_types_get()->find(type)!=tm_op->allowed_types_get()->end());
00247                                 }
00248                                 
00249                                 //Convert operand of the tm_inst template to ge-operand.
00250                                 ge_op = tm_op->convert_to_ge(tm_dt_simple::instance((::lestes::md::types::dt_id_type)type));
00251                                  
00252                                 tm_op2ge_op->insert(::std::pair<ulint, srp<ge_operand> >(operand_pid,ge_op));
00253                         }
00254                         
00255                         //Set origin of the operand.
00256                         ge_op->origin_set(ge);
00257                         
00258                         //add operand to list of output operands
00259                         output_ops->push_back(ge_op);
00260                 }
00261                 prev = ge;
00262                 output->push_back(ge);
00263         }
00264         
00265         log1 << "generate_ge_code - end\n" << eolog;
00266         
00267         return output;
00268 }
00269 
00270 /*!
00271         \brief Recursively traverses list of instruction_groups and chooses one instruction from each instruction_group that is consistent with the ones previously choosed.
00272 
00273         \param input_operand An input operand.
00274         \param input_reg If the input operand is pseudoregister, then parameter gets register allocated to the operand. NULL otherwise.
00275         \param output_operand An output operand.
00276         \param output_reg If the output operand is pseudoregister, then parameter gets register allocated to the operand. NULL otherwise.
00277         \param pat An examinated list of instruction_groups.
00278         \param selected_instrs A list of selected instructions from preceeding steps.
00279         \param selected_operands A list of operands of selected instructions from preceding steps.
00280         \param selected_op_types A list of datatypes of selected_operands.
00281         \param curr_instrs_pat_idx An index of the currentky examinated instruction_group.
00282         \return False if no one instruction from the examinated instruction_group is consistent with the ones choosed in previous steps.
00283 */
00284 bool move_generator::find_consistent_instructions(ptr<ge_operand> input_op, ptr<tm_register_base> input_reg, ptr<ge_operand> output_op, ptr<tm_register_base> output_reg, ptr<pi_pi2ge_pi_template_base> pat, ptr<ulint_vector__type> selected_instrs, ptr<ulint2tm_instr_op_base__type> selected_operands, ptr<ulint2ulint__type> selected_op_types, ulint curr_instrs_pat_idx) {
00285         log1 << "find_consisten_instructions - start\n" << eolog;
00286         
00287         if ( curr_instrs_pat_idx==pat->instruction_groups_get()->size() ) {
00288                 //All the instruction templates has been visited. Terminate recursion.
00289                 log1 << "find_consisten_instructions - end 1\n" << eolog;
00290                 return true;
00291         }
00292         
00293         //Inspected instruction template.
00294         ptr<instruction_group_base> instr_group = (*pat->instruction_groups_get())[curr_instrs_pat_idx];
00295         
00296         //Go through possible instruction versions and find the suitable one.
00297         for(ulint i=0; i<instr_group->instructions_get()->size(); ++i) {
00298                 ulint instr_version_id = (*instr_group->instructions_get())[i];
00299                 ptr<tm_instr_base> instr_version = tm_instr::instance(instr_version_id);
00300                 
00301                 if ( !is_instruction_consistent(input_op,input_reg,output_op,output_reg,instr_group,instr_version,selected_operands,selected_op_types) ) {
00302                         //The instruction is not suitable.
00303                         continue;
00304                 }
00305                 
00306                 //Add operands of the suitable instruction version to the selected_operands list.
00307                 add_selected_operands(input_op,output_op,instr_group,instr_version,selected_operands,selected_op_types);
00308                 selected_instrs->push_back(instr_version_id);
00309                 
00310                 //Check whether exists version of all consequent instruction templates that are suitable with the instructio version.
00311                 if ( find_consistent_instructions(input_op,input_reg,output_op,output_reg,pat,selected_instrs,selected_operands,selected_op_types,curr_instrs_pat_idx+1) ) {
00312                         //Yes, they exists.
00313                         log1 << "find_consisten_instructions - end 2 (good)\n" << eolog;
00314                         return true;
00315                 }
00316                 
00317                 //No, for some of the sonsequent instructions templates don't exist suitable instruction versions. Rollback and try another version.
00318                 remove_selected_operands(instr_group,selected_operands,selected_op_types);
00319                 selected_instrs->pop_back();
00320         }
00321         
00322         log1 << "find_consisten_instructions - end (bad)\n" << eolog;
00323         return false;
00324 }
00325 
00326 
00327 /*!
00328         \brief Checks whether a tm_instr is compatible with operands that are passed to it from preceding instructions.
00329 
00330         \param input_operand An input operand.
00331         \param input_reg If the input operand is pseudoregister, then parameter gets register allocated to the operand. NULL otherwise.
00332         \param output_operand An output operand.
00333         \param output_reg If the output operand is pseudoregister, then parameter gets register allocated to the operand. NULL otherwise.       
00334         \param instr_group A group of instructions.
00335         \param instr_version A instruction to be tested.
00336         \param pi A source pi-pseudoinstruction.
00337         \param selected_operands A list of operands of preceding instructions.
00338         \param selected_types A list of datatypes of the selected_operands.
00339         \return True if the instruction is consistent. False otherwise.
00340 */
00341 bool move_generator::is_instruction_consistent(ptr<ge_operand> input_op, ptr<tm_register_base> input_reg, ptr<ge_operand> output_op, ptr<tm_register_base> output_reg,ptr<instruction_group_base> instr_group, ptr<tm_instr_base> instr_version, ptr<ulint2tm_instr_op_base__type> selected_operands,ptr<ulint2ulint__type> selected_types) {
00342         log1 << "is_instruction_consistent - start (tm_instr=" << instr_version->id_get() << ")\n" << eolog;
00343         
00344         /*
00345                 Go through input operands and check that are compatible with selected output operands of preceeding instructions.
00346         */
00347         for(ulint i=0; i<instr_group->input_operand_pids_get()->size(); ++i) {  
00348                 ulint operand_pid = (*instr_group->input_operand_pids_get())[i];
00349                 ulint operand_ref = (*instr_group->input_operand_refs_get())[i];
00350                 
00351                 lassert(operand_pid<=PIN_4 || operand_pid>POUT_4 );
00352                 
00353                 ptr<tm_instr_op_base> op = find_op_by_id(instr_version->operands_input_get(),operand_ref);
00354                 
00355                 if ( operand_pid <= PIN_4 ) {
00356                         //The operand coresponds to the input pi-operand of the input pi-pseudoinstruction.
00357                         ulint i_op_pos = operand_pid - PIN_1;
00358                         
00359                         lassert(i_op_pos==0);
00360                         
00361                         if ( !is_operand_compatible1(op,input_op,input_op->type_get()->id_get(),input_reg) ) {
00362                                 log1 << "is_instruction_consistent - end 2 (bad)\n" << eolog;
00363                                 return false;
00364                         }
00365                          
00366                 } else {
00367                         //Check compatibility with selected output operands of preceeding instructions.
00368                         ulint2tm_instr_op_base__type::iterator it_op = selected_operands->find(operand_pid);
00369                         ulint2ulint__type::iterator it_t = selected_types->find(operand_pid);
00370                         
00371                         lassert(it_op!=selected_operands->end());
00372                         lassert(it_t!=selected_types->end());
00373                         
00374                         if ( !is_operand_compatible2(op,it_op->second,it_t->second) ) {
00375                                 log1 << "is_instruction_consistent - end 3 (bad)\n" << eolog;
00376                                 return false;
00377                         }
00378                 }
00379         }
00380         
00381         /*
00382                 Go through output operands and check that are compatible with output operands of the pi-pseudoinstruction.
00383         */
00384         for(ulint i=0; i<instr_group->output_operand_pids_get()->size(); ++i) { 
00385                 ulint operand_ref = (*instr_group->output_operand_refs_get())[i];
00386                 ulint operand_pid = (*instr_group->output_operand_pids_get())[i];
00387                 
00388                 lassert(operand_pid > PIN_4);
00389                 
00390                 if ( operand_pid>=POUT_1 && operand_pid <= POUT_4 ) {
00391                         ulint i_op_pos = operand_pid - POUT_1;
00392                         lassert(i_op_pos==0);
00393                         
00394                         ptr<tm_instr_op_base> op = find_op_by_id(instr_version->operands_output_get(),operand_ref);
00395                         
00396                         if ( !is_operand_compatible1(op,output_op,output_op->type_get()->id_get(),output_reg) ) {
00397                                 log1 << "is_instruction_consistent - end 4 (bad)\n" << eolog;
00398                                 return false;
00399                         }
00400                          
00401                 } 
00402         }
00403         
00404         log1 << "is_instruction_consistent - end\n" << eolog;
00405         return true;
00406 }
00407 
00408 /*!
00409         \brief Checks whether a tm_instr_op is compatible with a pi_operand (i.e. the tm_instr_op can be converted to the pi_operand).
00410         
00411         \param instr_op A tm_instr_op instance.
00412         \param pi_op A pi_operand instance.
00413         \param pi_type A datataype of the pi_operand.
00414         \return True if operands are compatible. False otherwise.
00415 */
00416 bool move_generator::is_operand_compatible1(ptr<tm_instr_op_base> instr_op, ptr<ge_operand> ge_op, ulint type, ptr<tm_register_base> reg) {
00417         log1 << "is_operand_compatible1 - start (instr_op=" << instr_op->id_get() << ")\n" << eolog;
00418         
00419         if ( instr_op->allowed_types_get()->find(type)==instr_op->allowed_types_get()->end() ) {
00420                 log1 << "is_operand_compatible1 - end1 (bad)\n" << eolog;
00421                 return false;
00422         }
00423         
00424         ulint kind1 = instr_op->kind_get();
00425         ulint kind2 = ge_op->kind_get();
00426         
00427         if ( kind1==tm_instr_op_base::REGISTER ) {
00428                 if ( kind2!=ge_operand::REGISTER ) {
00429                         return false;
00430                 }
00431                 
00432                 lassert(reg);
00433                 
00434                 ptr<tm_instr_op_reg_base> tmp_op = instr_op.dncast<tm_instr_op_reg_base>();
00435                 
00436                 return tmp_op->allowed_registers_get()->find(reg->id_get())!=tmp_op->allowed_registers_get()->end();
00437         }
00438         
00439         
00440         if ( ( kind1==tm_instr_op_base::IMMEDIATE && kind2!=ge_operand::IMMEDIATE ) ||
00441                  ( kind1==tm_instr_op_base::MEMORY && kind2!=ge_operand::MEMORY ) ) {
00442                  log1 << "is_operand_compatible1 - end2 (bad)\n" << eolog;
00443                  return false;
00444         }
00445          
00446         log1 << "is_operand_compatible1 - end\n" << eolog;
00447         return true;
00448 }
00449 
00450 /*!
00451         \brief Checks whether two operands have the same kind, nonempty intersection of allowed datatypes and nonempty set of allowed registers in case that the kind of the operands is register.
00452         
00453         \param op1 An operand.
00454         \param op2 An operand.
00455         \type type A type of the op2.
00456         \return True it the operands are compatible. False otherwise.
00457 */
00458 bool move_generator::is_operand_compatible2(ptr<tm_instr_op_base> op1, ptr<tm_instr_op_base> op2, ulint type) {
00459         log1 << "is_operand_compatible2 - start (instr_op=" << op1->id_get() << ")\n" << eolog;
00460         
00461         if ( op1->allowed_types_get()->find(type)==op1->allowed_types_get()->end() ) {
00462                 log1 << "is_operand_compatible2 - end 1 (bad)\n" << eolog;
00463                 return false;
00464         }
00465         
00466         if ( op1->kind_get()!=op2->kind_get() ) {
00467                 log1 << "is_operand_compatible2 - end 2 (bad)\n" << eolog;
00468                 return false;
00469         }
00470         
00471         if ( op1->kind_get()==tm_instr_op_base::REGISTER ) {
00472                 ptr<id_set__type> allowed_regs1 = op1.dncast<tm_instr_op_reg_base>()->allowed_registers_get();
00473                 ptr<id_set__type> allowed_regs2 = op2.dncast<tm_instr_op_reg_base>()->allowed_registers_get();
00474                 ptr<id_set__type> allowed_intersec = id_set__type::create();
00475                 
00476                 ::std::set_intersection(
00477                         allowed_regs1->begin(),
00478                         allowed_regs1->end(),
00479                         allowed_regs2->begin(),
00480                         allowed_regs2->end(),
00481                         ::std::inserter(*allowed_intersec, allowed_intersec->begin()));
00482                         
00483                 
00484                 if ( allowed_intersec->size()!=0 ) {
00485                         log1 << "is_operand_compatible2 - end 3 (good)\n" << eolog;
00486                         return true;
00487                 }
00488         }
00489         
00490         log1 << "is_operand_compatible2 - end (bad)\n" << eolog;
00491         return false;
00492 }
00493 
00494 /*!
00495         \brief Adds instruction's operands to a list of selected operands.
00496         
00497         \param instr_group A group of instructions.
00498         \param instr_version A parent instruction of the operands.
00499         \param pi A source pi-pseudoinstruction.
00500         \param selected_operands A list of operands of preceding instructions.
00501         \param selected_types A list of datatypes of the selected_operands.
00502 */
00503 void move_generator::add_selected_operands(ptr<ge_operand> input_op,ptr<ge_operand>, ptr<instruction_group_base> instr_group, ptr<tm_instr_base> instr_version, ptr<ulint2tm_instr_op_base__type> selected_operands,ptr<ulint2ulint__type> selected_types) {
00504         
00505         // Add output operands of the selected instruction version to the selected_operands list.  The types of the selected operands add to the selected_types list. 
00506         for(ulint i=0; i<instr_group->output_operand_pids_get()->size(); ++i) {
00507                 ulint operand_pid = (*instr_group->output_operand_pids_get())[i];
00508                 ulint operand_ref = (*instr_group->output_operand_refs_get())[i];
00509                 
00510                 lassert(operand_pid > PIN_4);
00511                 
00512                 ptr<tm_instr_op_base> op = find_op_by_id(instr_version->operands_output_get(),operand_ref);
00513                 selected_operands->insert(::std::pair<ulint, srp<tm_instr_op_base> >(operand_pid, op));         
00514                 
00515                 ulint type;
00516                 
00517                 type = input_op->type_get()->id_get();
00518                 
00519                 selected_types->insert(::std::pair<ulint, ulint>(operand_pid, type));           
00520         }
00521 }
00522 
00523 /*!
00524         \brief Removes instruction's operands to a list of selected operands.
00525         
00526         \param instr_group A group of instructions.
00527         \param selected_operands A list of operands of preceding instructions.
00528         \param selected_types A list of datatypes of the selected_operands.
00529 */
00530 void move_generator::remove_selected_operands(ptr<instruction_group_base> instr_group, ptr<ulint2tm_instr_op_base__type> selected_operands, ptr<ulint2ulint__type> selected_types) {
00531         
00532         for(ulint i=0; i<instr_group->output_operand_pids_get()->size(); ++i) {
00533                 ulint operand_pid = (*instr_group->output_operand_pids_get())[i];
00534                 selected_operands->erase(operand_pid);          
00535                 selected_types->erase(operand_pid);             
00536         }
00537 }
00538 
00539 /*!
00540         \brief Traverses a list of operands and returns an operand with given id.
00541         
00542         \param list A list of operands.
00543         \param id An id of operand.
00544         \return A operand.
00545 */
00546 ptr<tm_instr_op_base> move_generator::find_op_by_id(ptr<tm_instr_op_base_vector__type> list, ulint id) {
00547         for(uint i=0; i<list->size(); ++i) {
00548                 ptr<tm_instr_op_base> op = (*list)[i];
00549                 
00550                 if ( op->id_get()==id ) {
00551                         return op;
00552                 }
00553         }
00554         
00555         return NULL;
00556 }
00557 
00558 
00559 end_package(registers);
00560 end_package(md);
00561 end_package(lestes);
00562 

Generated on Mon Feb 12 18:22:41 2007 for lestes by doxygen 1.5.1-20070107