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  

procnode.cc

Go to the documentation of this file.
00001 // $Id: procnode.cc,v 1.9 2003/08/11 17:18:05 abrown 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 
00040 // -- Global pointer to the current procedure being parsed
00041 
00042 procNode * procNode::_current = (procNode *)0;
00043 
00044 // --------------------------------------------------------------------
00045 // Constructors
00046 // --------------------------------------------------------------------
00047 
00048 procNode::procNode(declNode * decl, blockNode * body, const Coord coord)
00049   : defNode(Proc, coord),
00050     _decl(decl),
00051     _body(body),
00052     _last_stack_local(0),
00053     _stack_frame_size(0),
00054     _return_label(NULL),
00055     _return_decl(NULL)
00056 {}
00057 
00058 // ------------------------------------------------------------
00059 // -- This constructor corresponds to DefineProc in procedure.c
00060 //     (old version)
00061 // ------------------------------------------------------------
00062 
00063 extern char * cbtext;
00064 
00065 procNode::procNode(bool old_style, declNode * decl_in)
00066   : defNode(Proc, decl_in->coord()),
00067     _decl(decl_in),
00068     _body(0),
00069     _last_stack_local(0),
00070     _stack_frame_size(0),
00071     _return_label(NULL),
00072     _return_decl(NULL)
00073 {
00074   assert(decl_in);
00075   declNode * the_decl = decl_in;
00076 
00077   funcNode * func = (funcNode *) the_decl->type();
00078   
00079   assert(func);
00080 
00081   if (func->typ() != Func) {
00082     CBZ::SyntaxError(the_decl->coord(), 
00083                      string("expecting a function definition"));
00084     return;
00085   }
00086 
00087   // since the parser uses the '{' to determine that
00088   //   this is a definition, we know that cblex() just returned
00089   //   the '{' and so has entered the scope for the upcoming body.
00090 
00091   assert(*cbtext == '{'); // verify that last token was '{'
00092   // This doesn't make sense anymore: assert(CBZ::current_unit->symbol_level() == 0);
00093 
00094   // what the hell was this statement for?  all finish does is set
00095   // the storage class, so all this does is blow it away; it may
00096   // have been static, but it just throws it away.  argh!
00097 
00098   //the_decl->finish(declNode::NONE);
00099 
00100   // this preserves the storage class and calls finish; basically a no-op,
00101   // but maybe finish will do something else in the future?
00102 
00103   the_decl->finish(the_decl->storage_class());
00104   the_decl->decl_location(declNode::PROC);
00105 
00106   // We know that this is a function definition, rather than merely a
00107   // declaration.  Convert an empty arglist to (void) and then recheck
00108   // the definition against the external scope (where the previous
00109   // declarations will be).
00110 
00111   // -- Maintain the static "current" procedure pointer...
00112 
00113   _current = this;
00114 
00115   if (func->args().empty()) {
00116 
00117     // -- Create "void" arguments
00118 
00119     declNode * void_decl = new declNode(new primNode(basic_type::Void, func->coord()), declNode::NONE);
00120     void_decl->decl_location(declNode::FORMAL);
00121 
00122     func->args().push_front(void_decl);
00123 
00124     // -- Recheck against the prototype
00125     /*
00126     declNode * orig = CBZ::current_unit->externs()->insert(the_decl->name(), the_decl);
00127     if (orig) {
00128 
00129       // -- FunctionConflict from procedure.c
00130 
00131       funcNode * ofunc = (funcNode *) orig->type();
00132 
00133       // -- If the old definition is not compatible...
00134 
00135       if (! ofunc->is_compatible_with(func)) {
00136         // CBZ::SyntaxError(coord(),
00137         //               string("function identifier `") + 
00138         //               the_decl->name() + string("' redeclared"));
00139         // cerr << "\tPrevious declaration: " << orig->coord() << endl;
00140       }
00141     }
00142     */
00143   }
00144 
00145   if (old_style) {
00146 
00147     declNode * var = the_decl;
00148 
00149     // -- NOTE: This is done in the parse: identifier.list
00150     // Convert any formals of type ID to the default DECL
00151 
00152     if (false) {
00153       decl_list & the_args = func->args();
00154       decl_list_p p;
00155       decl_list new_args;
00156 
00157       for (p = the_args.begin(); p != the_args.end(); ++p) {
00158         if ((*p)->typ() == Id) {
00159           idNode * id = (idNode *) (*p);
00160 
00161           // -- Make the id into a declaration node
00162           declNode * d = new declNode(id, declNode::NONE,
00163                                           new primNode(id->coord()),
00164                                           (exprNode *) 0, (exprNode *) 0);
00165           d->decl_location(declNode::FORMAL);
00166           new_args.push_back(d);
00167         }
00168         else
00169           new_args.push_back(*p);
00170 
00171       } // -- END for all args
00172 
00173       // -- Replace with new arguments..
00174 
00175       func->args().swap(new_args);
00176     }
00177 
00178     // -- Insert the declaration for the first time...
00179     /*
00180     declNode * orig;
00181     orig = CBZ::current_unit->externs()->insert(the_decl->name(), var);
00182     if (! orig)
00183       orig = CBZ::current_unit->ids()->insert(the_decl->name(), var);
00184 
00185     // -- Check for conflict...
00186 
00187     if (orig) {
00188       // -- FunctionConflict from procedure.c
00189 
00190       funcNode * ofunc = (funcNode *) orig->type();
00191 
00192       // -- If the old definition is not compatible...
00193       
00194       if (! ofunc->is_compatible_with(func)) {
00195         // CBZ::SyntaxError(coord(),
00196         //               string("function identifier `") + 
00197         //               the_decl->name() + string("' redeclared"));
00198         // cerr << "\tPrevious declaration: " << orig->coord() << endl;
00199       }
00200     }
00201     */
00202   } // -- END if old_style
00203 
00204   // -- Enter scope of function body
00205 
00206   CBZ::current_unit->enter_scope();
00207 
00208   // -- Add formals to the scope of the upcoming block
00209 
00210   decl_list & the_args = func->args();
00211   decl_list_p p;
00212 
00213   bool first = true;
00214   for (p = the_args.begin(); p != the_args.end(); ++p) {
00215 
00216     if ((*p)->datatype()->is_ellipsis())
00217       ;
00218     else
00219       if ((*p)->datatype()->is_void()) {
00220         if (! first)
00221           CBZ::SyntaxError((*p)->coord(),
00222                            string("void argument must be first"));
00223       }
00224       else
00225         if ((*p)->typ() == Decl) {
00226 
00227           // -- Normal declaration...
00228           /*
00229           declNode * a_decl = (declNode *) (*p);
00230           declNode * o_decl = CBZ::current_unit->ids()->insert(a_decl->name(), a_decl);
00231 
00232           // -- Check for conflict...
00233           if (o_decl)
00234             CBZ::SyntaxError(a_decl->coord(),
00235                              string("formal `") + 
00236                              o_decl->name() + string("' used multiple times"));
00237           */
00238 
00239         } else
00240           CBZ::SyntaxError((*p)->coord(),
00241                            string("argument without a name"));
00242 
00243     first = false;
00244   }
00245 }
00246 
00247 // ------------------------------------------------------------
00248 // Was SetProcBody in procedure.c
00249 // ------------------------------------------------------------
00250 
00251 void procNode::define(blockNode * the_body)
00252 {
00253   assert(decl());
00254 
00255   CBZ::current_unit->exit_scope();
00256 
00257   body(the_body);
00258 
00259   if (! the_body) {
00260     CBZ::Warning(4, decl()->coord(),
00261                  string("procedure `") + decl()->name() + 
00262                  string("' has no code"));
00263   } else {
00264     // -- NOTE: This is handled by goto_label_walker...
00265     // check for unreferenced/unresolved labels,
00266     //   all labels are now out of scope
00267     // Symbols::Labels->reset();
00268   }
00269 
00270   _current = 0;
00271 }
00272 
00273 procNode * procNode::define_and(blockNode * the_body)
00274 {
00275   define(the_body);
00276   return this;
00277 }
00278 
00279 // ------------------------------------------------------------
00280 // For use in CFG form
00281 // ------------------------------------------------------------
00282 
00283 basicblockNode * procNode::entry() const
00284 {
00285   return (basicblockNode *) _body->stmts().front();
00286 }
00287 
00288 basicblockNode * procNode::exit() const
00289 {
00290   return (basicblockNode *) _body->stmts().back();
00291 }
00292 
00293 // ------------------------------------------------------------
00294 // Data type base
00295 // ------------------------------------------------------------
00296 
00297 typeNode * procNode::base_type(bool TdefIndir) const
00298 {
00299   return decl()->base_type(TdefIndir);
00300 }
00301 
00302 // ------------------------------------------------------------
00303 //  Walker
00304 // ------------------------------------------------------------
00305 
00306 void procNode::visit(Visitor * the_visitor) 
00307 {
00308   the_visitor->at_proc(this);
00309 }
00310 
00311 void procNode::walk(Walker & the_walker)
00312 {
00313   Walker::Order ord = the_walker.order(); 
00314 
00315   if (ord == Walker::Preorder || ord == Walker::Both)
00316     the_walker.at_proc(this, Walker::Preorder);
00317 
00318   if (the_walker.depth() == Walker::Subtree) {
00319     // -- Visit the children 
00320 
00321     list_walker(pragmas(), the_walker);
00322 
00323     if (decl())
00324       decl()->walk(the_walker);
00325 
00326     if (body())
00327       body()->walk(the_walker);
00328   }
00329 
00330   if (ord == Walker::Postorder || ord == Walker::Both)
00331     the_walker.at_proc(this, Walker::Postorder);
00332 }
00333 
00334 // ------------------------------------------------------------
00335 //  Dataflow
00336 // ------------------------------------------------------------
00337 
00338 void procNode::dataflow(FlowVal * v, FlowProblem & fp)
00339 {
00340   if (fp.forward()) {
00341     fp.flow_proc(v, this, FlowProblem::Entry);
00342 
00343     if (body())
00344       body()->dataflow(v, fp);
00345 
00346     v->meet(at_exit());
00347 
00348     fp.flow_proc(v, this, FlowProblem::Exit);
00349   }
00350   else {
00351     fp.flow_proc(v, this, FlowProblem::Exit);
00352 
00353     v->meet(at_exit());
00354 
00355     if (body())
00356       body()->dataflow(v, fp);
00357 
00358     fp.flow_proc(v, this, FlowProblem::Entry);
00359   }
00360 }
00361 
00362 // ------------------------------------------------------------
00363 // Output
00364 // ------------------------------------------------------------
00365 
00366 void procNode::output(output_context & ct, Node * parent)
00367 {
00368   decl()->output(ct, this);
00369 
00370   if (body())
00371     body()->output(ct, this);
00372   else
00373     ct << '{' << '}';
00374 }
00375 
00376 
00377 // ------------------------------------------------------------
00378 //  Changer
00379 // ------------------------------------------------------------
00380 
00381 Node * procNode::change(Changer & the_changer, bool redispatch)
00382 {
00383   Changer::Order ord = the_changer.order(); 
00384   procNode * the_proc = this;
00385 
00386   if ((ord == Changer::Preorder || ord == Changer::Both) && ! redispatch)
00387     the_proc = (procNode *) the_changer.at_proc(the_proc, Changer::Preorder);
00388 
00389   if (the_proc) {
00390 
00391     if (the_proc != this)
00392       return the_proc->change(the_changer, true);
00393 
00394     change_list(the_proc->pragmas(), the_changer);
00395 
00396     declNode * old_decl = the_proc->decl();
00397     if (old_decl) {
00398       declNode * new_decl = (declNode *) old_decl->change(the_changer);
00399       if (old_decl != new_decl) {
00400         //if (the_changer.delete_old())
00401           //delete old_decl;
00402         the_proc->decl(new_decl);
00403       }
00404     }
00405 
00406     blockNode * old_body = the_proc->body();
00407     if (old_body) {
00408       blockNode * new_body = (blockNode *) old_body->change(the_changer);
00409       if (old_body != new_body) {
00410         //if (the_changer.delete_old())
00411           //delete old_body;
00412         the_proc->body(new_body);
00413       }
00414     }
00415 
00416   }
00417 
00418   if ((ord == Changer::Postorder || ord == Changer::Both) && ! redispatch)
00419     the_proc = (procNode *) the_changer.at_proc(the_proc, Changer::Postorder);
00420 
00421   return the_proc;
00422 }
00423 
00424 // ------------------------------------------------------------
00425 // Stack allocation
00426 // ------------------------------------------------------------
00427 
00428 void procNode::set_initial_stack_local_offset( int offset ) 
00429 {
00430         // save this for later
00431         _last_stack_local = offset;
00432 }
00433 
00434 int procNode::alloc_stack_local( declNode * decl ) {
00435   // we need arch info to do this
00436   if ( ! CBZ::ArchInfo.is_valid() ) {
00437     CBZFAIL(("Can't allocate stack space for declaration - missing "
00438              "architecture info.  Specify with -arch."));
00439   }
00440 
00441   declNode::Storage_location & loc = decl->storage_location();
00442 
00443   // is it already done?
00444   if ( loc._type == declNode::Storage_location::storageloc_stack )
00445     return loc._stack_offset;
00446 
00447   // how big is it?
00448   int size = decl->type()->alloc_size();
00449   assert( size > 0 );
00450   int align = decl->type()->alloc_align();
00451   assert( align > 0 );
00452 
00453   // adjust our last allocated location for this thing
00454   _last_stack_local = (( (_last_stack_local - size) - align + 1 )
00455                        / align ) * align;
00456   loc._type = declNode::Storage_location::storageloc_stack;
00457   loc._stack_offset = _last_stack_local;
00458 
00459   // return what we decided on
00460   return _last_stack_local;
00461 }
00462 
00463 // ------------------------------------------------------------
00464 // Destructor
00465 // ------------------------------------------------------------
00466 
00467 procNode::~procNode()
00468 {
00469   //delete _decl;
00470   //delete _body;
00471 }
00472 

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