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  

dismantle-static.cc

Go to the documentation of this file.
00001 // ----------------------------------------------------------------------
00002 //
00003 //  C-Breeze
00004 //  C Compiler Framework
00005 // 
00006 //  Copyright (c) 2000 University of Texas at Austin
00007 // 
00008 //  Samuel Z. Guyer
00009 //  Daniel A. Jimenez
00010 //  Calvin Lin
00011 //  Adam Brown
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 // dismantle-static.cc
00039 //
00040 
00041 #include <sstream>
00042 #include "c_breeze.h"
00043 #include "dismantle.h"
00044 #include "ref_clone_changer.h"
00045 
00046 StaticToGlobalDismantle::StaticToGlobalDismantle(void) :
00047   Changer(Both, Subtree, false),
00048   _cur_unit(0),
00049   _cur_proc(0),
00050   _declareProc(false)
00051 {}
00052 
00053 class UpdateTdefChanger : public Changer {
00054 public:
00055   UpdateTdefChanger(const map<typeNode *, string> & newNames) :
00056     Changer(Preorder, Subtree, false),
00057     _newNames(newNames)
00058   {}
00059   Node * at_tdef(tdefNode * the_tdef, Order ord) {
00060     if ( _newNames.find(the_tdef->def()) != _newNames.end() )
00061       the_tdef->name(_newNames[the_tdef->def()]);
00062     return the_tdef;
00063   }
00064 private:
00065   map<typeNode *, string> _newNames;
00066 };
00067 
00068 Node * StaticToGlobalDismantle::at_unit(unitNode * the_unit, Order ord) {
00069   if ( ord == Preorder ) {
00070     _cur_unit = the_unit;
00071     _topLevelSuespecs.clear();
00072   } else {
00073     UpdateTdefChanger utc(_newTypedefName);
00074     the_unit->change(utc);
00075   }
00076   return the_unit;
00077 }
00078 
00079 void StaticToGlobalDismantle::rename_decl(declNode * to_rename,
00080                                           procNode * the_proc) {
00081   if ( to_rename->storage_class() != declNode::EXTERN ) {
00082     if ( !to_rename->name().empty() ) {
00083       // rename the decl to ensure uniqueness at top level
00084       ostringstream ost;
00085       ost << DismantleUtil::new_id() << "_" << the_proc->decl()->name()
00086           << "_" << to_rename->name();
00087       to_rename->name(ost.str());
00088 
00089       // update referring idNode's name()
00090       for ( id_list_p id = to_rename->ref_list().begin();
00091             id != to_rename->ref_list().end();
00092             id++ )
00093         (*id)->name(to_rename->name());
00094 
00095       if ( to_rename->storage_class() == declNode::TYPEDEF ) {
00096         _newTypedefName[to_rename->type()] = to_rename->name();
00097 
00098         if ( sueNode * the_sue = dynamic_cast<sueNode *>(to_rename->type()) ) {
00099           // also need to rename the struct tag, if the struct was
00100           // defined inside a procedure
00101           suespecNode * the_suespec = the_sue->spec();
00102           if (_topLevelSuespecs.find(the_suespec) == _topLevelSuespecs.end()) {
00103             ostringstream sueost;
00104             sueost << DismantleUtil::new_id() << "_" 
00105                    << the_proc->decl()->name()
00106                    << "_" << the_suespec->name();
00107             the_suespec->name(sueost.str());
00108           }
00109         }
00110       }
00111     } else {
00112       // this must be a declaration for a sue type w/o a typedef
00113       sueNode * the_sue = dynamic_cast<sueNode *>(to_rename->type());
00114       assert(the_sue);
00115       suespecNode * the_suespec = the_sue->spec();
00116 
00117       ostringstream ost;
00118       ost << DismantleUtil::new_id() << "_" << the_proc->decl()->name()
00119           << "_" << the_suespec->name();
00120       the_suespec->name(ost.str());
00121     }
00122   } // end if ( ... != declNode::EXTERN )
00123 }
00124 
00125 Node * StaticToGlobalDismantle::at_proc(procNode * the_proc, Order ord) {
00126   if ( ord == Preorder ) {
00127     _cur_proc = the_proc;
00128     _declsToMove.clear();
00129     _declareProc = false;
00130   } else { // ord == Postorder
00131     assert(_blockStack.empty());
00132     def_list_p procIter = find(_cur_unit->defs().begin(),
00133                                _cur_unit->defs().end(),
00134                                the_proc);
00135     if ( _declareProc ) {
00136       declNode * proc_decl = 
00137         (declNode *) ref_clone_changer::clone(the_proc->decl(), false);
00138       proc_decl->decl_location(declNode::TOP);
00139       _cur_unit->defs().insert(procIter, proc_decl);
00140     }
00141 
00142     set<declNode *> moved;
00143     for ( map<declNode *, decl_list>::iterator p = _declsToMove.begin();
00144           p != _declsToMove.end();
00145           p++ ) {
00146       for ( decl_list_p q = p->second.begin(); q != p->second.end(); q++ ) {
00147         if ( moved.find(*q) == moved.end() ) {
00148           _cur_unit->defs().insert(procIter, *q);
00149           moved.insert(*q);
00150           (*q)->decl_location(declNode::TOP);
00151           rename_decl(*q, the_proc);
00152         }
00153       }
00154       _cur_unit->defs().insert(procIter, p->first);
00155       p->first->decl_location(declNode::TOP);
00156       rename_decl(p->first, the_proc);
00157     }
00158   }
00159   return the_proc;
00160 }
00161 
00162 Node * StaticToGlobalDismantle::at_block(blockNode * the_block, Order ord) {
00163   if ( ord == Preorder ) {
00164     _blockStack.push_front(the_block);
00165   } else { // ord == Postorder
00166     assert(_blockStack.front() == the_block);
00167     _blockStack.pop_front();
00168   }
00169   return the_block;
00170 }
00171 
00172 class RequiresGatherer : public Walker {
00173 public:
00174   RequiresGatherer(void) :
00175     Walker(Preorder, Subtree)
00176   {}
00177   virtual void at_id(idNode * the_id, Order ord) {
00178     _decls.push_back(the_id->decl());
00179     the_id->decl()->walk(*this);
00180   }
00181   virtual void at_tdef(tdefNode * the_tdef, Order ord) {
00182     _types.push_back(the_tdef->def());
00183     the_tdef->def()->walk(*this);
00184   }
00185   virtual void at_sue(sueNode * the_sue, Order ord) {
00186     _types.push_back(the_sue);
00187   }
00188   bool requires(declNode * the_decl) {
00189     bool isReqdDecl = ( find(_decls.begin(), _decls.end(), the_decl)
00190                         != _decls.end() );
00191     bool isReqdTypedef = the_decl->storage_class() == declNode::TYPEDEF
00192       && ( find(_types.begin(), _types.end(), the_decl->type())
00193            != _types.end() );
00194     bool isAbstract = the_decl->name().empty();
00195     bool matchingSuespec = false;
00196     if ( sueNode * decl_sue = dynamic_cast<sueNode *>(the_decl->type()) ) {
00197       suespecNode * decl_spec = decl_sue->spec();
00198       for ( list<typeNode *>::iterator p = _types.begin();
00199             p != _types.end();
00200             p++ ) {
00201         if ( sueNode * the_sue = dynamic_cast<sueNode *>(*p) )
00202           if ( decl_spec == the_sue->spec() )
00203             matchingSuespec = true;
00204       }
00205     }
00206 
00207     return ( isReqdDecl || isReqdTypedef || (isAbstract && matchingSuespec) );
00208   }
00209 private:
00210   decl_list _decls;
00211   list < typeNode * > _types;
00212 };
00213 
00214 Node * StaticToGlobalDismantle::at_decl(declNode * the_decl, Order ord) {
00215   if ( ord == Preorder ) {
00216     if ( the_decl->decl_location() == declNode::TOP ) {
00217       // gather listing of struct's defined at the top level, so that
00218       // they don't get inadvertently renamed
00219       if ( sueNode * the_sue = dynamic_cast<sueNode *>(the_decl->type()) ) {
00220         _topLevelSuespecs.insert(the_sue->spec());
00221       }
00222     } else if ( the_decl->storage_class() == declNode::STATIC 
00223                 && the_decl->decl_location() == declNode::BLOCK ) {
00224       // ensure that the_decl appears in _declsToMove
00225       _declsToMove[the_decl].clear();
00226 
00227       RequiresGatherer rg;
00228       the_decl->walk(rg);
00229 
00230       _declareProc = _declareProc || rg.requires(_cur_proc->decl());
00231 
00232       decl_list_p iter = _declsToMove[the_decl].end();
00233       block_list_p p = _blockStack.begin();
00234       while ( p != _blockStack.end() ) {
00235         blockNode * cur_block = *p;
00236         p++;
00237         // determine if cur_block contains any Nodes that the_decl
00238         // depends upon.
00239         decl_list_p q = cur_block->decls().begin();
00240         while ( q != cur_block->decls().end() ) {
00241           declNode * cur_decl = *q;
00242           q++;
00243 
00244           if ( rg.requires(cur_decl) ) {
00245             cur_block->decls().remove(cur_decl);
00246             _declsToMove[the_decl].insert(iter, cur_decl);
00247           }
00248         }
00249         iter = _declsToMove[the_decl].begin();
00250       }
00251       return NULL; // remove this decl from original location
00252     }
00253   }
00254   return the_decl;
00255 }

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