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  

main.cc

Go to the documentation of this file.
00001 // $Id: main.cc,v 1.20 2003/08/11 17:20:21 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 #include "c_breeze.h"
00038 #include "print_walker.h"
00039 #include "ref_clone_changer.h"
00040 #include "scope_walker.h"
00041 #include "id_lookup_walker.h"
00042 #include "goto_label_walker.h"
00043 #include "cfg.h"
00044 #include "bits.h"
00045 #include "live.h"
00046 #include "dead.h"
00047 #include "localcopyprop.h"
00048 #include "gc_walker.h"
00049 #include "lir_gen_walker.h"
00050 #include "lir_flow_walker.h"
00051 #include "briggs_reg_alloc.h"
00052 #include "dummy_reg_alloc.h"
00053 #include "asm_gen_walker.h"
00054 #include "dismantle.h"
00055 #include "tree_checker.h"
00056 #include "inliner.h"
00057 
00058 #include <unistd.h>
00059 
00063 // ------------------------------------------------------------
00064 // Predefined Phases
00065 // ------------------------------------------------------------
00066 
00070 class print_ast_phase : public Phase
00071 {
00072 public:
00073 
00074   void run()
00075   {
00076     for (unit_list_p p = CBZ::Program.begin();
00077          p != CBZ::Program.end();
00078          ++p)
00079       print_walker::print(*p, cout);
00080   }
00081 };
00082 
00083 Phases Print_AST("ast", new print_ast_phase());
00084 
00088 class output_c_phase : public Phase
00089 {
00090 public:
00091 
00092   void run()
00093   {
00094       for (unit_list_p p = CBZ::Program.begin();
00095        p != CBZ::Program.end();
00096            ++p) {
00097 
00098         unitNode * the_unit = (*p);
00099 
00100         // haven't output any sue bodies for
00101         // this unit yet
00102 
00103         if (the_unit->output_file() == "(stdout)") {
00104           output_context a = output_context(cout);
00105           the_unit->output(a, 0);
00106           cout << endl;
00107         }
00108         else {
00109           ofstream outf(the_unit->output_file().c_str());
00110           output_context b = output_context(outf);
00111           the_unit->output(b, 0);
00112           outf << endl;
00113         }
00114       }
00115   }
00116 };
00117 
00118 Phases Output_C("c-code", new output_c_phase());
00119 
00123 class DismantleControlChangerPhase : public Phase {
00124 public:
00125 
00126   void run() {
00127     unit_list_p n;
00128     // dismantle each unit
00129 
00130     for (n=CBZ::Program.begin(); n != CBZ::Program.end(); n++)
00131       Dismantle::dismantle_control(*n);
00132   }
00133 };
00134 
00135 Phases dismantle_control_phase("dismantle-control", 
00136                                new DismantleControlChangerPhase());
00137 
00141 class DismantleChangerPhase : public Phase {
00142 public:
00143 
00144   void run() {
00145     unit_list_p n;
00146     // dismantle each unit
00147 
00148     for (n=CBZ::Program.begin(); n != CBZ::Program.end(); n++)
00149       Dismantle::dismantle(*n);
00150   }
00151 };
00152 
00153 Phases dismantle_phase("dismantle", new DismantleChangerPhase());
00154 
00158 class CfgPhase : public Phase {
00159 public:
00160   void run() {
00161     unit_list_p n;
00162     for ( n = CBZ::Program.begin(); n != CBZ::Program.end(); n++ )
00163       cfg_changer::generate_cfg(*n);
00164   }
00165 };
00166 
00167 Phases make_cfg_phase("cfg", new CfgPhase());
00168 
00169 // phase to generate LIR code for a translation unit
00170 class lirGenWalkerPhase: public Phase {
00171 public: 
00172   void run() {
00173     // do we have architecture info?
00174     if (! CBZ::ArchInfo.is_valid()) {
00175       printf( "ERROR: Can't generate LIR - missing architecture specification file.  specify with '-arch' option\n" );
00176       return;
00177     }
00178 
00179     // dismantle everything
00180     for ( unit_list_p u = CBZ::Program.begin();
00181           u != CBZ::Program.end();
00182           u++ )
00183       Dismantle::dismantle(*u);
00184 
00185     // walk the tree generating LIR instructions
00186     lir_gen_walker lgw;
00187     unit_list_p u;
00188     for (u=CBZ::Program.begin(); u!=CBZ::Program.end(); u++){
00189       (*u) -> walk(lgw);
00190     }
00191 
00192     // if we have no register allocator, go do simple
00193     // register allocation so that generated assembler is
00194     // compilable.
00195     if (CBZ::NoRegAlloc) {
00196       dummy_reg_alloc_walker drw;
00197       unit_list_p u;
00198       for (u=CBZ::Program.begin(); u!=CBZ::Program.end(); u++){
00199         (*u) -> walk(drw);
00200       }
00201     }
00202   }
00203 };
00204 
00205 Phases lir_gen_walker_phase ("lir", new lirGenWalkerPhase());
00206 
00207 // phase to do various flow analysis of LIR code
00208 class lirFlowWalkerPhase: public Phase {
00209         public: 
00210         void run() {
00211 
00212                 // walk the tree generating LIR instructions
00213                 lir_flow_walker lfw;
00214                 unit_list_p u;
00215                 for (u=CBZ::Program.begin(); u!=CBZ::Program.end(); u++){
00216                         (*u) -> walk(lfw);
00217                 }
00218         }
00219 };
00220 
00221 Phases lir_flow_walker_phase ("lir_flow_walker", new lirFlowWalkerPhase());
00222 
00223 // phase to do register allocation on LIR code for a translation unit
00224 class regAllocPhase: public Phase {
00225         public: 
00226         void run() {
00227 
00228                 // do we have architecture info?
00229                 if (! CBZ::ArchInfo.is_valid()) {
00230                         printf( "ERROR: Can't run register allocator - missing architecture specification file.  specify with '-arch' option\n" );
00231                         return;
00232                 }
00233 
00234                 // run register allocator for each translation unit
00235                 RegAllocWalker ra;
00236                 unit_list_p u;
00237                 for (u=CBZ::Program.begin(); u!=CBZ::Program.end(); u++){
00238                         (*u) -> walk(ra);
00239                 }
00240         }
00241 };
00242 
00243 Phases reg_alloc_phase("reg_alloc", new regAllocPhase());
00244 
00245 // phase to generate assembler source for a translation unit
00246 class asmGenWalkerPhase: public Phase {
00247         public: 
00248         void run() {
00249 
00250                 // do we have architecture info?
00251                 if (! CBZ::ArchInfo.is_valid()) {
00252                         printf( "ERROR: Can't run asm generator - missing architecture specification file.  specify with '-arch' option\n" );
00253                         return;
00254                 }
00255 
00256                 // run asm generator for each translation unit
00257                 asm_gen_walker asm_gen;
00258                 unit_list_p u;
00259                 for (u=CBZ::Program.begin(); u!=CBZ::Program.end(); u++){
00260                         (*u) -> walk(asm_gen);
00261                 }
00262         }
00263 };
00264 
00265 Phases asm_gen_phase("asm", new asmGenWalkerPhase());
00266 
00270 class DeadPhase : public Phase {
00271 public:
00272   void run (void) {
00273     for (unit_list_p u = CBZ::Program.begin() ; u != CBZ::Program.end() ; u++)
00274       {
00275         cfg_changer::generate_cfg(*u);
00276 
00277         deadCodeEliminationChanger dcec;
00278         (*u)->change(dcec);
00279       }
00280   }
00281 };
00282 
00283 Phases deadPhase("dead", new DeadPhase());
00284 
00288 class ListPhase : public Phase {
00289 public:
00290   void run (void) {
00291     phase_vec * pv = Phases::phases();
00292     for (phase_vec_p p = pv->begin() ; p != pv->end() ; p++) {
00293       Phase_entry * pe = (Phase_entry *) (*p);
00294       pe->print();
00295     }
00296   }
00297 };
00298 
00299 Phases listPhase("listphases", new ListPhase(), 
00300                  "This phase lists currently registered phases.");
00301 
00305 class TreeCheckerPhase : public Phase {
00306 private:
00307   bool _verbose;
00308   bool _warning;
00309 public:
00310   void run (void) {
00311     // an iterator through a list of translation units
00312     for (unit_list_p u = CBZ::Program.begin() ; u != CBZ::Program.end() ; u++) 
00313       {
00314         // an instance of tree checker walker
00315         TreeChecker tcw(_verbose, _warning);
00316         (*u)->walk(tcw);  // walk the AST using the Tree Checker walker
00317       }
00318   }
00319 
00320   void get_flags(str_list_p & arg) {
00321     string opt = *arg;
00322     if(strncmp("verbose:", opt.c_str(), 8) == 0) {
00323       _verbose = true;
00324       opt.erase(0,8);
00325       arg++;
00326     }
00327     else if(strncmp("warning:", opt.c_str(), 8) == 0) {
00328       _warning = true;
00329       opt.erase(0,8);
00330       arg++;
00331     }
00332   };
00333 
00334   void usage () {
00335     cout << "  It can be used to verify the AST both before and after running "
00336          <<   "the dismantler." << endl
00337          << "  If this phase is run after the code has been dismantled, "
00338          <<   "then it will" << endl
00339          << "  additionally check that only valid nodes appear in the AST." 
00340          << endl
00341          << "  usage: cbz -check-ast [verbose: | warning:] files..." << endl
00342          << "    verbose:   Output all messages about what this phase is doing"
00343          << endl
00344          << "    warning:   Output warning and informative messages" << endl;
00345   }
00346 };
00347 
00348 Phases treeCheckerPhase("check-ast", new TreeCheckerPhase(), 
00349                          "This phase checks that the AST is indeed a tree.");
00350 
00351 Phases fiPhase("fi", new fi());
00352 
00353 // ------------------------------------------------------------
00354 // Main program
00355 // ------------------------------------------------------------
00356 
00357 // --- Read in the command line
00358 
00359 str_list * process_flags(int argc, char *argv[])
00360 {
00361   str_list * args = new str_list();
00362   str_list * pre = new str_list();
00363   str_list_p p, pn;
00364 
00365   for (int i = 1; i < argc; ++i) {
00366     char s[1000];
00367     int k=0, j=0;
00368     // change all double quotes to backslash-double quotes, so
00369     // the shell will see them as literal quotes
00370     for(;argv[i][j]; j++) {
00371         if (argv[i][j] == '"')
00372                 s[k++] = '\\';
00373         s[k++] = argv[i][j];
00374     }
00375     s[k] = 0;
00376     args->push_back(string(s));
00377   }
00378 
00379   p = args->begin();
00380 
00381   while (p != args->end()) {
00382 
00383     // After "--" the rest of the args are passed to the
00384     // preprocessor
00385 
00386     if (*p == "--") {
00387       ++p;
00388       pre->splice(pre->begin(), * args, p, args->end());
00389       break;
00390     }
00391 
00392     // -- Test for phases...
00393 
00394     if (Phases::phase_flag(p)) {
00395       // Nothing extra to do
00396     }
00397     else if (*p == "-ansi") {
00398       CBZ::ANSIOnly = true;
00399       ++p;
00400     }
00401     else if (*p == "-format") {
00402       CBZ::FormatReadably = true;
00403       ++p;
00404     }
00405     else if (*p == "-no-pre") {
00406       CBZ::Preprocess = false;
00407       ++p;
00408     }
00409     else if (*p == "-pre") {
00410       CBZ::ShowPreprocess = true;
00411       ++p;
00412     }
00413     else if (*p == "-gcc") {
00414       CBZ::GCCisms = true;
00415       ++p;
00416     }
00417     else if (*p == "-P") {
00418       ++p;
00419       CBZ::preproc = *p;
00420       ++p;
00421     }
00422     else if (*p == "-suff") {
00423       ++p;
00424       CBZ::output_suffix = *p;
00425       ++p;
00426     }
00427     else if (*p == "-W") {
00428       ++p;
00429       CBZ::WarningLevel = atoi((*p).c_str());
00430       if (CBZ::WarningLevel < 0 || CBZ::WarningLevel > 5) {
00431         cerr << "Error: Warning level must be between 0 and 5." << endl;
00432         CBZ::WarningLevel = 4;
00433       } else
00434         ++p;
00435     }
00436     else if (*p == "-Wall") {
00437       CBZ::WarningLevel = 5;
00438       ++p;
00439     }
00440     else if (*p == "-arch") {
00441       ++p;
00442       string spec_file = *p;
00443       ++p;
00444 
00445       // try to read this thing
00446       if (! CBZ::ArchInfo.load_arch_info(spec_file.c_str())) {
00447         cerr << "Error: Can't read architecture specification file '" 
00448              << spec_file << "'." << endl;
00449         return NULL;
00450       }
00451     }
00452     else if (*p == "-noreg") {
00453       CBZ::NoRegAlloc = true;
00454       ++p;
00455     }
00456     else {
00457       // -- Add a source code file to process...
00458       string output_file;
00459 
00460       if (*p == "(stdin)")
00461         output_file = string("(stdout)");
00462       else {
00463         output_file = (*p);
00464         int suff_pos = output_file.rfind(CBZ::input_suffix);
00465         if (suff_pos >= 0 && suff_pos < (int)(*p).length())
00466           output_file.replace(suff_pos,
00467                               CBZ::input_suffix.length(),
00468                               CBZ::output_suffix);
00469         else
00470           output_file = string("(stdout)");
00471       }
00472 
00473       CBZ::Program.push_back(new unitNode(*p, output_file));
00474       ++p;
00475     }
00476   } // END while more flags
00477 
00478   // -- Deal with any inspecified flags...
00479 
00480   if (CBZ::preproc.empty()) {
00481     if (CBZ::ANSIOnly)
00482       CBZ::preproc = CBZ::ansi_preproc;
00483     else if (CBZ::GCCisms)
00484       CBZ::preproc = CBZ::gcc_preproc;
00485     else
00486       CBZ::preproc = CBZ::default_preproc;
00487   }
00488 
00489   //delete args;
00490 
00491   return pre;
00492 }
00493 
00494 /* ---
00495 FILE * open_input(str_list * cpp_flags)
00496 {
00497   FILE * in_file;
00498   bool std_in;
00499 
00500   std_in = (input_file == "(stdin)");
00501   if (! std_in &&
00502       (access(input_file.c_str(), F_OK) != 0) &&
00503       (access(input_file.c_str(), R_OK) != 0)) {
00504     cerr << "Unable to open input file " << input_file << endl;
00505     exit(1);
00506   }
00507 
00508   if (CBZ::Preprocess && ! std_in) {
00509     string command = CBZ::preproc;
00510     for (str_list_p p = cpp_flags->begin();
00511          p != cpp_flags->end();
00512          ++p)
00513       command += " " + (*p);
00514     command += " " + input_file;
00515 
00516     delete cpp_flags;
00517 
00518     if (CBZ::ShowPreprocess)
00519       cout << "Preprocess: " << command << endl;
00520 
00521     in_file = popen(command.c_str(), "r");
00522 
00523     if (! in_file) {
00524       cerr << "Unable to preprocess input file " << input_file << endl;
00525       cerr << "Command: " << command << endl;
00526       exit(1);
00527     }
00528   }
00529   else {
00530     if (! std_in) {
00531       in_file = fopen(input_file.c_str(), "r");
00532 
00533       if (! in_file) {
00534         cerr << "Unable to open input file " << input_file << endl;
00535         exit(1);
00536       }
00537     }
00538     else
00539       in_file = stdin;
00540   }
00541 
00542   return in_file;
00543 }
00544 -- */
00545 
00546 int main(int argc, char * argv[])
00547 {
00548   // -- Initialize operators
00549 
00550   Operators::init();
00551 
00552   // -- Process the command line arguments
00553 
00554   CBZ::cpp_flags = process_flags(argc, argv);
00555   if ( ! CBZ::cpp_flags )
00556           return 1;
00557 
00558   // -- Parse the files
00559 
00560   for (unit_list_p p = CBZ::Program.begin();
00561        p != CBZ::Program.end();
00562        ++p)
00563     (*p)->parse(CBZ::cpp_flags);
00564 
00565   // -- Run the various phases
00566 
00567   Phases::run_all();
00568 
00569   // -- Debug some stuff
00570 
00571   // cout << "After parsing -------------------- " << endl;
00572   // Node::report();
00573 
00574   // delete CBZ::Program;
00575 
00576   // cout << "After deleting ------------------- " << endl;
00577   // Node::report();
00578 }
00579 

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