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  

linker.cc

Go to the documentation of this file.
00001 // $Id: linker.cc,v 1.10 2003/08/07 23:13:48 pnav Exp $
00002 // ----------------------------------------------------------------------
00003 //
00004 //  C-Breeze
00005 //  C Compiler Framework
00006 // 
00007 //  Copyright (c) 2003 University of Texas at Austin
00008 // 
00009 //  Samuel Z. Guyer
00010 //  Adam Brown
00011 //  Teck Bok Tok
00012 //  Paul Arthur Navratil
00013 //  Calvin Lin
00014 // 
00015 //  Permission is hereby granted, free of charge, to any person
00016 //  obtaining a copy of this software and associated documentation
00017 //  files (the "Software"), to deal in the Software without
00018 //  restriction, including without limitation the rights to use, copy,
00019 //  modify, merge, publish, distribute, sublicense, and/or sell copies
00020 //  of the Software, and to permit persons to whom the Software is
00021 //  furnished to do so, subject to the following conditions:
00022 //  
00023 //  The above copyright notice and this permission notice shall be
00024 //  included in all copies or substantial portions of the Software.
00025 //  
00026 //  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00027 //  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00028 //  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00029 //  NONINFRINGEMENT.  IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT
00030 //  AUSTIN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
00031 //  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
00032 //  OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00033 //  THE SOFTWARE.
00034 //
00035 //  We acknowledge the C-to-C Translator from MIT Laboratory for
00036 //  Computer Science for inspiring parts of the C-Breeze design.
00037 //
00038 // ----------------------------------------------------------------------
00039 
00040 #include "c_breeze.h"
00041 #include "linker.h"
00042 #include "ref_clone_changer.h"
00043 
00044 bool Linker::debug = false;
00045 
00046 Linker::Linker()
00047   : Walker(Preorder, Subtree),
00048     _external_symbols(),
00049     _internal_symbols(),
00050     _procedure_declarations(),
00051     _synthetic(),
00052     current_unit(0)
00053 {}
00054 
00055 Linker::~Linker()
00056 {
00057   clear();
00058 }
00059 
00060 void Linker::clear()
00061 {
00062   // -- Clear the symbol tables
00063 
00064   _external_symbols.clear();
00065   _internal_symbols.clear();
00066   _procedure_declarations.clear();
00067 
00068   // -- Put the synthetics back in the tables
00069 
00070   for (decl_name_map_p p = _synthetic.begin();
00071        p != _synthetic.end();
00072        ++p)
00073     {
00074       declNode * synth = (*p).second;
00075       _synthetic[synth->name()] = synth;
00076       _external_symbols[synth->name()] = synth;
00077     }
00078 
00079   current_unit = 0;
00080 }
00081 
00082 void Linker::link()
00083 {
00084 
00085   // -- Make sure the tables are clear
00086 
00087   clear();
00088 
00089   // -- First pass, collect all the external and internal definitions
00090   // (including both procedure definitions and global variables).
00091 
00092   if (debug)
00093     cout << "Linker: first pass, collect external and internal symbols" << endl;
00094 
00095   for (unit_list_p up = CBZ::Program.begin();
00096        up != CBZ::Program.end();
00097        ++up)
00098     {
00099       unitNode * unit = (*up);
00100       def_list & ds = unit->defs();
00101 
00102       // -- Visit all the top-level and store them according to their
00103       // linkage...
00104 
00105       for (def_list_p p = ds.begin();
00106            p != ds.end();
00107            ++p) {
00108         defNode * d = (*p);
00109         procNode * proc = 0;
00110         declNode * decl = 0;
00111 
00112         if (d->typ() == Proc) {
00113           proc = (procNode *) d;
00114           decl = proc->decl();
00115           if (decl->decl_location() == declNode::PROC)
00116             _procedure_declarations[decl] = proc;
00117         }
00118 
00119         if (d->typ() == Decl)
00120           decl = (declNode *)d;
00121 
00122         if (decl) {
00123           if (decl->storage_class() == declNode::STATIC) {
00124             _internal_symbols[unit][decl->name()] = decl;
00125             if (debug)
00126               cout << "    " << decl->name() << " at " << decl->coord() <<
00127                 " : internal to " << unit->input_file() << endl;
00128           }
00129           else {
00130 
00131             // External declarations are either procedure definitions or
00132             // top-level variables. We need to make sure to skip over
00133             // function declarations (top-level variables of type Func).
00134             
00135             bool is_procedure_definition = (decl->decl_location() == declNode::PROC);
00136             bool is_toplevel_var = (decl->storage_class() == declNode::NONE) &&
00137               (decl->decl_location() == declNode::TOP) && (decl->type()->typ() != Func);
00138 
00139             if (is_procedure_definition || is_toplevel_var) {
00140               _external_symbols[decl->name()] = decl;
00141               if (debug)
00142                 cout << "    " << decl->name() << " at " << decl->coord() <<
00143                   " : extern -- declared in " << unit->input_file() << endl;
00144             }
00145           }
00146         }
00147         
00148       } // END for all top-level definitions
00149 
00150     } // END for all translation units
00151 
00152 
00153   // -- Second pass, look for "extern" declarations for which there is no
00154   // actual definition. Create a synthetic declNode and enter it into the
00155   // externals map. Note that for external procedures, we create a single
00156   // declNode, but we don't attempt to create a synthetic procNode. That
00157   // could confuse some algorithms.
00158 
00159   if (debug)
00160     cout << "Linker: second pass, find externals with no definition:" << endl;
00161 
00162   for (unit_list_p up = CBZ::Program.begin();
00163        up != CBZ::Program.end();
00164        ++up)
00165     {
00166       unitNode * unit = (*up);
00167       def_list & ds = unit->defs();
00168 
00169       // -- Visit all the top-level definitions...
00170 
00171       for (def_list_p p = ds.begin();
00172            p != ds.end();
00173            ++p) {
00174         defNode * d = (*p);
00175 
00176         // If this is a declaration...
00177 
00178         if (d->typ() == Decl) {
00179           declNode * decl = (declNode *)d;
00180 
00181           // ... and it's extern...
00182 
00183           if ((decl->storage_class() == declNode::EXTERN) ||
00184               (decl->type()->typ() == Func)) {
00185 
00186             // ... and there's no entry for it already...
00187 
00188             bool unused;
00189             if ( ! lookup_symbol(unit, decl->name(), unused)) {
00190 
00191               // ... then create one.
00192               
00193               create_synthetic(decl);
00194 
00195               if (debug)
00196                 cout << "    " << decl->name() << " is synthetic." << endl;
00197             }
00198           }
00199         }
00200 
00201       } // END for all top-level definitions
00202       
00203     } // END for all translation units
00204 
00205   // Finally, walk the entire set of ASTs, fixing the declaration
00206   // references on the idNodes.
00207   
00208   if (debug)
00209     cout << "Linker: third pass, fix idNode declarations:" << endl;
00210 
00211   for (unit_list_p up = CBZ::Program.begin();
00212        up != CBZ::Program.end();
00213        ++up)
00214     {
00215       unitNode * unit = (*up);
00216       current_unit = unit;
00217       unit->walk(*this);
00218     }
00219 }
00220 
00223 declNode * Linker::lookup_symbol(unitNode * current, string name,
00224                                  bool & is_synthetic_decl)
00225 {
00226   // See if it's a synthetic
00227 
00228   is_synthetic_decl = (_synthetic.find(name) != _synthetic.end());
00229  
00230   // First look for a variable with internal linkage
00231 
00232   decl_name_map & current_unit_internals = _internal_symbols[current];
00233   decl_name_map_p p = current_unit_internals.find(name);
00234   if (p == current_unit_internals.end()) {
00235 
00236     // Not found, search for a global with external linkage
00237 
00238     p = _external_symbols.find(name);
00239     if (p == _external_symbols.end()) 
00240     {
00241       //cout << "Whoops!  returning null for a declaration" << endl;
00242       return 0;
00243     }
00244   }
00245 
00246   return (*p).second;
00247 }
00248 
00251 procNode * Linker::lookup_procedure(declNode * decl)
00252 {
00253   // First look for the procedure symbol
00254 
00255   if (decl) {
00256     proc_decl_map_p p = _procedure_declarations.find(decl);
00257     if (p != _procedure_declarations.end())
00258       return (*p).second;
00259   }
00260 
00261   return 0;
00262 }
00263 
00264 bool Linker::create_synthetic(declNode * local_decl)
00265 {
00266   decl_name_map_p p = _synthetic.find(local_decl->name());
00267   if (p != _synthetic.end()) {
00268     cerr << "Linker error: external variable \"" << local_decl->name() <<
00269       "\" has duplicate definitions." << endl;
00270     return false;
00271   }
00272   else {
00273     declNode * decl = (declNode *) ref_clone_changer::clone(local_decl, false);
00274     _synthetic[local_decl->name()] = decl;
00275     _external_symbols[decl->name()] = decl;    
00276     return true;
00277   }
00278 }
00279 
00280 // at_id: At each idNode, if the variable refers to some global symbol,
00281 // then look it up and set the declaration pointer appropriately.
00282 
00283 void Linker::at_id(idNode * the_id, Order ord)
00284 {
00285   declNode * decl = the_id->decl();
00286   bool lookup = false;
00287 
00288   // Figure out if this identifier refers to a global variable. We'll
00289   // assume that any variable with no declaration pointer is also a global
00290   // variable.
00291 
00292   /*lookup is false if it is a decl and a block variable*/
00293   if (decl) {
00294     if ((decl->decl_location() == declNode::TOP) || /*global*/
00295         (decl->decl_location() == declNode::PROC) || /*??*/
00296         (decl->decl_location() == declNode::UNKNOWN)) /*screwed up*/
00297       lookup = true;
00298 
00299     if (decl->type() && (decl->type()->typ() == Func))
00300       lookup = true;
00301   }
00302   else
00303     lookup = true;
00304 
00305   if (lookup) {
00306 
00307     // Look up the symbol, first searching the internal linkage, then the
00308     // external linkage. Set the idNode's declaration.
00309 
00310     bool is_synthetic_decl;
00311     declNode * real_decl = lookup_symbol(current_unit, the_id->name(), is_synthetic_decl);
00312     the_id->decl(real_decl);
00313 
00314     if (debug) {
00315       cout << "    " << the_id->name() << " at " << the_id->coord();
00316       if (real_decl)
00317         cout << " : actual declaration at " << real_decl->coord() << endl;
00318       else
00319         cout << " : no declaration found." << endl;
00320     }
00321   }
00322 }
00323 
00329 void Linker::at_call(callNode * the_call, Order ord)
00330 {
00331   if (the_call->name()->typ() == Id) {
00332     idNode * the_id = (idNode *) the_call->name();
00333 
00334     process_call(the_id, the_call);
00335   }
00336 }
00337 
00338 
00343 void
00344 Linker::at_threeAddr(threeAddrNode * ta, Order ord)
00345 {
00351    /*Do we have a callNode?*/
00352    if (ta->op() && ta->op()->id()==Operator::FUNC_CALL)
00353    { 
00354       operandNode * o = (operandNode *) ta->rhs1();
00355       assert(o);
00356       indexNode * i = o->var();
00357   
00358       assert(i->typ()==Id); /*since we know this is a call, can't be a const*/
00359       idNode * call = (idNode *)i;
00360 
00361       bool is_func_ptr = o->star() || !o->fields().empty() || o->index() ||
00362                          call->decl()->type()->follow_tdefs()->typ() == Ptr;
00363 
00364       if(! is_func_ptr)
00365         process_call(call, NULL);
00366    }
00367 }
00368 
00373 void
00374 Linker::process_call(idNode * call, callNode * callnode)
00375 {
00376    bool unused;
00377    declNode * real_decl = lookup_symbol(current_unit, call->name(), unused);
00378 
00379    if (! real_decl) {
00380 
00381       // Found a function call where the function name is undeclared (old
00382       // style).
00383 
00384       declNode * decl = call->decl();
00385       create_synthetic(decl);
00386 
00387       if (debug)
00388          cout << "    " << decl->name() << " is a synthetic, old-style function." << endl;
00389    }
00390    else if(callnode)
00391    {
00392 
00393       // -- Point to the called procedure
00394 
00395       callnode->proc(lookup_procedure(real_decl));
00396    }
00397 }
00398 
00399 proc_decl_map & Linker::procedure_declarations()
00400 {
00401    return _procedure_declarations;
00402 }
00403 

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