00001
00002
00003
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_base.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/types/copy_constructor_call_generator.g.hh>
00015 #include <lestes/md/instructions/pi_pi2ge_pi_base.g.hh>
00016
00017 package(lestes);
00018 package(md);
00019 package(instructions);
00020
00021 using namespace ::lestes::backend_v2::debug;
00022 using namespace ::lestes::msg;
00023 using ::lestes::backend_v2::structs::pi_operands;
00024 using ::lestes::md::types::tm_dt_simple;
00025 using ::lestes::md::types::copy_constructor_call_generator;
00026 using namespace ::lestes::backend_v2::intercode;
00027
00028 typedef list< ulint > ulint_list__type;
00029 typedef vector< ulint > ulint_vector__type;
00030 typedef set< ulint > ulint_set__type;
00031 typedef map< ulint, srp<tm_instr_op_base> > ulint2tm_instr_op_base__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 typedef map< ulint, srp<ge_operand> > ulint2ge_operand__type;
00041 typedef map< srp<pi_operand>, srp<ge_operand> > pi_op2ge_op__type;
00042 typedef map< srp<pi_sp>, srp<ge_sp> > pi_sp2ge_sp__type;
00043
00044
00045 declare_logger(log1);
00046 initialize_logger( log1, "pi_pi2ge_pi_base", md_logger );
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 ptr<ge_pi_vector__type> pi_pi2ge_pi_base::convert(ptr<pi_pi> pi, ptr<pi_pi2ge_pi_template_base> pat) {
00060 log1 << "convert - start (pi=" << pi->reflection_get()->back()->name_get() << ")\n" << eolog;
00061
00062 lassert(pi);
00063 lassert(pat);
00064
00065 ptr<ulint_vector__type> selected_instrs = ulint_vector__type::create();
00066 ptr<ulint2tm_instr_op_base__type> selected_operands = ulint2tm_instr_op_base__type::create();
00067 ptr<ulint2ulint__type> selected_op_types = ulint2ulint__type::create();
00068
00069 if ( !find_consistent_instructions(pi,pat,selected_instrs,selected_operands,selected_op_types,0) ) {
00070 log1 << "convert - end 1 (bad)\n" << eolog;
00071 return NULL;
00072 }
00073
00074 log1 << "convert - end\n" << eolog;
00075
00076 return generate_ge_code(pi,pat,selected_instrs,selected_op_types);
00077 }
00078
00079
00080
00081
00082
00083
00084 void pi_pi2ge_pi_base::setup_dependencies(ptr<ge_pi> ge) {
00085 log1 << "setup_dependencies - start\n" << eolog;
00086
00087 ptr<pi_pi> pi = ge->pi_source_get();
00088 ptr<ge_pi_set__type> dependencies = ge->dependencies_get();
00089
00090
00091 if ( pi->psp_get() ) {
00092
00093 ptr<ge_pi> ge_psp = (*pi_sp2ge_sp)[pi->psp_get().dncast<pi_sp>()];
00094 lassert(ge_psp);
00095 dependencies->insert(ge_psp);
00096 }
00097
00098
00099 if ( pi->nsp_get() && pi->nsp_get()->psp_get()!=pi ) {
00100
00101 ptr<ge_pi> ge_nsp = (*pi_sp2ge_sp)[pi->nsp_get().dncast<pi_sp>()];
00102 lassert(ge_nsp);
00103 ge_nsp->dependencies_get()->insert(ge);
00104 }
00105
00106
00107
00108 ptr<ge_operand_vector__type> in_ops = ge->operands_input_get();
00109 for(ge_operand_vector__type::size_type i=0; i<in_ops->size(); ++i) {
00110 ptr<ge_operand> op = (*in_ops)[i];
00111
00112
00113
00114
00115 if ( op->kind_get()!=ge_operand::IMMEDIATE ) {
00116 ptr<ge_pi> origin = op->origin_get();
00117
00118 if ( !origin ) {
00119
00120
00121
00122
00123
00124 ptr<pi_operand> pi_source = op->pi_source_get();
00125
00126 if ( pi_source->kind_get()==pi_operand::MEM_PTR_DEREF ) {
00127
00128
00129
00130
00131 ptr<ge_operand> addr = pi_source.dncast<pi_mem>()->factory_get().dncast<pi_mf_ptr_deref>()->ge_addr_get();
00132 origin = addr->origin_get();
00133 } else {
00134
00135
00136
00137
00138
00139 origin = (*pi_sp2ge_sp)[pi_source->origin_get().dncast<pi_sp>()];
00140 }
00141 op->origin_set(origin);
00142 }
00143
00144 lassert(origin);
00145 dependencies->insert(origin);
00146 }
00147 }
00148
00149
00150 log1 << "setup_dependencies - end\n" << eolog;
00151
00152 }
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 ptr<ge_pi_vector__type> pi_pi2ge_pi_base::generate_ge_code(ptr<pi_pi> pi, ptr<pi_pi2ge_pi_template_base> pat, ptr<ulint_vector__type> choosed_instrs, ptr<ulint2ulint__type> choosed_op_types) {
00164 log1 << "generate_ge_code - start\n" << eolog;
00165
00166 ptr<ge_pi_vector__type> output = ge_pi_vector__type::create();
00167 ptr<ulint2ge_operand__type> tm_op2ge_op = ulint2ge_operand__type::create();
00168 ptr<pi_operands> pi_ops = pi->accept_visitor_pi_pi2pi_operands_gen_base(pi_operands_getter);
00169
00170 ptr<ge_pi> prev;
00171
00172
00173
00174
00175 for(::lestes::std::vector< srp< instruction_group_base > >::size_type i=0; i<pat->instruction_groups_get()->size(); ++i) {
00176
00177 ptr<instruction_group_base> instr_group = (*pat->instruction_groups_get())[i];
00178
00179 ptr<tm_instr_base> instr_version = tm_instr::instance((*choosed_instrs)[i]);
00180
00181
00182 ptr<ge_pi> ge = ge_pi::create(instr_version,pi);
00183
00184 ptr<ge_operand_vector__type> input_ops = ge->operands_input_get();
00185 ptr<ge_operand_vector__type> output_ops = ge->operands_output_get();
00186 ptr<ge_pi_set__type> dependencies = ge->dependencies_get();
00187
00188 if ( prev ) {
00189
00190
00191
00192
00193
00194 dependencies->insert(prev);
00195 }
00196
00197
00198 for(::lestes::std::vector< ulint >::size_type j=0; j<instr_group->input_operand_pids_get()->size(); ++j) {
00199
00200 ulint operand_pid = (*instr_group->input_operand_pids_get())[j];
00201
00202 ulint operand_ref = (*instr_group->input_operand_refs_get())[j];
00203
00204 ptr<tm_instr_op_base> tm_op = (*instr_version->operands_input_get())[j];
00205 lassert(tm_op->id_get()==operand_ref);
00206
00207 ptr<ge_operand> ge_op;
00208
00209 if ( operand_pid <= PIN_4 ) {
00210
00211 ulint i_op_pos = operand_pid - PIN_1;
00212 ptr<pi_operand> pi_op = (*pi_ops->operands_input_get())[i_op_pos];
00213
00214
00215 ge_op = pi_op2ge_op_convertor->convert(pi_op);
00216
00217 if ( tm_op->destroyed_by_get()->size()!=0 && (*pi_op2count)[pi_op] > 1 ) {
00218
00219
00220
00221
00222
00223
00224 ptr<ge_pi_vector__type> copy_code = ge_pi_vector__type::create();
00225
00226 ge_op = copy_constructor_call_generator::instance()->generate_copy(ge_op,copy_code);
00227
00228
00229 for(ulint k=0; k<copy_code->size(); ++k) {
00230 ptr<ge_pi> cp = (*copy_code)[k];
00231 cp->pi_source_set(pi);
00232 output->push_back(cp);
00233
00234
00235
00236
00237
00238
00239 }
00240 }
00241 } else {
00242
00243
00244 ulint2ge_operand__type::iterator it_ge = tm_op2ge_op->find(operand_pid);
00245 lassert(it_ge!=tm_op2ge_op->end());
00246 ge_op = it_ge->second;
00247 }
00248
00249 input_ops->push_back(ge_op);
00250 }
00251
00252
00253 for(ulint j=0; j<instr_group->output_operand_pids_get()->size(); ++j) {
00254
00255 ulint operand_pid = (*instr_group->output_operand_pids_get())[j];
00256
00257 ulint operand_ref = (*instr_group->output_operand_refs_get())[j];
00258
00259 ptr<ge_operand> ge_op;
00260
00261 if ( operand_pid <= POUT_4 ) {
00262
00263 ulint i_op_pos = operand_pid - POUT_1;
00264 ptr<pi_operand> pi_op = (*pi_ops->operands_output_get())[i_op_pos];
00265
00266
00267 ge_op = pi_op2ge_op_convertor->convert(pi_op);
00268
00269 } else {
00270
00271 ptr<tm_instr_op_base> tm_op = (*instr_version->operands_output_get())[j];
00272 lassert(tm_op->id_get()==operand_ref);
00273
00274
00275 ulint type;
00276
00277 if ( tm_op->allowed_types_get()->size()==1 ) {
00278
00279 type = *tm_op->allowed_types_get()->begin();
00280 } else {
00281
00282 lassert(instr_group->input_operand_pids_get()->size()>0);
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300 ulint iop_pid = (*instr_group->input_operand_pids_get())[0];
00301 ulint2ulint__type::iterator it_t = choosed_op_types->find(iop_pid);
00302 lassert(it_t!=choosed_op_types->end());
00303
00304 type = it_t->second;
00305
00306
00307 lassert(tm_op->allowed_types_get()->find(type)!=tm_op->allowed_types_get()->end());
00308 }
00309
00310
00311 ge_op = tm_op->convert_to_ge(tm_dt_simple::instance((::lestes::md::types::dt_id_type)type));
00312
00313 tm_op2ge_op->insert(::std::pair<ulint, srp<ge_operand> >(operand_pid,ge_op));
00314 }
00315
00316
00317 ge_op->origin_set(ge);
00318
00319
00320 output_ops->push_back(ge_op);
00321 }
00322
00323 if ( instr_version->is_jump() ) {
00324
00325 ptr<ge_sp_vector__type> jmp_targets = ge_sp_vector__type::create();
00326
00327 ptr<pi_sp_vector__type> pi_targets = pi_ops->jmp_targets_get();
00328 for(ulint j=0; j<pi_targets->size(); ++j) {
00329 ptr<ge_sp> jmp_target = (*pi_sp2ge_sp)[(*pi_targets)[j]];
00330 jmp_target->is_jmp_target_set(true);
00331 jmp_targets->push_back(jmp_target);
00332 }
00333
00334 ge->jmp_targets_set(jmp_targets);
00335 }
00336 ge->validate();
00337 output->push_back(ge);
00338 }
00339
00340 log1 << "generate_ge_code - end\n" << eolog;
00341
00342 return output;
00343 }
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357 bool pi_pi2ge_pi_base::find_consistent_instructions(ptr<pi_pi> pi, 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) {
00358 log1 << "find_consisten_instructions - start\n" << eolog;
00359
00360 if ( curr_instrs_pat_idx==pat->instruction_groups_get()->size() ) {
00361
00362 log1 << "find_consisten_instructions - end 1\n" << eolog;
00363 return true;
00364 }
00365
00366
00367 ptr<instruction_group_base> instr_group = (*pat->instruction_groups_get())[curr_instrs_pat_idx];
00368
00369
00370 for(ulint i=0; i<instr_group->instructions_get()->size(); ++i) {
00371 ulint instr_version_id = (*instr_group->instructions_get())[i];
00372 ptr<tm_instr_base> instr_version = tm_instr::instance(instr_version_id);
00373
00374 if ( !is_instruction_consistent(instr_group,instr_version,pi,selected_operands,selected_op_types) ) {
00375
00376 continue;
00377 }
00378
00379
00380 add_selected_operands(instr_group,instr_version,pi,selected_operands,selected_op_types);
00381 selected_instrs->push_back(instr_version_id);
00382
00383
00384 if ( find_consistent_instructions(pi,pat,selected_instrs,selected_operands,selected_op_types,curr_instrs_pat_idx+1) ) {
00385
00386 log1 << "find_consisten_instructions - end 2 (good)\n" << eolog;
00387 return true;
00388 }
00389
00390
00391 remove_selected_operands(instr_group,selected_operands,selected_op_types);
00392 selected_instrs->pop_back();
00393 }
00394
00395 log1 << "find_consisten_instructions - end (bad)\n" << eolog;
00396 return false;
00397 }
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409 bool pi_pi2ge_pi_base::is_instruction_consistent(ptr<instruction_group_base> instr_group, ptr<tm_instr_base> instr_version, ptr<pi_pi> pi, ptr<ulint2tm_instr_op_base__type> selected_operands,ptr<ulint2ulint__type> selected_types) {
00410 log1 << "is_instruction_consistent - start (tm_instr=" << instr_version->id_get() << ")\n" << eolog;
00411
00412
00413
00414
00415
00416 if ( !targetmachine__is_instruction_consistent(instr_version,pi) ) {
00417 log1 << "is_instruction_consistent - end 1 (bad)\n" << eolog;
00418 return false;
00419 }
00420
00421 ptr<pi_operands> operands = pi->accept_visitor_pi_pi2pi_operands_gen_base(pi_operands_getter);
00422
00423
00424
00425 for(ulint i=0; i<instr_group->input_operand_pids_get()->size(); ++i) {
00426 ulint operand_pid = (*instr_group->input_operand_pids_get())[i];
00427 ulint operand_ref = (*instr_group->input_operand_refs_get())[i];
00428
00429 lassert(operand_pid<=PIN_4 || operand_pid>POUT_4 );
00430
00431 ptr<tm_instr_op_base> op = find_op_by_id(instr_version->operands_input_get(),operand_ref);
00432
00433 if ( operand_pid <= PIN_4 ) {
00434
00435 ulint i_op_pos = operand_pid - PIN_1;
00436
00437 lassert(operands->operands_input_types_get()->size()>i_op_pos);
00438 if ( !is_operand_compatible1(op,(*operands->operands_input_get())[i_op_pos],(*operands->operands_input_types_get())[i_op_pos]->id_get()) ) {
00439 log1 << "is_instruction_consistent - end 2 (bad)\n" << eolog;
00440 return false;
00441 }
00442
00443 } else {
00444
00445 ulint2tm_instr_op_base__type::iterator it_op = selected_operands->find(operand_pid);
00446 ulint2ulint__type::iterator it_t = selected_types->find(operand_pid);
00447
00448 lassert(it_op!=selected_operands->end());
00449 lassert(it_t!=selected_types->end());
00450
00451 if ( !is_operand_compatible2(op,it_op->second,it_t->second) ) {
00452 log1 << "is_instruction_consistent - end 3 (bad)\n" << eolog;
00453 return false;
00454 }
00455 }
00456 }
00457
00458
00459
00460
00461 for(ulint i=0; i<instr_group->output_operand_pids_get()->size(); ++i) {
00462 ulint operand_ref = (*instr_group->output_operand_refs_get())[i];
00463 ulint operand_pid = (*instr_group->output_operand_pids_get())[i];
00464
00465 lassert(operand_pid > PIN_4);
00466
00467 if ( operand_pid>=POUT_1 && operand_pid <= POUT_4 ) {
00468 ptr<tm_instr_op_base> op = find_op_by_id(instr_version->operands_output_get(),operand_ref);
00469 ulint i_op_pos = operand_pid - POUT_1;
00470
00471 lassert(operands->operands_output_types_get()->size()>i_op_pos);
00472 if ( !is_operand_compatible1(op,(*operands->operands_output_get())[i_op_pos],(*operands->operands_output_types_get())[i_op_pos]->id_get()) ) {
00473 log1 << "is_instruction_consistent - end 4 (bad)\n" << eolog;
00474 return false;
00475 }
00476
00477 }
00478 }
00479
00480 log1 << "is_instruction_consistent - end\n" << eolog;
00481 return true;
00482 }
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492 bool pi_pi2ge_pi_base::is_operand_compatible1(ptr<tm_instr_op_base> instr_op, ptr<pi_operand> pi_op, ulint pi_type) {
00493 log1 << "is_operand_compatible1 - start (instr_op=" << instr_op->id_get() << ")\n" << eolog;
00494
00495 if ( instr_op->allowed_types_get()->find(pi_type)==instr_op->allowed_types_get()->end() ) {
00496 log1 << "is_operand_compatible1 - end1 (bad)\n" << eolog;
00497 return false;
00498 }
00499
00500 ulint kind1 = instr_op->kind_get();
00501 ulint kind2 = pi_op->kind_get();
00502
00503 if ( ( kind1==tm_instr_op_base::REGISTER && ( kind2!=pi_operand::PREG && kind2!=pi_operand::MEM_PREG)) ||
00504 ( kind1==tm_instr_op_base::IMMEDIATE && kind2!=pi_operand::LIT ) ||
00505 ( kind1==tm_instr_op_base::MEMORY && (kind2==pi_operand::MEM_PREG || kind2==pi_operand::PREG || kind2==pi_operand::LIT) ) ) {
00506 log1 << "is_operand_compatible1 - end2 (bad)\n" << eolog;
00507 return false;
00508 }
00509
00510 log1 << "is_operand_compatible1 - end\n" << eolog;
00511 return true;
00512 }
00513
00514
00515
00516
00517
00518
00519
00520
00521 bool pi_pi2ge_pi_base::is_in(ptr<vector<ulint> > list, ulint value) {
00522 for(uint i=0; i<list->size(); ++i) {
00523 if ( (*list)[i]==value ) {
00524 return true;
00525 }
00526 }
00527 return false;
00528 }
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538 bool pi_pi2ge_pi_base::is_operand_compatible2(ptr<tm_instr_op_base> op1, ptr<tm_instr_op_base> op2, ulint type) {
00539 log1 << "is_operand_compatible2 - start (instr_op=" << op1->id_get() << ")\n" << eolog;
00540
00541 if ( op1->allowed_types_get()->find(type)==op1->allowed_types_get()->end() ) {
00542 log1 << "is_operand_compatible2 - end 1 (bad)\n" << eolog;
00543 return false;
00544 }
00545
00546 if ( op1->kind_get()!=op2->kind_get() ) {
00547 log1 << "is_operand_compatible2 - end 2 (bad)\n" << eolog;
00548 return false;
00549 }
00550
00551 if ( op1->kind_get()==tm_instr_op_base::REGISTER ) {
00552 ptr<ulint_set__type> allowed_regs1 = op1.dncast<tm_instr_op_reg_base>()->allowed_registers_get();
00553 ptr<ulint_set__type> allowed_regs2 = op2.dncast<tm_instr_op_reg_base>()->allowed_registers_get();
00554 ptr<ulint_set__type> allowed_intersec = ulint_set__type::create();
00555
00556 ::std::set_intersection(
00557 allowed_regs1->begin(),
00558 allowed_regs1->end(),
00559 allowed_regs2->begin(),
00560 allowed_regs2->end(),
00561 ::std::inserter(*allowed_intersec, allowed_intersec->begin()));
00562
00563
00564 if ( allowed_intersec->size()!=0 ) {
00565 log1 << "is_operand_compatible2 - end 3 (good)\n" << eolog;
00566 return true;
00567 }
00568 }
00569
00570 log1 << "is_operand_compatible2 - end (bad)\n" << eolog;
00571 return false;
00572 }
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583 void pi_pi2ge_pi_base::add_selected_operands(ptr<instruction_group_base> instr_group, ptr<tm_instr_base> instr_version, ptr<pi_pi> pi, ptr<ulint2tm_instr_op_base__type> selected_operands,ptr<ulint2ulint__type> selected_types) {
00584 ptr<pi_operands> operands = pi->accept_visitor_pi_pi2pi_operands_gen_base(pi_operands_getter);
00585
00586
00587 for(ulint i=0; i<instr_group->output_operand_pids_get()->size(); ++i) {
00588 ulint operand_pid = (*instr_group->output_operand_pids_get())[i];
00589 ulint operand_ref = (*instr_group->output_operand_refs_get())[i];
00590
00591 lassert(operand_pid > PIN_4);
00592
00593 ptr<tm_instr_op_base> op = find_op_by_id(instr_version->operands_output_get(),operand_ref);
00594 selected_operands->insert(::std::pair<ulint, srp<tm_instr_op_base> >(operand_pid, op));
00595
00596 ulint type;
00597
00598 if ( operand_pid>=POUT_1 && operand_pid <= POUT_4 ) {
00599
00600 ulint i_op_pos = operand_pid - POUT_1;
00601 ptr<pi_operand> pi_op = (*operands->operands_output_get())[i_op_pos];
00602 type = pi_op->type_get()->id_get();
00603 } else {
00604 if ( op->allowed_types_get()->size()==1 ) {
00605
00606 type = *op->allowed_types_get()->begin();
00607 } else {
00608
00609 lassert(instr_group->input_operand_pids_get()->size()>0);
00610 ulint iop_pid = (*instr_group->input_operand_pids_get())[0];
00611
00612 ulint2ulint__type::iterator it_t = selected_types->find(iop_pid);
00613
00614 lassert(it_t!=selected_types->end());
00615
00616 type = it_t->second;
00617 }
00618 }
00619
00620 selected_types->insert(::std::pair<ulint, ulint>(operand_pid, type));
00621 }
00622 }
00623
00624
00625
00626
00627
00628
00629
00630
00631 void pi_pi2ge_pi_base::remove_selected_operands(ptr<instruction_group_base> instr_group, ptr<ulint2tm_instr_op_base__type> selected_operands, ptr<ulint2ulint__type> selected_types) {
00632
00633 for(ulint i=0; i<instr_group->output_operand_pids_get()->size(); ++i) {
00634 ulint operand_pid = (*instr_group->output_operand_pids_get())[i];
00635 selected_operands->erase(operand_pid);
00636 selected_types->erase(operand_pid);
00637 }
00638 }
00639
00640
00641
00642
00643
00644
00645
00646
00647 ptr<tm_instr_op_base> pi_pi2ge_pi_base::find_op_by_id(ptr<tm_instr_op_base_vector__type> list, ulint id) {
00648 for(uint i=0; i<list->size(); ++i) {
00649 ptr<tm_instr_op_base> op = (*list)[i];
00650
00651 if ( op->id_get()==id ) {
00652 return op;
00653 }
00654 }
00655
00656 return NULL;;
00657 }
00658
00659
00660 end_package(instructions);
00661 end_package(md);
00662 end_package(lestes);
00663