00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
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
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
00101
00102
00103
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
00147
00148
00149
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
00187
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
00200
00201
00202
00203
00204
00205 lexer.setDebug(Options::showLex);
00206
00207 extern int transition_parse(TransitionLexer *lexer);
00208 transition_parse(&lexer);
00209
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
00234
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
00269
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
00308
00309
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
00322
00323
00324
00325
00326 bool showTypes = false;
00327
00328
00329
00330
00331
00332
00333
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 }