UocInfo.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 
00038 #include <assert.h>
00039 #include <stdint.h>
00040 #include <dirent.h>
00041 #include <string>
00042 #include <iostream>
00043 #include <sstream>
00044 
00045 #include "Options.hxx"
00046 #include "Version.hxx"
00047 #include "UocInfo.hxx"
00048 #include "Type.hxx"
00049 #include "backend.hxx"
00050 #include "inter-pass.hxx"
00051 #include "TransitionLexer.hxx"
00052 
00053 #include <boost/filesystem/operations.hpp>
00054 #include "BoostCompat.hxx"
00055 #include <libsherpa/util.hxx>
00056 
00057 
00058 using namespace std;
00059 using namespace boost;
00060 using namespace sherpa;
00061 
00062 vector<filesystem::path> UocInfo::searchPath;
00063 UocMap UocInfo::ifList;
00064 UocMap UocInfo::srcList;
00065 
00066 bool UocInfo::mainIsDefined = false;
00067 
00068 PassInfo UocInfo::passInfo[] = {
00069 #define PASS(nm, short, descrip) { short, &UocInfo::fe_##nm, descrip, false },
00070 #include "pass.def"
00071 };
00072 
00073 OnePassInfo UocInfo::onePassInfo[] = {
00074 #define ONEPASS(nm, short, descrip) { short, &UocInfo::be_##nm, descrip, false },
00075 #include "onepass.def"
00076 };
00077 
00078 
00079 std::string 
00080 UocInfo::UocNameFromSrcName(const std::string& srcFileName, unsigned ndx)
00081 {
00082   // Use the filename with the extension (if any) chopped off.
00083   size_t ifSepPos = srcFileName.rfind(FQName::sep);
00084   return srcFileName.substr(0, ifSepPos) + "#" + unsigned_str(ndx);
00085 }
00086 
00087 UocInfo::UocInfo(const std::string& _uocName, const std::string& _origin,
00088                  shared_ptr<AST> _uocAst)
00089 {
00090   lastCompletedPass = pn_none;
00091   uocAst = _uocAst;
00092   env = GC_NULL;
00093   gamma = GC_NULL;
00094 
00095   uocName = _uocName;
00096   origin = _origin;
00097   flags = UOC_NO_FLAGS;
00098 }
00099 
00100 // Why does this exist? Are we actually using it anywhere?
00101 // I'm concerned because it isn't doing deep copy, I don't understand
00102 // whether it *needs* to do deep copy (or not), and there is no
00103 // comment here answering my question.
00104 UocInfo::UocInfo(shared_ptr<UocInfo> uoc)
00105 {
00106   uocName = uoc->uocName;
00107   origin = uoc->origin;
00108   lastCompletedPass = uoc->lastCompletedPass;
00109   uocAst = uoc->uocAst;
00110   env = uoc->env;
00111   gamma = uoc->gamma;
00112   instEnv = uoc->instEnv;
00113   flags = UOC_NO_FLAGS;
00114 }
00115 
00116 shared_ptr<UocInfo>
00117 UocInfo::CreateUnifiedUoC()
00118 {
00119   LexLoc loc;
00120   shared_ptr<AST> ast = AST::make(at_module, loc);
00121 
00122   std::string uocName = "*emit*";
00123   shared_ptr<UocInfo> uoc = UocInfo::make(uocName, "*internal*", ast);
00124 
00125   uoc->env = ASTEnvironment::make(uocName);
00126   uoc->gamma = TSEnvironment::make(uocName);
00127   uoc->instEnv = InstEnvironment::make(uocName);
00128 
00129   uoc->env = uoc->env->newDefScope();
00130   uoc->gamma = uoc->gamma->newDefScope();
00131   uoc->instEnv = uoc->instEnv->newDefScope();  
00132 
00133   return uoc;
00134 }
00135 
00136 
00137 filesystem::path
00138 UocInfo::resolveInterfacePath(std::string ifName)
00139 {
00140   std::string tmp = ifName;
00141   for (size_t i = 0; i < tmp.size(); i++) {
00142     if (tmp[i] == '.')
00143       tmp[i] = '/';
00144   }
00145   
00146   // Hack: if the interface name is bitc.target.arch, then we now have
00147   // bitc/target/arch. Re-write that as 
00148   // bitc/target/arch-<thearch>, so that we have a way to get 
00149   // target-dependent information into the standard build environment.
00150   if (ifName == "bitc.target.arch")
00151     tmp = std::string("bitc/target/arch-") + TARGET_ARCH;
00152 
00153   std::string leafName = tmp + ".bitc";
00154 
00155   for (size_t i = 0; i < UocInfo::searchPath.size(); i++) {
00156     filesystem::path testPath = UocInfo::searchPath[i] / leafName;
00157     
00158     if (filesystem::exists(testPath)) {
00159       if (!filesystem::is_regular_file(testPath)) {
00160         std::cerr << "bitcc: source path \""
00161                   << testPath.string() << "\" for interface \""
00162                   << ifName << "\" is not "
00163                   << "a regular file." << std::endl;
00164         exit(1);
00165       }
00166       return testPath;
00167     }
00168   }
00169 
00170   std::cerr << "bitcc: error: no source path found for interface \""
00171             << ifName << "\"." << std::endl;
00172   exit(0);
00173 }
00174 
00175 
00176 void 
00177 UocInfo::addTopLevelForm(shared_ptr<AST> def)
00178 {
00179   assert(uocAst->astType == at_module);
00180   uocAst->children.push_back(def);  
00181 }
00182 
00183 bool
00184 UocInfo::CompileFromFile(const filesystem::path& src, bool fromCmdLine)
00185 {
00186   // Use binary mode so that newline conversion and character set
00187   // conversion is not done by the stdio library.
00188   std::ifstream fin(src.string().c_str(), std::ios_base::binary);
00189 
00190   if (!fin.is_open()) {
00191     std::cerr << "Couldn't open input file \""
00192               << src.string()
00193               << "\"" << std::endl;
00194     return false;
00195   }
00196 
00197   TransitionLexer lexer(std::cerr, fin, src.string(), fromCmdLine);
00198 
00199   // This is no longer necessary, because the parser now handles it
00200   // for all interfaces whose name starts with "bitc.xxx"
00201   //
00202   // if (this->flags & UOC_IS_PRELUDE)
00203   //   lexer.isRuntimeUoc = true;
00204 
00205   lexer.setDebug(Options::showLex);
00206 
00207   extern int transition_parse(TransitionLexer *lexer);
00208   transition_parse(&lexer);  
00209   // On exit, ast is a pointer to the AST tree root.
00210   
00211   fin.close();
00212 
00213   if (lexer.num_errors != 0u)
00214     return false;
00215 
00216   return true;
00217 }
00218 
00219 shared_ptr<UocInfo> 
00220 UocInfo::findInterface(const std::string& ifName)
00221 {
00222   UocMap::iterator itr = UocInfo::ifList.find(ifName);
00223   if (itr == UocInfo::ifList.end())
00224     return GC_NULL;
00225 
00226   return itr->second;
00227 }
00228 
00229 shared_ptr<UocInfo> 
00230 UocInfo::importInterface(std::ostream& errStream,
00231                          const LexLoc& loc, const std::string& ifName)
00232 {
00233   // First check to see if we already have it. Yes, this
00234   // IS a gratuitously stupid way to do it.
00235   shared_ptr<UocInfo> puoci = findInterface(ifName);
00236 
00237   if (puoci && puoci->uocAst)
00238     return puoci;
00239 
00240   if (puoci) {
00241     errStream
00242       << loc.asString() << ": "
00243       << "Fatal error: recursive dependency on interface "
00244       << "\"" << ifName << "\"\n"
00245       << "This needs a better diagnostic so you can decipher"
00246       << " what happened.\n";
00247     exit(1);
00248   }
00249 
00250   filesystem::path path = resolveInterfacePath(ifName);
00251   if (path.empty()) {
00252     errStream
00253       << loc.asString() << ": "
00254       << "Import failed for interface \"" << ifName << "\".\n"
00255       << "Interface unit of compilation not found on search path.\n";
00256     exit(1);
00257   }
00258 
00259   if (!CompileFromFile(path, false)) {
00260     errStream
00261       << loc.asString() << ": "
00262       << "Import failed for interface \"" << ifName << "\".\n"
00263       << "Imported interface did not compile.\n";
00264 
00265     exit(1);
00266   }
00267 
00268   // If we survived the compile, the interface is now in the ifList
00269   // and can be found.
00270   return findInterface(ifName);
00271 }
00272 
00273 bool
00274 UocInfo::fe_none(std::ostream& errStream, bool init, 
00275                  unsigned long flags)
00276 {
00277   return true;
00278 }
00279 
00280 bool
00281 UocInfo::fe_npass(std::ostream& errStream, bool init,
00282                   unsigned long flags)
00283 {
00284   return true;
00285 }
00286 
00287 
00288 bool
00289 UocInfo::be_none(std::ostream& errStream, bool init, 
00290                  unsigned long flags)
00291 {
00292   return true;
00293 }
00294 
00295 bool
00296 UocInfo::be_npass(std::ostream& errStream, bool init,
00297                   unsigned long flags)
00298 {
00299   return true;
00300 }
00301 
00302 
00303 bool
00304 UocInfo::fe_parse(std::ostream& errStream, bool init,
00305                   unsigned long flags)
00306 {
00307   // The parse pass is now vestigial. The only reason that it still
00308   // exists is to preserve the ability to get a post-parse dump of the
00309   // parse tree in various output languages.
00310 
00311   return true;
00312 }
00313 
00314 void
00315 UocInfo::Compile()
00316 {
00317   for (size_t i = pn_none+1; (Pass)i <= Options::backEnd->needPass; i++) {
00318     if (Options::showPasses)
00319       std::cerr << uocName << " PASS " << passInfo[i].name << std::endl;
00320     
00321     //std::cout << "Now performing "
00322     //              << passInfo[i].descrip
00323     //              << " on " << path->asString()
00324     //              << std::endl;
00325     
00326     bool showTypes = false;
00327     
00328     // We now find the `bare' name of a UOC. Source modules are named
00329     // as uocName#index_number. But, for showing the types for a 
00330     // UOC whose name specified as the input argument, we must compare 
00331     // only the bare UOC name.
00332     // In effect, this will display the types for all UOCs whose name
00333     // matches the command line argument.
00334     std::string bareName = uocName;
00335     std::string::size_type pos = uocName.find ('#');
00336     if (pos != std::string::npos)
00337       bareName = uocName.substr(0, pos);
00338 
00339     if (Options::showTypesUocs.find(bareName) !=
00340         Options::showTypesUocs.end())
00341       showTypes = true;
00342     
00343     if (! (this->*passInfo[i].fn)(std::cerr, true, 0) ) {
00344       std::cerr << "Exiting due to errors during "
00345                 << passInfo[i].descrip
00346                 << std::endl;
00347       exit(1);
00348     }
00349 
00350     if (!uocAst->isValid()) {
00351       std::cerr << "PANIC: Invalid AST built for file \""        
00352                 << origin
00353                 << "\"."
00354                 << "[Pass: "
00355                 << passInfo[i].descrip
00356                 << "] "
00357                 << "Please report this problem.\n"; 
00358       std::cerr << uocAst->asString() << std::endl;
00359       exit(1);
00360     }
00361 
00362     if (passInfo[i].printAfter) {
00363       std::cerr << "==== DUMPING "
00364                 << uocName
00365                 << " AFTER " << passInfo[i].name 
00366                 << " ====" << std::endl;
00367       this->PrettyPrint(std::cerr, Options::ppDecorate);
00368     }
00369     if (passInfo[i].typesAfter || 
00370         (showTypes && passInfo[i].name == "typecheck")) {
00371       std::cerr << "==== TYPES "
00372                 << uocName
00373                 << " AFTER " << passInfo[i].name 
00374                 << " ====" << std::endl;
00375       this->ShowTypes(std::cerr);
00376       std::cerr <<std::endl << std::endl;
00377     }
00378 
00379     if (passInfo[i].stopAfter) {
00380       std::cerr << "Stopping (on request) after "
00381                 << passInfo[i].name
00382                 << std::endl;
00383       return;
00384     }
00385 
00386     lastCompletedPass = (Pass) i;
00387   }
00388 }
00389 
00390 void
00391 UocInfo::DoBackend() 
00392 {
00393   for (size_t i = op_none+1; (OnePass)i <= Options::backEnd->oPass ; i++) {
00394     
00395     if (Options::showPasses)
00396       std::cerr << "PASS " << onePassInfo[i].name << std::endl;
00397 
00398     if (! (this->*onePassInfo[i].fn)(std::cerr, true, 0)) {
00399       std::cerr << "Exiting due to errors during "
00400                 << onePassInfo[i].descrip
00401                 << std::endl;
00402       exit(1);
00403     }
00404 
00405     if (!uocAst->isValid()) {
00406       std::cerr << "PANIC: Invalid AST built for file \""
00407                 << origin
00408                 << "\"."
00409                 << "Please report this problem.\n"; 
00410       std::cerr << uocAst->asString() << std::endl;
00411       exit(1);
00412     }
00413 
00414     if (onePassInfo[i].printAfter) {
00415       std::cerr << "==== DUMPING bigAST AFTER"
00416                 << onePassInfo[i].name 
00417                 << " ====" << std::endl;
00418       this->PrettyPrint(std::cerr, Options::ppDecorate);
00419     }
00420 
00421     if (onePassInfo[i].typesAfter) {
00422       std::cerr << "==== TYPES bigAST AFTER"
00423                 << onePassInfo[i].name 
00424                 << " ====" << std::endl;
00425       this->ShowTypes(std::cerr);
00426       std::cerr <<std::endl << std::endl;
00427     }
00428 
00429     if (onePassInfo[i].stopAfter) {
00430       std::cerr << "Stopping (on request) after "
00431                 << onePassInfo[i].name
00432                 << std::endl;
00433       exit(1);
00434     }
00435   }  
00436 }

Generated on Thu May 17 23:59:16 2012 for BitC Compiler by  doxygen 1.4.7