bitcc.cxx

Go to the documentation of this file.
00001 /**************************************************************************
00002  *
00003  * Copyright (C) 2008, Johns Hopkins University.
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or
00007  * without modification, are permitted provided that the following
00008  * conditions are met:
00009  *
00010  *   - Redistributions of source code must contain the above
00011  *     copyright notice, this list of conditions, and the following
00012  *     disclaimer.
00013  *
00014  *   - Redistributions in binary form must reproduce the above
00015  *     copyright notice, this list of conditions, and the following
00016  *     disclaimer in the documentation and/or other materials
00017  *     provided with the distribution.
00018  *
00019  *   - Neither the names of the copyright holders nor the names of any
00020  *     of any contributors may be used to endorse or promote products
00021  *     derived from this software without specific prior written
00022  *     permission.
00023  *
00024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00025  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00026  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00027  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00028  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00029  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00030  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00031  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00032  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00033  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00034  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  **************************************************************************/
00037 
00079 
00080 #include <stdint.h>
00081 #include <stdlib.h>
00082 #include <dirent.h>
00083 #include <errno.h>
00084 
00085 #include <unistd.h>
00086 #include <sys/types.h>
00087 #include <sys/stat.h>
00088 #include <sys/time.h>
00089 #include <sys/resource.h>
00090 #include <fcntl.h>
00091 #include <signal.h>
00092 
00093 
00094 #include <fstream>
00095 #include <iostream>
00096 #include <iomanip>
00097 
00098 #include <getopt.h>
00099 #include <langinfo.h>
00100 
00101 #include <boost/filesystem/operations.hpp>
00102 #include <boost/filesystem/convenience.hpp>
00103 #include "BoostCompat.hxx"
00104 #include <libsherpa/util.hxx>
00105 
00106 #include "Version.hxx"
00107 #include "UocInfo.hxx"
00108 #include "Options.hxx"
00109 #include "AST.hxx"
00110 #include "backend.hxx"
00111 #include "Instantiate.hxx"
00112 #include "TvPrinter.hxx"
00113 #include "MixFix.hxx"
00114 
00115 using namespace std;
00116 using namespace boost;
00117 using namespace sherpa;
00118 
00119 #define BITC_COMPILER_MODE        0x1u
00120 #define BITC_INTERPRETER_MODE     0x2u
00121 #define BITC_CURRENT_MODE BITC_COMPILER_MODE
00122 
00123 #define LOPT_SHOWLEX      257   /* Show tokens */
00124 #define LOPT_SHOWPARSE    258   /* Show parse */
00125 #define LOPT_DUMPAFTER    259   /* PP after this pass */
00126 #define LOPT_SHOWPASSNMS  260   /* Show all pass names */
00127 #define LOPT_NOSTDINC     261   /* Do not append std search paths */
00128 #define LOPT_NOSTDLIB     262   /* Do not append std lib paths */
00129 #define LOPT_RAW_TVARS    263   /* Show tvars as is */
00130 #define LOPT_FQ_TYPES     264   /* Show fully quantified types */
00131 #define LOPT_SA_TCC       265   /* Show all Type class constraints */
00132 #define LOPT_SHOWPASSES   266   /* Show passes as they are run */
00133 #define LOPT_PPFQNS       267   /* Show FQNs when pretty printing */
00134 #define LOPT_DUMPTYPES    268   /* Show types after this pass */
00135 #define LOPT_STOPAFTER    269   /* Stop after this pass */
00136 #define LOPT_PPDECORATE   270   /* Decorate pretty printing with types */
00137 #define LOPT_SHOW_TYPES   271   /* Dump types a particular uoc only */
00138 #define LOPT_XML_TYPES    272   /* Dump XML types */
00139 #define LOPT_NOGC         273   /* NO GC mode */
00140 #define LOPT_NOPRELUDE    274   /* Don't process prelude */
00141 #define LOPT_HEURISTIC    275   /* Use Heuristic Inference */
00142 #define LOPT_HELP         276   /* Display usage information. */
00143 #define LOPT_EMIT         277   /* Specify the desired output language. */
00144 #define LOPT_SYSTEM       278   /* Specify the desired output
00145                                    language. */
00146 #define LOPT_NOALLOC      279   /* Statically reject heap-allocating
00147                                    operations and constructs */
00148 #define LOPT_MIXDEBUG     280   /* Debug level for the mixfix parser */
00149 #define LOPT_USAGE        281   /* Show resource usage. */
00150 
00151 struct option longopts[] = {
00152   /*  name,           has-arg, flag, val           */
00153   // Decorate pretty printing with types */
00154   { "decorate",             0,  0, LOPT_PPDECORATE },
00155   // Dump the AST after the named pass
00156   { "dumpafter",            1,  0, LOPT_DUMPAFTER },
00157   // Dump symbol types after the named pass
00158   { "dumptypes",            1,  0, LOPT_DUMPTYPES },
00159   // Specify the desired output language.
00160   { "emit",                 1,  0, LOPT_EMIT },
00161   // Show fully quantified types in output
00162   { "full-qual-types",      0,  0, LOPT_FQ_TYPES },
00163   // Print command line help and exit
00164   { "help",                 0,  0, LOPT_HELP },
00165   // Use heuristic inference instead of complete inference
00166   { "heuristic-inf",        0,  0, LOPT_HEURISTIC },
00167   // Set the debug level for the mixfix parser:
00168   { "mixfix-debug",         1,  0, LOPT_MIXDEBUG },
00169   // Disallow any construct that would cause heap allocation at runtime.
00170   { "no-alloc",             0,  0, LOPT_NOALLOC },
00171   // Do not link the garbage collector.
00172   { "no-gc",                0,  0, LOPT_NOGC },
00173   // Do not load the standard BitC prelude.
00174   { "no-prelude",           0,  0, LOPT_NOPRELUDE },
00175   // Do not add standard include locations to the include search path.
00176   { "nostdinc",             0,  0, LOPT_NOSTDINC },
00177   // Do not add standard library locations to the library/module search path.
00178   { "nostdlib",             0,  0, LOPT_NOSTDLIB },
00179   // Show FQNs when pretty printing
00180   { "ppfqns",               0,  0, LOPT_PPFQNS },
00181   // Show tvars without pretty-printing: useful for Debugging
00182   { "raw-tvars",            0,  0, LOPT_RAW_TVARS },
00183   // Show all Type class constraints, including subsumed ones
00184   { "show-all-tccs",        0,  0, LOPT_SA_TCC },
00185   { "show-resources",       0,  0, LOPT_USAGE },
00186   // Print tokens as they are accepted. Primarily useful for debugging
00187   // parse errors.
00188   { "showlex",              0,  0, LOPT_SHOWLEX },
00189   // Print parse reductions as they occur.
00190   { "showparse",            0,  0, LOPT_SHOWPARSE },
00191   // Print the names of all passes as they are executed
00192   { "showpasses",           0,  0, LOPT_SHOWPASSES },
00193   // Print the names of all passes
00194   { "showpassnames",        0,  0, LOPT_SHOWPASSNMS },
00195   // Show types as they appear after the named path
00196   { "showtypes",            1,  0, LOPT_SHOW_TYPES },
00197   // Stop processing after the named pass
00198   { "stopafter",            1,  0, LOPT_STOPAFTER },
00199   // Change the standard search prefix directory, similar to gcc --system
00200   { "system",               1,  0, LOPT_SYSTEM },
00201   { "times",                0,  0, LOPT_USAGE }, // convenience alias
00202   // Run verbosely. Not clear that this is actually being used anyware.
00203   { "verbose",              0,  0, 'v' },
00204   // Print compiler version and exit
00205   { "version",              0,  0, 'V' },
00206   // Dump symbol types in XML form after the named pass. This should
00207   // probably be obsoleted.
00208   { "xmltypes",             1,  0, LOPT_XML_TYPES },
00209 #if 0
00210   /* Options that have short-form equivalents: */
00211   { "debug",                0,  0, 'd' },
00212 
00213   { "dispatchers",          0,  0, 's' },
00214   { "entry",                1,  0, 'e' },
00215   { "execdir",              1,  0, 'X' },
00216   { "header",               1,  0, 'h' },
00217   { "include",              1,  0, 'I' },
00218   { "index"  ,              1,  0, 'n' },
00219   { "outdir",               1,  0, 'D' },
00220   { "output",               1,  0, 'o' },
00221   { "verbose",              0,  0, 'v' },
00222 #endif
00223   {0,                       0,  0, 0}
00224 };
00225 
00227 void
00228 help()
00229 {
00230   std::cerr
00231     << "Common Usage:" << endl
00232     //    << "  bitcc [-I include] -c file1.bits ...\n"
00233     << "  bitcc [-I include] [-o outfile.bito] -c file.bits\n"
00234     // << "  bitcc [-I include] -h file.bitc ...\n"
00235     << "  bitcc [-I include] [-o outfile.h] -h file.bits\n"
00236     << "  bitcc [file1.bito|library.a] ... [-o exefile]\n"
00237     << "  bitcc -V|--version\n"
00238     << "  bitcc --help\n"
00239     << "\n"
00240     << "Debugging options:\n"
00241     << "  --showlex --showparse --showpasses\n"
00242     << "  --stopafter 'pass'\n"
00243     << "  --decorate --dumpafter 'pass' --dumptypes 'pass'\n"
00244     << "  --showtypes 'uoc' \n"
00245     << "  --emit 'Language'\n" 
00246     //<< "  --xmltypes 'uoc' \n"
00247     << "  --ppfqns --full-qual-types\n"
00248     << "  --raw-tvars --show-maybes --show-all-tccs \n"
00249     << "\n"
00250     << "Languages: xmlpp, xmldump, xmltypes, bitcpp, showtypes, bito,\n"
00251     << "           c, h, obj\n"
00252     << flush;
00253 }
00254 
00256 void
00257 fatal()
00258 {
00259   cerr << "Confused due to previous errors, bailing."
00260        << endl;
00261   exit(1);
00262 }
00263 
00264 
00270 static bool SawFirstBitcInput = false;
00271 
00274 void
00275 AddLinkArgumentForGCC(const std::string& s)
00276 {
00277   if (SawFirstBitcInput)
00278     Options::LinkPostOptionsGCC.push_back(s);
00279   else {
00280     Options::LinkPreOptionsGCC.push_back(s);
00281   }
00282 }
00283 
00286 void
00287 AddCompileArgumentForGCC(const std::string& s)
00288 {
00289   if (SawFirstBitcInput) {
00290     cerr << "Compiler options must appear before the first BitC input file."
00291          << endl;
00292     exit(1);
00293   }
00294 
00295   Options::CompilePreOptionsGCC.push_back(s);
00296 }
00297 
00299 BackEnd *
00300 FindBackEnd(const char *nm)
00301 {
00302   for (size_t i = 0; i < BackEnd::nBackEnd; i++) {
00303     if (BackEnd::backends[i].name == nm)
00304       return &BackEnd::backends[i]; //&OK
00305   }
00306 
00307   return NULL;
00308 }
00309 
00315 void
00316 handle_sigsegv(int param)
00317 {
00318   cerr << "Internal Compiler error: SIGSEGV. "
00319        << "Please report this problem along with sample source."
00320        << endl;
00321   exit(1);
00322 }
00323 
00340 filesystem::path
00341 ResolveLibPath(std::string name)
00342 {
00343   string fullNm = "lib" + name + ".bita";
00344 
00345   for (size_t i = 0; i < Options::libDirs.size(); i++) {
00346     filesystem::path testPath = Options::libDirs[i] / fullNm;
00347     if (filesystem::exists(testPath)) {
00348       if (!filesystem::is_regular_file(testPath)) {
00349         std::cerr << "bitcc: error: \"-l" << name
00350                   << "\" resolves to \""
00351                   << testPath.string()
00352                   << "\", which is not a regular file."
00353                   << endl;
00354         exit(1);
00355       }
00356 
00357       return testPath;
00358     }
00359   }
00360 
00361   return filesystem::path();
00362 }
00363 
00364 int
00365 main(int argc, char *argv[])
00366 {
00367   int c;
00368   //  extern int optind;
00369   int opterr = 0;
00370 
00371   signal(SIGSEGV, handle_sigsegv);
00372 
00395 
00396   while ((c = getopt_long(argc, argv,
00397                           "-e:o:O::l:VvcghI:L:",
00398                           longopts, 0
00399                      )) != -1) {
00400     switch(c) {
00401     case 1:
00402       {
00403         std::string sfx = filesystem::extension(optarg);
00404 
00405         if (
00406             // Interface files. Probably should not appear on the
00407             // command line, but this may be a case of obsolete
00408             // usage. Allow it for now.
00409             (sfx == ".bitc")
00410             // BitC source file.
00411             || (sfx == ".bits")
00412             // BitC "object" file.
00413             || (sfx == ".bito")
00414             // BitC archive file.
00415             || (sfx == ".bita")) {
00416 
00417           SawFirstBitcInput = true;
00418           Options::inputs.push_back(optarg);
00419         }
00420         else
00421           // Else it is something to be passed through to GCC:
00422           AddLinkArgumentForGCC(optarg);
00423 
00424         break;
00425       }
00426 
00427     case 'V':
00428       cerr << "Bitc Version: " << BITC_VERSION << endl;
00429       exit(0);
00430       break;
00431 
00432     case LOPT_NOSTDINC:
00433       Options::useStdInc = false;
00434       AddCompileArgumentForGCC("--nostdinc");
00435       AddLinkArgumentForGCC("--nostdinc");
00436       break;
00437 
00438     case LOPT_NOSTDLIB:
00439       Options::useStdLib = false;
00440       AddLinkArgumentForGCC("--nostdlib");
00441       break;
00442 
00443     case LOPT_SHOWPARSE:
00444       Options::showParse = true;
00445       break;
00446 
00447     case LOPT_SHOWLEX:
00448       Options::showLex = true;
00449       break;
00450 
00451     case LOPT_SHOWPASSES:
00452       Options::showPasses = true;
00453       break;
00454 
00455     case LOPT_PPFQNS:
00456       Options::ppFQNS = true;
00457       break;
00458 
00459     case LOPT_PPDECORATE:
00460       Options::ppDecorate = true;
00461       break;
00462 
00463     case LOPT_NOGC:
00464       Options::noGC = true;
00465       break;
00466 
00467     case LOPT_NOALLOC:
00468       Options::noAlloc = true;
00469       break;
00470 
00471     case LOPT_NOPRELUDE:
00472       Options::noPrelude = true;
00473       break;
00474 
00475     case LOPT_HEURISTIC:
00476       Options::heuristicInference=true;
00477       break;
00478 
00479     case LOPT_SHOWPASSNMS:
00480       {
00481         std::cerr.width(15);
00482         std::cerr << left
00483                   << "PASS"
00484                   << "PURPOSE" << std::endl << std::endl;
00485 
00486         for (size_t i = (size_t)pn_none+1; i < (size_t) pn_npass; i++) {
00487           std::cerr.width(15);
00488           std::cerr << left
00489                     << UocInfo::passInfo[i].name
00490                     << UocInfo::passInfo[i].descrip << std::endl;
00491         }
00492 
00493         std::cerr << left
00494                   << "Polyinst"
00495                   << "Template-like instantiation of polymorphic definitions" << std::endl;
00496 
00497         for (size_t i = (size_t)op_none+1; i < (size_t) op_npass; i++) {
00498           std::cerr.width(15);
00499           std::cerr << left
00500                     << UocInfo::onePassInfo[i].name
00501                     << UocInfo::onePassInfo[i].descrip << std::endl;
00502         }
00503 
00504         exit(0);
00505       }
00506 
00507     case LOPT_DUMPAFTER:
00508       {
00509         for (size_t i = (size_t)pn_none+1; i < (size_t) pn_npass; i++) {
00510           if (strcmp(UocInfo::passInfo[i].name, optarg) == 0 ||
00511               strcmp("ALL", optarg) == 0)
00512             UocInfo::passInfo[i].printAfter = true;
00513         }
00514 
00515         for (size_t i = (size_t)op_none+1; i < (size_t) op_npass; i++) {
00516           if (strcmp(UocInfo::onePassInfo[i].name, optarg) == 0 ||
00517               strcmp("ALL", optarg) == 0)
00518             UocInfo::onePassInfo[i].printAfter = true;
00519         }
00520         
00521         if (strcmp("midend", optarg) == 0 ||
00522             strcmp("ALL", optarg) == 0)
00523           Options::dumpAfterMidEnd = true;
00524 
00525         break;
00526       }
00527 
00528     case LOPT_DUMPTYPES:
00529       {
00530         for (size_t i = (size_t)pn_none+1; i < (size_t) pn_npass; i++) {
00531           if (strcmp(UocInfo::passInfo[i].name, optarg) == 0 ||
00532               strcmp("ALL", optarg) == 0)
00533             UocInfo::passInfo[i].typesAfter = true;
00534         }
00535 
00536         for (size_t i = (size_t)op_none+1; i < (size_t) op_npass; i++) {
00537           if (strcmp(UocInfo::onePassInfo[i].name, optarg) == 0 ||
00538               strcmp("ALL", optarg) == 0)
00539             UocInfo::onePassInfo[i].typesAfter = true;
00540         }
00541         
00542         if (strcmp("midend", optarg) == 0 ||
00543             strcmp("ALL", optarg) == 0)
00544           Options::dumpTypesAfterMidEnd = true;
00545 
00546         break;
00547       }
00548 
00549     case LOPT_STOPAFTER:
00550       {
00551         for (size_t i = (size_t)pn_none+1; i < (size_t) pn_npass; i++) {
00552           if (strcmp(UocInfo::passInfo[i].name, optarg) == 0 ||
00553               strcmp("ALL", optarg) == 0)
00554             UocInfo::passInfo[i].stopAfter = true;
00555         }
00556 
00557         for (size_t i = (size_t)op_none+1; i < (size_t) op_npass; i++) {
00558           if (strcmp(UocInfo::onePassInfo[i].name, optarg) == 0 ||
00559               strcmp("ALL", optarg) == 0)
00560             UocInfo::onePassInfo[i].stopAfter = true;
00561         }
00562 
00563         break;
00564       }
00565 
00566     case LOPT_RAW_TVARS:
00567       {
00568         Options::rawTvars = true;
00569         break;
00570       }
00571 
00572     case LOPT_FQ_TYPES:
00573       {
00574         Options::FQtypes = true;
00575         break;
00576       }
00577 
00578     case LOPT_SA_TCC:
00579       {
00580         Options::showAllTccs = true;
00581         break;
00582       }
00583 
00584     case LOPT_SHOW_TYPES:
00585       {
00586         Options::showTypesUocs.insert(optarg);
00587         break;
00588       }
00589 
00590     case LOPT_XML_TYPES:
00591       {
00592         Options::xmlTypesUocs.insert(optarg);
00593         break;
00594       }
00595 
00596     case 'v':
00597       Options::verbose++;
00598       if (Options::verbose > 1) {
00599         AddCompileArgumentForGCC("-v");
00600         AddLinkArgumentForGCC("-v");
00601       }
00602       break;
00603 
00604     case 'c':
00605       {
00606         if (Options::backEnd) {
00607           std::cerr << "Can only specify one output language.\n";
00608           exit(1);
00609         }
00610 
00611         // Issue: if we are passed a .c file, shouldn't we pass that
00612         // along to GCC in this case? Problem: what if there aren't
00613         // any inputs exclusively for GCC?
00614         //
00615         // AddArgumentForGCC("-c");
00616 
00617         Options::backEnd = FindBackEnd("bito");
00618         break;
00619       }
00620 
00621     case 'h':
00622       {
00623         if (Options::backEnd) {
00624           std::cerr << "Can only specify one output language.\n";
00625           exit(1);
00626         }
00627 
00628         Options::backEnd = FindBackEnd("h");
00629         break;
00630       }
00631 
00632     case LOPT_EMIT:
00633       {
00634         if (Options::backEnd) {
00635           std::cerr << "Can only specify one output language.\n";
00636           exit(1);
00637         }
00638 
00639         Options::backEnd = FindBackEnd(optarg);
00640         if (!Options::backEnd) {
00641           std::cerr << "Unknown target language.\n";
00642           exit(1);
00643         }
00644 
00645         break;
00646       }
00647 
00648     case LOPT_MIXDEBUG:
00649       {
00650         if (Options::mixfixDebug > 0) {
00651           // already set
00652           std::cerr << "Warning: overriding previous setting of mixfix-debug.\n";
00653         }
00654 
00655         // Validation:
00656         for (const char *arg = optarg; *arg; arg++) {
00657           if(!isdigit(*arg)) {
00658             std::cerr << "Argument to --mixfix-debug must be a number.\n";
00659             exit(1);
00660           }
00661         }
00662 
00663         Options::mixfixDebug = strtoul(optarg, 0, 0);
00664 
00665         break;
00666       }
00667 
00668     case 'e':
00669       {        
00670         Options::entryPts.insert(FQName(optarg));
00671         break;
00672       }
00673 
00674     case LOPT_HELP:
00675       {
00676         help();
00677         exit(0);
00678       }
00679 
00680     case 'o':
00681       Options::outputFileName = optarg;
00682 
00683       AddLinkArgumentForGCC("-o");
00684       AddLinkArgumentForGCC(optarg);
00685 
00686       break;
00687 
00688     case 'I':
00689       AddCompileArgumentForGCC("-I");
00690       AddCompileArgumentForGCC(optarg);
00691       AddLinkArgumentForGCC("-I");
00692       AddLinkArgumentForGCC(optarg);
00693       UocInfo::searchPath.push_back(optarg);
00694       break;
00695 
00696     case LOPT_SYSTEM:
00697       Options::SystemDirs.push_back(optarg);
00698       break;
00699 
00700     case LOPT_USAGE:
00701       Options::show_usage = true;
00702       break;
00703 
00704     case 'l':
00705       {
00706         AddLinkArgumentForGCC("-l");
00707         AddLinkArgumentForGCC(optarg);
00708 
00709         filesystem::path path = ResolveLibPath(optarg);
00710         if (!path.empty())
00711           Options::inputs.push_back(path.string());
00712         break;
00713       }
00714 
00715     case 'L':
00716       AddLinkArgumentForGCC("-L");
00717       AddLinkArgumentForGCC(optarg);
00718 
00719       Options::libDirs.push_back(optarg);
00720       break;
00721 
00722     case 'g':
00723       {
00724         AddCompileArgumentForGCC("-g");
00725         AddLinkArgumentForGCC("-g");
00726         break;
00727       }
00728 
00729     case 'O':                        // a.k.a. -O2
00730       {
00731         std::string optlevel = "-O";
00732         if (optarg)
00733           optlevel += optarg;
00734 
00735         AddCompileArgumentForGCC(optlevel);
00736         AddLinkArgumentForGCC(optlevel);
00737       }
00738 
00739       break;
00740 
00741     default:
00742       opterr++;
00743       break;
00744     }
00745   }
00746 
00747   mixfix_init();
00748 
00749   // Select default backend if none chosen otherwise.
00750   if (Options::backEnd == 0)
00751     Options::backEnd = &BackEnd::backends[0];
00752 
00753   for (size_t i = 0; i < Options::SystemDirs.size(); i++) {
00754     filesystem::path incPath = Options::SystemDirs[i] / "include";
00755 
00756     UocInfo::searchPath.push_back(incPath);
00757     Options::CompilePreOptionsGCC.push_back("-I");
00758     Options::CompilePreOptionsGCC.push_back(incPath.string());
00759 
00761     std::string lib_leaf_name = filesystem::path(AUTOCONF_LIBDIR).leaf();
00762     filesystem::path libPath = Options::SystemDirs[i] / lib_leaf_name;
00763 
00764     Options::libDirs.push_back(libPath);
00765     Options::LinkPostOptionsGCC.push_back("-L");
00766     Options::LinkPostOptionsGCC.push_back(libPath.string());
00767   }
00768 
00769   // Since BitC may hot have been compiled for install into a standard
00770   // location, add AUTOCONF_LIBDIR to libDirs and also to the link
00771   // options:
00772 
00773   if (Options::useStdLib) {
00774     Options::libDirs.push_back(filesystem::path(AUTOCONF_LIBDIR));
00775     Options::LinkPostOptionsGCC.push_back("-L");
00776     Options::LinkPostOptionsGCC.push_back(AUTOCONF_LIBDIR);
00777   }
00778 
00779   if (Options::useStdLib) {
00780     filesystem::path path = ResolveLibPath("bitc");
00781     if (path.empty() && (Options::backEnd->flags & BK_LINKING)) {
00782       cerr << "Cannot find bitc standard library, which is needed"
00783            << endl;
00784       exit(1);
00785     }
00786     if (!path.empty())
00787       Options::inputs.push_back(path.string());
00788   }
00789 
00790   /* From this point on, argc and argv should no longer be consulted. */
00791 
00792   if (Options::inputs.empty())
00793     opterr++;
00794 
00795   if (opterr) {
00796     std::cerr << "Usage: Try bitcc --help" << std::endl;
00797     exit(0);
00798   }
00799 
00800   if (Options::outputFileName.size() == 0)
00801     Options::outputFileName = "bitc.out";
00802 
00803   /************************************************************/
00804   /*                UOC Parse and Validate                    */
00805   /************************************************************/
00806   // Process the Prelude:
00807 
00808   /* Per-file backend output after processing frontend, if any */
00809   bool doFinal = true;
00810 
00811   // FIX: TEMPORARY
00812   if (!Options::noPrelude) {
00813     sherpa::LexLoc loc = LexLoc();
00814     if (!UocInfo::importInterface(std::cerr, loc, "bitc.prelude"))
00815       doFinal = false;
00816   }
00817 
00818   // Compile everything
00819   for (size_t i = 0; i < Options::inputs.size(); i++)
00820     if (!UocInfo::CompileFromFile(Options::inputs[i], true))
00821       doFinal = false;
00822 
00823   /* Backend-defined processing for each interface module */
00824   for (UocMap::iterator itr = UocInfo::ifList.begin();
00825       itr != UocInfo::ifList.end(); ++itr) {
00826     shared_ptr<UocInfo> puoci = itr->second;
00827 
00828     if (puoci->lastCompletedPass >= Options::backEnd->needPass) {
00829       if (Options::backEnd->fn)
00830         Options::backEnd->fn(std::cout, std::cerr, puoci);
00831     }
00832     else
00833       doFinal = false;
00834   }
00835 
00836   /* Backend-defined processing for each source module */
00837   for (UocMap::iterator itr = UocInfo::srcList.begin();
00838       itr != UocInfo::srcList.end(); ++itr) {
00839     shared_ptr<UocInfo> puoci = itr->second;
00840 
00841     if (puoci->lastCompletedPass >= Options::backEnd->needPass){
00842       if (Options::backEnd->fn)
00843         Options::backEnd->fn(std::cout, std::cerr, puoci);
00844     }
00845     else
00846       doFinal = false;
00847   }
00848 
00849   /* We have completed all of the per-UOC passes. Assuming that we did
00850    * so successfully, run any required mid-end function:
00851    */
00852   if (doFinal) {
00853     if (Options::backEnd->midfn) {
00854       Options::backEnd->midfn(std::cout, std::cerr);
00855     }
00856   }
00857 
00858   if (!doFinal)
00859     exit(1);
00860 
00861   if (Options::backEnd->flags & BK_UOC_MODE)
00862     exit(0);
00863 
00864   /************************************************************/
00865   /*   The mid zone, build the polyinstantiate + big-ast      */
00866   /************************************************************/
00867 #if (BITC_CURRENT_MODE == BITC_COMPILER_MODE)
00868   /* Build the list of things to be instantiated */
00869 
00879   if (Options::entryPts.empty() &&
00880      ((Options::backEnd->flags & BK_HDR_MODE) == 0))
00881     Options::entryPts.insert(FQName("bitc.main","main"));
00882 
00888   UocInfo::addAllCandidateEPs();
00889 #endif
00890 
00891   // Update all of the defForm pointers so that we can find things:
00892   UocInfo::findAllDefForms();
00893 
00894   /* Create a new unit of compilation that will become the grand,
00895      unified UoC */
00896   shared_ptr<UocInfo> unifiedUOC = UocInfo::CreateUnifiedUoC();
00897 
00898   // Build the master back-end AST. This is done in a way that can be
00899   // extended incrementally.
00900   // The batch version is similar to the unbatched instantiator as
00901   // it calls the real instantiator one entry point at a time over
00902   // the list of entry points it recieves. The only difference is
00903   // that the megaENVs is not updated after each entry point if we
00904   // use batch mode. In an interpreter, if we are instantiating only
00905   // one entry point, one might as well use instantiate instead of
00906   // instantiateBatch call.
00907   bool midPassOK = unifiedUOC->instantiateBatch(std::cerr, Options::entryPts);
00908 
00909   if (Options::dumpAfterMidEnd) {
00910     std::cerr << "==== DUMPING *unified UOC*"
00911               << " AFTER mid-end"
00912               << " ====" << std::endl;
00913     unifiedUOC->PrettyPrint(std::cerr, Options::ppDecorate);
00914   }
00915   if (Options::dumpTypesAfterMidEnd) {
00916     std::cerr << "==== TYPES for *unified UOC*"
00917               << " AFTER mid-end"
00918               << " ====" << std::endl;
00919     unifiedUOC->ShowTypes(std::cerr);
00920     std::cerr <<std::endl << std::endl;
00921   }
00922 
00923   if (!midPassOK) {
00924     std::cerr << "Exiting due to errors during Instantiation."
00925               << std::endl;
00926     exit(1);
00927   }
00928 
00929   /************************************************************/
00930   /*                        The backend                       */
00931   /************************************************************/
00932 
00933   // Finally perform one-pass backend Functions.
00934   unifiedUOC->DoBackend();
00935 
00936   // If there is any post-gather output, it should be done now.
00937   if (Options::backEnd->plfn) {
00938     bool done = Options::backEnd->plfn(std::cout, std::cerr,
00939                                        unifiedUOC);
00940     if (!done)
00941       exit(1);
00942   }
00943 
00944   if (Options::show_usage) {
00945     struct rusage my_rusage;
00946     struct rusage child_rusage;
00947 
00948     getrusage(RUSAGE_CHILDREN, &child_rusage);
00949     getrusage(RUSAGE_SELF, &my_rusage);
00950 
00951     std::cout << "Time in bitcc:  " 
00952               << my_rusage.ru_utime.tv_sec
00953               << "."
00954               << std::setw(6) << std::setfill('0')
00955               << my_rusage.ru_utime.tv_usec
00956               << "u "
00957               << my_rusage.ru_stime.tv_sec
00958               << "."
00959               << std::setw(6) << std::setfill('0')
00960               << my_rusage.ru_stime.tv_usec
00961               << 's'
00962               << std::endl;
00963     std::cout << "Time in gcc/ld: " 
00964               << child_rusage.ru_utime.tv_sec
00965               << "."
00966               << std::setw(6) << std::setfill('0')
00967               << child_rusage.ru_utime.tv_usec
00968               << "u "
00969               << child_rusage.ru_stime.tv_sec
00970               << "."
00971               << std::setw(6) << std::setfill('0')
00972               << child_rusage.ru_stime.tv_usec
00973               << 's'
00974               << std::endl;
00975   }
00976 
00977   exit(0);
00978 }
00979 

Generated on Sat Feb 4 23:59:28 2012 for BitC Compiler by  doxygen 1.4.7