C-Breeze
C Compiler Infrastructure

[ Project home page]
Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

ipconstants.cc

Go to the documentation of this file.
00001 // $Id: ipconstants.cc,v 1.4 2003/08/07 23:14:15 pnav Exp $
00002 // ----------------------------------------------------------------------
00003 //
00004 //  C-Breeze
00005 //  C Compiler Framework
00006 // 
00007 //  Copyright (c) 2000 University of Texas at Austin
00008 // 
00009 //  Samuel Z. Guyer
00010 //  Daniel A. Jimenez
00011 //  Calvin Lin
00012 // 
00013 //  Permission is hereby granted, free of charge, to any person
00014 //  obtaining a copy of this software and associated documentation
00015 //  files (the "Software"), to deal in the Software without
00016 //  restriction, including without limitation the rights to use, copy,
00017 //  modify, merge, publish, distribute, sublicense, and/or sell copies
00018 //  of the Software, and to permit persons to whom the Software is
00019 //  furnished to do so, subject to the following conditions:
00020 //  
00021 //  The above copyright notice and this permission notice shall be
00022 //  included in all copies or substantial portions of the Software.
00023 //  
00024 //  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00025 //  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00026 //  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00027 //  NONINFRINGEMENT.  IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT
00028 //  AUSTIN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
00029 //  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
00030 //  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00031 //  THE SOFTWARE.
00032 //
00033 //  We acknowledge the C-to-C Translator from MIT Laboratory for
00034 //  Computer Science for inspiring parts of the C-Breeze design.
00035 //
00036 // ----------------------------------------------------------------------
00037 
00038 #include "c_breeze.h"
00039 #include "ipconstants.h"
00040 
00041 // ------------------------------------------------------------
00042 // ipConstant
00043 // ------------------------------------------------------------
00044 
00045 // This class represents a single constant value associated with one
00046 // def of a variable. It can hold either a constant value, or have the
00047 // special lattice TOP value. The lattice BOTTOM is represented by a
00048 // constant no_val (which is built into the constant class).
00049 
00050 // Constructors
00051 
00052 ipConstant::ipConstant(constant & value)
00053   : _value(value),
00054     _top(false),
00055     _internal(false)
00056 {}
00057 
00058 ipConstant::ipConstant()
00059   : _value(0),
00060     _top(true),
00061     _internal(false)
00062 {}
00063 
00064 ipConstant::ipConstant(const ipConstant & other)
00065   : _value(other._value),
00066     _top(other._top),
00067     _internal(false)
00068 {}
00069 
00070 ipConstant::~ipConstant()
00071 {
00072   if (_internal)
00073     cout << "ERROR: Deleting an internal ipConstant" << endl;
00074 }
00075 
00076 // -- Top and bottom
00077 
00078 bool ipConstant::is_top() const
00079 {
00080   return _top && (! _value.no_val());
00081 }
00082 
00083 bool ipConstant::is_bottom() const
00084 {
00085   return _value.no_val();
00086 }
00087 
00088 void ipConstant::to_bottom()
00089 {
00090   _value.set_no_val();
00091   _top = false;
00092 }
00093 
00094 // -- Assignment
00095 
00096 void ipConstant::assign(const ipConstant * other)
00097 {
00098   _value = other->_value;
00099   _top = other->_top;
00100 }
00101 
00102 // -- Comparison
00103 
00104 bool ipConstant::diff(analysisVal * other) const
00105 {
00106   ipConstant * ic_other = (ipConstant *) other;
00107 
00108   if (is_bottom() || ic_other->is_bottom())
00109     return is_bottom() != ic_other->is_bottom();
00110 
00111   if (is_top() || ic_other->is_top())
00112     return is_top() != ic_other->is_top();
00113 
00114   return ! (value().is_equal_to(ic_other->value()));
00115 }
00116 
00117 // -- Meet "^" operator
00118 // Must satisfy the following:
00119 //    Associative: x ^ (y ^ z) = (x ^ y) ^ z
00120 //    Commutative: x ^ y = y ^ x
00121 //    Idempotent:  x ^ x = x
00122 
00123 void ipConstant::meet_with(const analysisVal * other)
00124 {
00125   ipConstant * ic_other = (ipConstant *) other;
00126 
00127   /*
00128   cout << "Meet : ";
00129   print(cout);
00130   cout << "  ";
00131   ic_other->print(cout);
00132   cout << endl;
00133   */
00134 
00135   // Case 1 : BOTTOM ^ <anything> = BOTTOM
00136 
00137   if (is_bottom())
00138     return;
00139 
00140   // Case 2 : <anything> ^ BOTTOM = BOTTOM
00141 
00142   if (ic_other->is_bottom()) {
00143     to_bottom();
00144     return;
00145   }
00146 
00147   // Case 3 : TOP ^ <value> = <value>
00148 
00149   if (is_top()) {
00150     value() = ic_other->value();
00151     _top = false;
00152     return;
00153   }
00154 
00155   // Case 4 : <value> ^ TOP = <value>
00156 
00157   if (ic_other->is_top()) {
00158     return;
00159   }
00160 
00161   // Case 5 : <value1> ^ <value2> = <value1>, if value1 == value2
00162 
00163   if (value().is_equal_to(ic_other->value())) {
00164     return;
00165   }
00166   else
00167     // Case 6 : <value1> ^ <value2> = BOTTOM, if value1 != value2
00168     to_bottom();
00169 }
00170 
00171 // -- Computational functions
00172 
00173 void ipConstant::binary_operator(const Operator * op,
00174                                  const analysisVal * right_operand)
00175 {
00176   ipConstant * ic_right = (ipConstant *) right_operand;
00177 
00178   /*
00179   cout << "Binop : ";
00180   print(cout);
00181   cout << "  ";
00182   ic_right->print(cout);
00183   cout << endl;
00184   */
00185 
00186   value() = constant::eval(op, value(), ic_right->value());
00187 }
00188 
00189 void ipConstant::unary_operator(const Operator * op)
00190 {
00191   /*
00192   cout << "Unary : ";
00193   print(cout);
00194   cout << endl;
00195   */
00196 
00197   value() = constant::eval(op, value());
00198 }
00199 
00200 void ipConstant::cast_operator(const typeNode * type)
00201 {
00202   /*
00203   cout << "Cast : ";
00204   print(cout);
00205   cout << endl;
00206   */
00207 
00208   if (type->typ() == Prim) {
00209     primNode * prim = (primNode *) type;
00210     value() = constant::cast(prim->basic(), value());
00211   }
00212 }
00213 
00214 void ipConstant::print(ostream & o)
00215 {
00216   if (is_top())
00217     o << "TOP";
00218   else
00219     if (is_bottom())
00220       o << "BOTTOM";
00221     else
00222       o << value().to_string();
00223 }
00224 
00225 // ------------------------------------------------------------
00226 // ipConstantPropagation
00227 // ------------------------------------------------------------
00228 
00229 // This class controls the constant propagation algorithm by holding
00230 // the current states of all objects, looking them up when needed, and
00231 // setting their values at assignments.
00232 
00233 // -- Process an assignment; return true if the state of the defined
00234 // object changes.
00235 
00236 bool ipConstantPropagation::assignment(const Path * where,
00237                                        memoryDef * left_hand_side,
00238                                        analysisVal * ipa_rhs,
00239                                        bool is_strong_update)
00240 {
00241   ipConstant * ic_rhs = (ipConstant *) ipa_rhs;
00242 
00243   // Look up the particular def, creating one if necessary
00244 
00245   const_variables_map_p found = _values.find(left_hand_side);
00246   ipConstant * ic_lhs = 0;
00247   bool f;
00248   if (found == _values.end()) {
00249     ic_lhs = new ipConstant();
00250     allocate(ic_lhs);
00251     _values[left_hand_side] = ic_lhs;
00252     ic_lhs->intern();
00253     f = true;
00254   }
00255   else {
00256     ic_lhs = (*found).second;
00257     f = false;
00258   }
00259 
00260   bool diff;
00261   if (is_strong_update) {
00262 
00263     // Check to see if a change will occur
00264 
00265     diff = ic_lhs->diff(ic_rhs);
00266     ic_lhs->assign(ic_rhs);
00267   }
00268   else {
00269 
00270     // If not a strong update, go to bottom
00271 
00272     diff = ! ic_lhs->is_bottom();
00273     ic_lhs->assign(_bottom);
00274   }
00275 
00276   return diff;
00277 }
00278 
00279 // -- Lookup the flow value for an object (not a copy)
00280 
00281 analysisVal * ipConstantPropagation::lookup(memoryBlock * block, memoryUse * use)
00282 {
00283   ipConstant * out = 0;
00284 
00285   // For enum types, use the constant value stored on the declaration.
00286 
00287   if (block->decl()->decl_location() == declNode::ENUM) {
00288     ipConstant * res = new ipConstant(block->decl()->init()->value());
00289     allocate(res);
00290     return res;
00291   }
00292 
00293   memoryDef * def = use->reaching_def();
00294 
00295   if (def) {
00296     const_variables_map_p found = _values.find(def);
00297     if (found == _values.end()) {
00298       cout << "lookup: Could not find " << def->owner()->decl()->name() << endl;
00299     }
00300     else {
00301       ipConstant * con = _values[def];
00302       if (con) {
00303 
00304         /*
00305         cout << "lookup: ";
00306         con->print(cout);
00307         cout << endl;
00308         */
00309 
00310         return clone(con);
00311       }
00312     }
00313   }
00314 
00315   return 0;
00316 }
00317 
00318 analysisVal * ipConstantPropagation::lookup(constNode * con)
00319 {
00320   ipConstant * out = 0;
00321 
00322   /*
00323   constants_map_p found = _constants.find(con);
00324   if (found == _constants.end()) {
00325     out = new ipConstant(con->value());
00326     _count++;
00327     _constants[con] = out;
00328   }
00329   else
00330     out = (*found).second;
00331   */
00332 
00333   out = new ipConstant(con->value());
00334   allocate(out);
00335 
00336   /*
00337   cout << "lookup const:";
00338   out->print(cout);
00339   cout << endl;
00340   */
00341 
00342   return out;
00343 }
00344 
00345 analysisVal * ipConstantPropagation::lookup(const string & field_name)
00346 {
00347   return 0;
00348 }
00349 
00350 // -- Clone
00351 
00352 ipConstant * ipConstantPropagation::clone(analysisVal * to_clone)
00353 {
00354   ipConstant * copy = new ipConstant( * ((ipConstant *) to_clone));
00355   allocate(copy);
00356   return copy;
00357 }
00358 
00359 // -- Free
00360 
00361 void ipConstantPropagation::free(analysisVal * to_free)
00362 {
00363   if (to_free) {
00364     ipConstant * ic_to_free = (ipConstant *) to_free;
00365   
00366     ipconstant_set_p p = _deleted.find(ic_to_free);
00367     if (p == _deleted.end()) {
00368       _deleted.insert(ic_to_free);
00369 
00370       /*
00371       cout << "Deallocate : (" << _count << ") ";
00372       ic_to_free->print(cout);
00373       cout << endl;
00374       */
00375 
00376       _count--;
00377     }
00378     else
00379       cout << "ERROR: Double delete" << endl;
00380   }
00381 }
00382 
00383 // -- Return the TOP flow value (not a copy)
00384 
00385 analysisVal * ipConstantPropagation::top()
00386 {
00387   return clone(_top);
00388 }
00389 
00390 // -- Return the BOTTOM flow value (not a copy)
00391 
00392 analysisVal * ipConstantPropagation::bottom()
00393 {
00394   return clone(_bottom);
00395 }
00396 
00397 // ------------------------------------------------------------
00398 // Computational Operators
00399 // ------------------------------------------------------------
00400 
00401 analysisVal * ipConstantPropagation::binary_operator(const Operator * op,
00402                                                      const analysisVal * left_operand,
00403                                                      const analysisVal * right_operand)
00404 {
00405   if ((op->id() == '.') || (op->id() == Operator::ARROW))
00406     return 0;
00407 
00408   ipConstant * left  = (ipConstant *) left_operand;
00409   ipConstant * right = (ipConstant *) right_operand;
00410 
00411   left->binary_operator(op, right);
00412 
00413   return left;
00414 }
00415 
00416 analysisVal * ipConstantPropagation::unary_operator(const Operator * op,
00417                                                     const analysisVal * operand)
00418 {
00419   if ((op->id() == Operator::ADDRESS) || (op->id() == Operator::INDIR))
00420     return 0;
00421 
00422   ipConstant * oper = (ipConstant *) operand;
00423 
00424   oper->unary_operator(op);
00425 
00426   return oper;
00427 }
00428 
00429 analysisVal * ipConstantPropagation::cast_operator(const typeNode * type,
00430                                       const analysisVal * operand)
00431 {
00432   ipConstant * oper = (ipConstant *) operand;
00433 
00434   oper->cast_operator(type);
00435 
00436   return oper;
00437 }
00438 
00439 // ------------------------------------------------------------
00440 // Stats
00441 // ------------------------------------------------------------
00442 
00443 void ipConstantPropagation::stats()
00444 {
00445   for (const_variables_map_p p = _values.begin();
00446        p != _values.end();
00447        ++p)
00448     {
00449       memoryDef * def = (*p).first;
00450       ipConstant * con = (*p).second;
00451 
00452       cout << "Value of " << def->owner()->decl()->name();
00453       def->print(cout);
00454       cout << "  = ";
00455       con->print(cout);
00456       cout << endl;
00457 
00458       if (def->where()->block() != 0) {
00459         stmtNode * stmt = def->where()->stmt();
00460 
00461         /*
00462           ostringstream com;
00463           com << "  " << def->owner()->decl()->name() << " = ";
00464           con->print(com);
00465           com << endl;
00466           stmt->comment() += com.str();
00467         */
00468       }
00469     }
00470 
00471   cout << "Total count = " << _count << endl;
00472   cout << "Accounted for = " << _values.size() << endl;
00473 }

Generated on August 27, 2003
Back to the C-Breeze home page