mapConformance.cpp

Go to the documentation of this file.
00001 /* Copyright 1996 LongView Technologies L.L.C. $Revision: 1.1 $ */
00002 /* Copyright (c) 2006, Sun Microsystems, Inc.
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 
00006 following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
00010           disclaimer in the documentation and/or other materials provided with the distribution.
00011     * Neither the name of Sun Microsystems nor the names of its contributors may be used to endorse or promote products derived 
00012           from this software without specific prior written permission.
00013 
00014 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
00015 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
00016 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
00017 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00018 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
00019 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
00020 
00021 
00022 */
00023 
00024 # include "incls/_precompiled.incl"
00025 
00026 # ifdef DELTA_COMPILER
00027 # include "incls/_mapConformance.cpp.incl"
00028 
00029 void Variable::print() {
00030   if (in_register()) {
00031     std->print("R%d", offset());
00032   } else if (on_stack()) {
00033     std->print("S[%d]", offset());
00034   } else if (is_unused()) {
00035     std->print("UN");
00036   } else if (is_top_of_stack()){
00037     std->print("tos");
00038   } else {
00039     fatal("invalid variable");
00040   }
00041 }
00042 
00043 
00044 Variable MapConformance::pop_temporary() {
00045   Variable result = Variable::top_of_stack();
00046   if (!_free_register.is_unused()) {
00047     result = _free_register;
00048     _free_register = Variable::unused();
00049   }
00050   return result;
00051 }
00052 
00053 void MapConformance::push_temporary(Variable var) {
00054   if (var.in_register()) {
00055     _free_register = var;
00056   }
00057 }
00058 
00059 void MapConformance::push(Variable src, int n) {
00060   for (int index = 0; index < n; index++) {
00061     push(src);
00062   }
00063 }
00064 class MappingEntry : public ValueObj {
00065  private:
00066   Variable _reg;
00067   Variable _stack;
00068  public:
00069   MappingEntry(Variable reg, Variable stack) {
00070     _reg   = reg;
00071     _stack = stack;
00072   }
00073   Variable reg()   { return _reg;  }
00074   Variable stack() { return _stack; }
00075 
00076   bool has_reg()   { return !reg().is_unused(); }
00077   bool has_stack() { return !stack().is_unused(); }
00078 
00079   void set_reg(Variable r)   { _reg = r; }
00080   void set_stack(Variable s) { _stack = s; }
00081 
00082   void print();
00083 };
00084 
00085 void MappingEntry::print() {
00086   if (!reg().is_unused())   reg().print();
00087   if (!stack().is_unused()) stack().print();
00088 }
00089 
00090 bool operator == (MappingEntry x, MappingEntry y) {
00091   return x.reg() == y.reg() && x.stack() == y.stack();
00092 }
00093 
00094 class MappingTask : public ResourceObj {
00095  private:
00096   MappingTask* _next;         // next task with same source
00097   MappingTask* _parent;       // parent chain for recursion
00098   bool         _is_processed; 
00099   char*        _what_happend; // what happend to this task
00100   bool         _uses_top_of_stack;
00101   Variable     _variable_to_free;
00102  public:
00103   MappingTask(Variable src_register, Variable src_stack, Variable dst_register, Variable dst_stack) 
00104   : src(src_register, src_stack), dst(dst_register, dst_stack) {
00105     _next         = NULL;
00106     _is_processed = false;
00107     _what_happend = "Nothing";
00108     _parent       = NULL;
00109     _uses_top_of_stack = false;
00110     _variable_to_free = Variable::unused();
00111   }
00112 
00113   bool is_processed() const { return _is_processed; }
00114   void set_processed(char* reason) {
00115     _is_processed = true;
00116     _what_happend = reason;
00117   }
00118 
00119   void append(MappingTask* son) {
00120     assert(!is_processed(),      "should be un touched");
00121     assert(!son->is_processed(), "should be un touched");
00122     son->set_next(next());
00123     set_next(son);
00124     son->set_processed("Linked");
00125   }
00126 
00127   MappingTask* next() const { return _next; }
00128   void set_next(MappingTask* n) { _next = n; }
00129 
00130   MappingTask* parent() const { return _parent; }
00131   void set_parent(MappingTask* p) { _parent = p; }
00132 
00133   Variable variable_to_free() const { return _variable_to_free; }
00134   void set_variable_to_free(Variable var) { _variable_to_free = var; }
00135 
00136   bool uses_top_of_stack() const { return _uses_top_of_stack; }
00137   void set_uses_top_of_stack(bool b) { _uses_top_of_stack = b; }
00138 
00139   MappingEntry src;
00140   MappingEntry dst;
00141 
00142   void process_task(MapConformance* mc, MappingTask* p);
00143   void generate_code(MapConformance* mc);
00144 
00145   bool target_includes(Variable var);
00146   bool is_dependent(MapConformance* mc, MappingTask* task);
00147   bool in_parent_chain(MappingTask* task);
00148 
00149   int  number_of_targets();
00150 
00151   void print(int index);
00152 };
00153 
00154 int MappingTask::number_of_targets() {
00155   int result = 0;
00156   for (MappingTask* current = this; current; current = current->next()) {
00157     if (current->dst.has_reg())   result++;
00158     if (current->dst.has_stack()) result++;
00159   }
00160   return result;
00161 }
00162 
00163 
00164 bool MappingTask::in_parent_chain(MappingTask* task) {
00165   for (MappingTask* current = this; current; current = current->parent()) {
00166     if (current == task) return true;
00167   }
00168   return false;
00169 }
00170 
00171 bool MappingTask::target_includes(Variable var) {
00172   for (MappingTask* current = this; current; current = current->next()) {
00173     if (current->dst.reg() == var || current->dst.stack() == var)
00174       return true;
00175   }
00176   return false;
00177 }
00178 
00179 
00180 bool MappingTask::is_dependent(MapConformance* mc, MappingTask* task) {
00181   // Do we have to process task before this?
00182   // => do task->results overlap with src?
00183   if (this == task) return false;
00184 
00185   bool is_reg_dependent   = false;
00186   bool is_stack_dependent = false;
00187 
00188   if (task->src.has_reg()) {
00189     is_reg_dependent = target_includes(task->src.reg());
00190   }
00191 
00192   if (task->src.has_stack()) {
00193     is_stack_dependent = target_includes(task->src.stack());
00194   }
00195 
00196   if (is_reg_dependent || is_stack_dependent) {
00197     if (in_parent_chain(task)) {
00198       // A....task......this
00199       if (task->src.has_reg()) {
00200         if (task->src.has_stack()) {
00201           task->src.set_stack(Variable::unused());
00202         }
00203         Variable temp = mc->pop_temporary();
00204         if (temp.is_top_of_stack()) {
00205           mc->push(task->src.reg(), number_of_targets());
00206           task->src.set_reg(temp);
00207           task->set_uses_top_of_stack(true);
00208         } else {
00209           mc->move(task->src.reg(), temp);
00210           task->src.set_reg(temp);
00211           task->set_variable_to_free(temp);
00212         }
00213       } else {
00214         Variable temp = mc->pop_temporary();
00215         if (temp.is_top_of_stack()) {
00216           mc->push(task->src.stack(), number_of_targets());
00217           task->src.set_reg(temp);
00218           task->set_uses_top_of_stack(true);
00219         } else {
00220           mc->move(task->src.stack(), temp);
00221           task->src.set_reg(temp);
00222           task->src.set_stack(Variable::unused());
00223           task->set_variable_to_free(temp);
00224         }
00225       }
00226       return false;
00227     }
00228   }
00229 
00230   return is_reg_dependent || is_stack_dependent;
00231 }
00232 
00233 void MappingTask::process_task(MapConformance* mc, MappingTask* p) {
00234   if (is_processed()) return;
00235 
00236   //Is anybody dependent on source?
00237   set_parent(p);
00238   for (int index = 0; index < mc->mappings->length(); index++) {
00239     MappingTask* task = mc->mappings->at(index);
00240     if (!task->is_processed() && is_dependent(mc, task)) {
00241       task->process_task(mc, this);
00242     }
00243   }
00244   set_parent(NULL);
00245 
00246   // Generate code for task
00247   generate_code(mc);
00248   mc->push_temporary(variable_to_free());
00249   set_processed("Code has been generated");
00250 }
00251 
00252 void MappingTask::generate_code(MapConformance* mc) {
00253   bool uses_temp = false;
00254 
00255   if (uses_top_of_stack()) {
00256     //Use source register for moves
00257     for (MappingTask* current = this; current; current = current->next()) {
00258       if(current->dst.has_reg()) {
00259         mc->pop(current->dst.reg()); 
00260       }
00261       if (dst.has_stack() && !(src.stack() == dst.stack())) {
00262         mc->pop(current->dst.stack());
00263       }
00264     }
00265   } else if (src.has_reg()) {
00266     //Use source register for moves
00267     for (MappingTask* current = this; current; current = current->next()) {
00268       if(current->dst.has_reg()) {
00269         mc->move(src.reg(), current->dst.reg()); 
00270       }
00271       if (current->dst.has_stack() && !(src.stack() == current->dst.stack())) {
00272         mc->move(src.reg(), current->dst.stack());
00273       }
00274     }
00275   } else {
00276     //Use register in target or free register
00277     Variable temp;
00278     for (MappingTask* current = this; current; current = current->next()) {
00279       if(current->dst.has_reg()) temp = current->dst.reg();
00280     }
00281     if (temp.is_unused()) {
00282       uses_temp = true;
00283       temp = mc->pop_temporary();
00284     }
00285     if (temp.in_register()) {
00286       //We found a temporary register
00287       mc->move(src.stack(), temp);
00288       for (MappingTask* current = this; current; current = current->next()) {
00289         if(current->dst.has_reg() && !(current->dst.reg() == temp)) {
00290           mc->move(temp, current->dst.reg()); 
00291         }
00292         if (current->dst.has_stack() && !(src.stack() == current->dst.stack())) {
00293           mc->move(temp, current->dst.stack());
00294         }
00295       }
00296       if (uses_temp) {
00297         mc->push_temporary(temp);
00298       }
00299     } else {
00300       for (MappingTask* current = this; current; current = current->next()) {
00301         if(current->dst.has_reg()) {
00302           mc->push(src.stack());
00303           mc->pop(current->dst.reg()); 
00304         }
00305         if (current->dst.has_stack() && !(src.stack() == current->dst.stack())) {
00306           mc->push(src.stack());
00307           mc->pop(current->dst.stack()); 
00308         }
00309       }
00310     }
00311   }
00312 }
00313 
00314 void MappingTask::print(int index) {
00315   std->print("  %2d: ", index);
00316   src.print();
00317   std->print(" -> ");
00318   dst.print();
00319   if (_what_happend != NULL) {
00320     std->set_indentation(35);
00321     std->indent();
00322     std->print("%s", _what_happend);
00323   }
00324   std->cr();
00325 }
00326 
00327 MapConformance::MapConformance() {
00328   mappings       = new GrowableArray<MappingTask*>(20);
00329   used_variables = NULL;
00330   _free_register.set_unused();
00331 }
00332 
00333 void MapConformance::append_mapping(Variable src_register, Variable src_stack, Variable dst_register, Variable dst_stack) {
00334   mappings->append(new MappingTask(src_register, src_stack, dst_register, dst_stack));
00335 }
00336 
00337 void MapConformance::generate(Variable free_register1, Variable free_register2) {
00338  this->_free_register  = free_register1;
00339  // There is max. 2 used variables per mapping.
00340  this->used_variables = NEW_RESOURCE_ARRAY(Variable, mappings->length() * 2);
00341  this->number_of_used_variables = 0;
00342 
00343  simplify();
00344  process_tasks();
00345 
00346  this->_free_register.set_unused();
00347  this->used_variables = NULL;
00348 }
00349 
00350 void MapConformance::move(Variable src, Variable dst) {
00351   std->print("  move  ");
00352   src.print();
00353   std->print(", ");
00354   dst.print();
00355   std->cr();
00356 }
00357 
00358 void MapConformance::push(Variable src) {
00359   std->print("  push  ");
00360   src.print();
00361   std->cr();
00362 }
00363 
00364 void MapConformance::pop(Variable dst) {
00365   std->print("  pop  ");
00366   dst.print();
00367   std->cr();
00368 }
00369 
00370 void MapConformance::print() {
00371   std->print_cr("MapConformance");
00372   for (int index = 0; index < mappings->length(); index++) {
00373     mappings->at(index)->print(index);
00374   }
00375 }
00376 
00377 bool MapConformance::reduce_noop_task(MappingTask* task) {
00378   // A noop task if destination is a subset of source
00379   bool result = true;
00380 
00381   if (task->dst.has_reg() && task->src.reg() != task->dst.reg()) {
00382     result = false;
00383   }
00384 
00385   if (task->dst.has_stack() && task->src.stack() != task->dst.stack()) {
00386     result = false;
00387   }
00388 
00389   if (result) task->set_processed("Noop");
00390   return result;
00391 }
00392 
00393 void MapConformance::simplify() {
00394   // Links tasks with identical source.
00395   for (int x = 0; x < mappings->length(); x++) {
00396     MappingTask* x_task = mappings->at(x);
00397     if (!x_task->is_processed() && !reduce_noop_task(x_task)) {
00398       for (int y = x + 1; y < mappings->length(); y++) {
00399         MappingTask* y_task = mappings->at(y);
00400         if (x_task->src == y_task->src) x_task->append(y_task);
00401       }
00402     }
00403   }
00404 }
00405 
00406 void MapConformance::process_tasks() {
00407   for (int index = 0; index < mappings->length(); index++) {
00408     mappings->at(index)->process_task(this, NULL);
00409   }
00410 }
00411 
00412 #endif // DELTA_COMPILER

Generated on Mon Oct 9 13:37:14 2006 for Strongtalk VM by  doxygen 1.4.7