void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, const HeaderSearchOptions &HSOpts) { llvm::Triple::OSType os = triple.getOS(); if (HSOpts.UseStandardSystemIncludes) { switch (os) { case llvm::Triple::FreeBSD: case llvm::Triple::NetBSD: case llvm::Triple::OpenBSD: case llvm::Triple::Bitrig: break; default: // FIXME: temporary hack: hard-coded paths. AddPath("/usr/local/include", System, false); break; } } // Builtin includes use #include_next directives and should be positioned // just prior C include dirs. if (HSOpts.UseBuiltinIncludes) { // Ignore the sys root, we *always* look for clang headers relative to // supplied path. SmallString<128> P = StringRef(HSOpts.ResourceDir); llvm::sys::path::append(P, "include"); AddUnmappedPath(P.str(), ExternCSystem, false); } // All remaining additions are for system include directories, early exit if // we aren't using them. if (!HSOpts.UseStandardSystemIncludes) return; // Add dirs specified via 'configure --with-c-include-dirs'. StringRef CIncludeDirs(C_INCLUDE_DIRS); if (CIncludeDirs != "") { SmallVector<StringRef, 5> dirs; CIncludeDirs.split(dirs, ":"); for (SmallVectorImpl<StringRef>::iterator i = dirs.begin(); i != dirs.end(); ++i) AddPath(*i, ExternCSystem, false); return; } switch (os) { case llvm::Triple::Linux: case llvm::Triple::Win32: llvm_unreachable("Include management is handled in the driver."); case llvm::Triple::Haiku: AddPath("/boot/common/include", System, false); AddPath("/boot/develop/headers/os", System, false); AddPath("/boot/develop/headers/os/app", System, false); AddPath("/boot/develop/headers/os/arch", System, false); AddPath("/boot/develop/headers/os/device", System, false); AddPath("/boot/develop/headers/os/drivers", System, false); AddPath("/boot/develop/headers/os/game", System, false); AddPath("/boot/develop/headers/os/interface", System, false); AddPath("/boot/develop/headers/os/kernel", System, false); AddPath("/boot/develop/headers/os/locale", System, false); AddPath("/boot/develop/headers/os/mail", System, false); AddPath("/boot/develop/headers/os/media", System, false); AddPath("/boot/develop/headers/os/midi", System, false); AddPath("/boot/develop/headers/os/midi2", System, false); AddPath("/boot/develop/headers/os/net", System, false); AddPath("/boot/develop/headers/os/storage", System, false); AddPath("/boot/develop/headers/os/support", System, false); AddPath("/boot/develop/headers/os/translation", System, false); AddPath("/boot/develop/headers/os/add-ons/graphics", System, false); AddPath("/boot/develop/headers/os/add-ons/input_server", System, false); AddPath("/boot/develop/headers/os/add-ons/screen_saver", System, false); AddPath("/boot/develop/headers/os/add-ons/tracker", System, false); AddPath("/boot/develop/headers/os/be_apps/Deskbar", System, false); AddPath("/boot/develop/headers/os/be_apps/NetPositive", System, false); AddPath("/boot/develop/headers/os/be_apps/Tracker", System, false); AddPath("/boot/develop/headers/cpp", System, false); AddPath("/boot/develop/headers/cpp/i586-pc-haiku", System, false); AddPath("/boot/develop/headers/3rdparty", System, false); AddPath("/boot/develop/headers/bsd", System, false); AddPath("/boot/develop/headers/glibc", System, false); AddPath("/boot/develop/headers/posix", System, false); AddPath("/boot/develop/headers", System, false); break; case llvm::Triple::RTEMS: break; case llvm::Triple::Cygwin: // The headers in w32api/ are not cygwin-compatible (but native) //AddPath("/usr/include/w32api", System, false); break; case llvm::Triple::MinGW32: { // mingw-w64 crt include paths // <sysroot>/i686-w64-mingw32/include SmallString<128> P = StringRef(HSOpts.ResourceDir); llvm::sys::path::append(P, "../../../i686-w64-mingw32/include"); AddPath(P.str(), System, false); // <sysroot>/x86_64-w64-mingw32/include P.resize(HSOpts.ResourceDir.size()); llvm::sys::path::append(P, "../../../x86_64-w64-mingw32/include"); AddPath(P.str(), System, false); // mingw.org crt include paths // <sysroot>/include P.resize(HSOpts.ResourceDir.size()); llvm::sys::path::append(P, "../../../include"); AddPath(P.str(), System, false); AddPath("/mingw/include", System, false); #if defined(_WIN32) AddPath("c:/mingw/include", System, false); #endif } break; default: break; } if ( os != llvm::Triple::RTEMS ) AddPath("/usr/include", ExternCSystem, false); }
/// runPasses - Run the specified passes on Program, outputting a bitcode file /// and writing the filename into OutputFile if successful. If the /// optimizations fail for some reason (optimizer crashes), return true, /// otherwise return false. If DeleteOutput is set to true, the bitcode is /// deleted on success, and the filename string is undefined. This prints to /// outs() a single line message indicating whether compilation was successful /// or failed. /// bool BugDriver::runPasses(Module &Program, const std::vector<std::string> &Passes, std::string &OutputFilename, bool DeleteOutput, bool Quiet, unsigned NumExtraArgs, const char *const *ExtraArgs) const { // setup the output file name outs().flush(); SmallString<128> UniqueFilename; std::error_code EC = sys::fs::createUniqueFile( OutputPrefix + "-output-%%%%%%%.bc", UniqueFilename); if (EC) { errs() << getToolName() << ": Error making unique filename: " << EC.message() << "\n"; return 1; } OutputFilename = UniqueFilename.str(); // set up the input file name Expected<sys::fs::TempFile> Temp = sys::fs::TempFile::create(OutputPrefix + "-input-%%%%%%%.bc"); if (!Temp) { errs() << getToolName() << ": Error making unique filename: " << toString(Temp.takeError()) << "\n"; return 1; } DiscardTemp Discard{*Temp}; raw_fd_ostream OS(Temp->FD, /*shouldClose*/ false); WriteBitcodeToFile(Program, OS, PreserveBitcodeUseListOrder); OS.flush(); if (OS.has_error()) { errs() << "Error writing bitcode file: " << Temp->TmpName << "\n"; OS.clear_error(); return 1; } std::string tool = OptCmd; if (OptCmd.empty()) { if (ErrorOr<std::string> Path = sys::findProgramByName("opt")) tool = *Path; else errs() << Path.getError().message() << "\n"; } if (tool.empty()) { errs() << "Cannot find `opt' in PATH!\n"; return 1; } if (!sys::fs::exists(tool)) { errs() << "Specified `opt' binary does not exist: " << tool << "\n"; return 1; } std::string Prog; if (UseValgrind) { if (ErrorOr<std::string> Path = sys::findProgramByName("valgrind")) Prog = *Path; else errs() << Path.getError().message() << "\n"; } else Prog = tool; if (Prog.empty()) { errs() << "Cannot find `valgrind' in PATH!\n"; return 1; } // setup the child process' arguments SmallVector<StringRef, 8> Args; if (UseValgrind) { Args.push_back("valgrind"); Args.push_back("--error-exitcode=1"); Args.push_back("-q"); Args.push_back(tool); } else Args.push_back(tool); for (unsigned i = 0, e = OptArgs.size(); i != e; ++i) Args.push_back(OptArgs[i]); Args.push_back("-disable-symbolication"); Args.push_back("-o"); Args.push_back(OutputFilename); std::vector<std::string> pass_args; for (unsigned i = 0, e = PluginLoader::getNumPlugins(); i != e; ++i) { pass_args.push_back(std::string("-load")); pass_args.push_back(PluginLoader::getPlugin(i)); } for (std::vector<std::string>::const_iterator I = Passes.begin(), E = Passes.end(); I != E; ++I) pass_args.push_back(std::string("-") + (*I)); for (std::vector<std::string>::const_iterator I = pass_args.begin(), E = pass_args.end(); I != E; ++I) Args.push_back(I->c_str()); Args.push_back(Temp->TmpName.c_str()); for (unsigned i = 0; i < NumExtraArgs; ++i) Args.push_back(*ExtraArgs); LLVM_DEBUG(errs() << "\nAbout to run:\t"; for (unsigned i = 0, e = Args.size() - 1; i != e; ++i) errs() << " " << Args[i]; errs() << "\n";);
void MCStreamer::EmitRawTextAsm(const Twine &T) { SmallString<128> Str; T.toVector(Str); EmitRawTextAsm(Str.str()); }
const char *ArgList::MakeArgString(const Twine &T) const { SmallString<256> Str; T.toVector(Str); return MakeArgString(Str.str()); }
void Preprocessor::HandlePragmaIncludeAlias(Token &Tok) { // We will either get a quoted filename or a bracketed filename, and we // have to track which we got. The first filename is the source name, // and the second name is the mapped filename. If the first is quoted, // the second must be as well (cannot mix and match quotes and brackets). // Get the open paren Lex(Tok); if (Tok.isNot(tok::l_paren)) { Diag(Tok, diag::warn_pragma_include_alias_expected) << "("; return; } // We expect either a quoted string literal, or a bracketed name Token SourceFilenameTok; CurPPLexer->LexIncludeFilename(SourceFilenameTok); if (SourceFilenameTok.is(tok::eod)) { // The diagnostic has already been handled return; } StringRef SourceFileName; SmallString<128> FileNameBuffer; if (SourceFilenameTok.is(tok::string_literal) || SourceFilenameTok.is(tok::angle_string_literal)) { SourceFileName = getSpelling(SourceFilenameTok, FileNameBuffer); } else if (SourceFilenameTok.is(tok::less)) { // This could be a path instead of just a name FileNameBuffer.push_back('<'); SourceLocation End; if (ConcatenateIncludeName(FileNameBuffer, End)) return; // Diagnostic already emitted SourceFileName = FileNameBuffer.str(); } else { Diag(Tok, diag::warn_pragma_include_alias_expected_filename); return; } FileNameBuffer.clear(); // Now we expect a comma, followed by another include name Lex(Tok); if (Tok.isNot(tok::comma)) { Diag(Tok, diag::warn_pragma_include_alias_expected) << ","; return; } Token ReplaceFilenameTok; CurPPLexer->LexIncludeFilename(ReplaceFilenameTok); if (ReplaceFilenameTok.is(tok::eod)) { // The diagnostic has already been handled return; } StringRef ReplaceFileName; if (ReplaceFilenameTok.is(tok::string_literal) || ReplaceFilenameTok.is(tok::angle_string_literal)) { ReplaceFileName = getSpelling(ReplaceFilenameTok, FileNameBuffer); } else if (ReplaceFilenameTok.is(tok::less)) { // This could be a path instead of just a name FileNameBuffer.push_back('<'); SourceLocation End; if (ConcatenateIncludeName(FileNameBuffer, End)) return; // Diagnostic already emitted ReplaceFileName = FileNameBuffer.str(); } else { Diag(Tok, diag::warn_pragma_include_alias_expected_filename); return; } // Finally, we expect the closing paren Lex(Tok); if (Tok.isNot(tok::r_paren)) { Diag(Tok, diag::warn_pragma_include_alias_expected) << ")"; return; } // Now that we have the source and target filenames, we need to make sure // they're both of the same type (angled vs non-angled) StringRef OriginalSource = SourceFileName; bool SourceIsAngled = GetIncludeFilenameSpelling(SourceFilenameTok.getLocation(), SourceFileName); bool ReplaceIsAngled = GetIncludeFilenameSpelling(ReplaceFilenameTok.getLocation(), ReplaceFileName); if (!SourceFileName.empty() && !ReplaceFileName.empty() && (SourceIsAngled != ReplaceIsAngled)) { unsigned int DiagID; if (SourceIsAngled) DiagID = diag::warn_pragma_include_alias_mismatch_angle; else DiagID = diag::warn_pragma_include_alias_mismatch_quote; Diag(SourceFilenameTok.getLocation(), DiagID) << SourceFileName << ReplaceFileName; return; } // Now we can let the include handler know about this mapping getHeaderSearchInfo().AddIncludeAlias(OriginalSource, ReplaceFileName); }
bool WriteBundleEnd(raw_fd_ostream &OS, StringRef TargetTriple) final { assert(NumberOfProcessedInputs <= NumberOfInputs && "Processing more inputs that actually exist!"); assert(HostInputIndex != ~0u && "Host input index not defined."); // If this is not the last output, we don't have to do anything. if (NumberOfProcessedInputs != NumberOfInputs) return false; // Create the bitcode file name to write the resulting code to. Keep it if // save-temps is active. SmallString<128> BitcodeFileName; if (sys::fs::createTemporaryFile("clang-offload-bundler", "bc", BitcodeFileName)) { errs() << "error: unable to create temporary file.\n"; return true; } // Dump the contents of the temporary file if that was requested. if (DumpTemporaryFiles) { errs() << ";\n; Object file bundler IR file.\n;\n"; AuxModule.get()->print(errs(), nullptr, /*ShouldPreserveUseListOrder=*/false, /*IsForDebug=*/true); errs() << '\n'; } // Find clang in order to create the bundle binary. StringRef Dir = sys::path::parent_path(BundlerExecutable); auto ClangBinary = sys::findProgramByName("clang", Dir); if (ClangBinary.getError()) { // Remove bitcode file. sys::fs::remove(BitcodeFileName); errs() << "error: unable to find 'clang' in path.\n"; return true; } // Do the incremental linking. We write to the output file directly. So, we // close it and use the name to pass down to clang. OS.close(); SmallString<128> TargetName = getTriple(TargetNames[HostInputIndex]); std::vector<StringRef> ClangArgs = {"clang", "-r", "-target", TargetName.c_str(), "-o", OutputFileNames.front().c_str(), InputFileNames[HostInputIndex].c_str(), BitcodeFileName.c_str(), "-nostdlib"}; // If the user asked for the commands to be printed out, we do that instead // of executing it. if (PrintExternalCommands) { errs() << "\"" << ClangBinary.get() << "\""; for (StringRef Arg : ClangArgs) errs() << " \"" << Arg << "\""; errs() << "\n"; } else { // Write the bitcode contents to the temporary file. { std::error_code EC; raw_fd_ostream BitcodeFile(BitcodeFileName, EC, sys::fs::F_None); if (EC) { errs() << "error: unable to open temporary file.\n"; return true; } WriteBitcodeToFile(*AuxModule, BitcodeFile); } bool Failed = sys::ExecuteAndWait(ClangBinary.get(), ClangArgs); // Remove bitcode file. sys::fs::remove(BitcodeFileName); if (Failed) { errs() << "error: incremental linking by external tool failed.\n"; return true; } } return false; }
/// ParseInitializerWithPotentialDesignator - Parse the 'initializer' production /// checking to see if the token stream starts with a designator. /// /// designation: /// designator-list '=' /// [GNU] array-designator /// [GNU] identifier ':' /// /// designator-list: /// designator /// designator-list designator /// /// designator: /// array-designator /// '.' identifier /// /// array-designator: /// '[' constant-expression ']' /// [GNU] '[' constant-expression '...' constant-expression ']' /// /// NOTE: [OBC] allows '[ objc-receiver objc-message-args ]' as an /// initializer (because it is an expression). We need to consider this case /// when parsing array designators. /// ExprResult Parser::ParseInitializerWithPotentialDesignator() { // If this is the old-style GNU extension: // designation ::= identifier ':' // Handle it as a field designator. Otherwise, this must be the start of a // normal expression. if (Tok.is(tok::identifier)) { const IdentifierInfo *FieldName = Tok.getIdentifierInfo(); SmallString<256> NewSyntax; llvm::raw_svector_ostream(NewSyntax) << '.' << FieldName->getName() << " = "; SourceLocation NameLoc = ConsumeToken(); // Eat the identifier. assert(Tok.is(tok::colon) && "MayBeDesignationStart not working properly!"); SourceLocation ColonLoc = ConsumeToken(); Diag(NameLoc, diag::ext_gnu_old_style_field_designator) << FixItHint::CreateReplacement(SourceRange(NameLoc, ColonLoc), NewSyntax.str()); Designation D; D.AddDesignator(Designator::getField(FieldName, SourceLocation(), NameLoc)); return Actions.ActOnDesignatedInitializer(D, ColonLoc, true, ParseInitializer()); } // Desig - This is initialized when we see our first designator. We may have // an objc message send with no designator, so we don't want to create this // eagerly. Designation Desig; // Parse each designator in the designator list until we find an initializer. while (Tok.is(tok::period) || Tok.is(tok::l_square)) { if (Tok.is(tok::period)) { // designator: '.' identifier SourceLocation DotLoc = ConsumeToken(); if (Tok.isNot(tok::identifier)) { Diag(Tok.getLocation(), diag::err_expected_field_designator); return ExprError(); } Desig.AddDesignator(Designator::getField(Tok.getIdentifierInfo(), DotLoc, Tok.getLocation())); ConsumeToken(); // Eat the identifier. continue; } // We must have either an array designator now or an objc message send. assert(Tok.is(tok::l_square) && "Unexpected token!"); // Handle the two forms of array designator: // array-designator: '[' constant-expression ']' // array-designator: '[' constant-expression '...' constant-expression ']' // // Also, we have to handle the case where the expression after the // designator an an objc message send: '[' objc-message-expr ']'. // Interesting cases are: // [foo bar] -> objc message send // [foo] -> array designator // [foo ... bar] -> array designator // [4][foo bar] -> obsolete GNU designation with objc message send. // // We do not need to check for an expression starting with [[ here. If it // contains an Objective-C message send, then it is not an ill-formed // attribute. If it is a lambda-expression within an array-designator, then // it will be rejected because a constant-expression cannot begin with a // lambda-expression. InMessageExpressionRAIIObject InMessage(*this, true); BalancedDelimiterTracker T(*this, tok::l_square); T.consumeOpen(); SourceLocation StartLoc = T.getOpenLocation(); ExprResult Idx; // If Objective-C is enabled and this is a typename (class message // send) or send to 'super', parse this as a message send // expression. We handle C++ and C separately, since C++ requires // much more complicated parsing. if (getLangOpts().ObjC1 && getLangOpts().CPlusPlus) { // Send to 'super'. if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super && NextToken().isNot(tok::period) && getCurScope()->isInObjcMethodScope()) { CheckArrayDesignatorSyntax(*this, StartLoc, Desig); return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, ConsumeToken(), ParsedType(), 0); } // Parse the receiver, which is either a type or an expression. bool IsExpr; void *TypeOrExpr; if (ParseObjCXXMessageReceiver(IsExpr, TypeOrExpr)) { SkipUntil(tok::r_square); return ExprError(); } // If the receiver was a type, we have a class message; parse // the rest of it. if (!IsExpr) { CheckArrayDesignatorSyntax(*this, StartLoc, Desig); return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, SourceLocation(), ParsedType::getFromOpaquePtr(TypeOrExpr), 0); } // If the receiver was an expression, we still don't know // whether we have a message send or an array designator; just // adopt the expression for further analysis below. // FIXME: potentially-potentially evaluated expression above? Idx = ExprResult(static_cast<Expr*>(TypeOrExpr)); } else if (getLangOpts().ObjC1 && Tok.is(tok::identifier)) { IdentifierInfo *II = Tok.getIdentifierInfo(); SourceLocation IILoc = Tok.getLocation(); ParsedType ReceiverType; // Three cases. This is a message send to a type: [type foo] // This is a message send to super: [super foo] // This is a message sent to an expr: [super.bar foo] switch (Sema::ObjCMessageKind Kind = Actions.getObjCMessageKind(getCurScope(), II, IILoc, II == Ident_super, NextToken().is(tok::period), ReceiverType)) { case Sema::ObjCSuperMessage: case Sema::ObjCClassMessage: CheckArrayDesignatorSyntax(*this, StartLoc, Desig); if (Kind == Sema::ObjCSuperMessage) return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, ConsumeToken(), ParsedType(), 0); ConsumeToken(); // the identifier if (!ReceiverType) { SkipUntil(tok::r_square); return ExprError(); } return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, SourceLocation(), ReceiverType, 0); case Sema::ObjCInstanceMessage: // Fall through; we'll just parse the expression and // (possibly) treat this like an Objective-C message send // later. break; } } // Parse the index expression, if we haven't already gotten one // above (which can only happen in Objective-C++). // Note that we parse this as an assignment expression, not a constant // expression (allowing *=, =, etc) to handle the objc case. Sema needs // to validate that the expression is a constant. // FIXME: We also need to tell Sema that we're in a // potentially-potentially evaluated context. if (!Idx.get()) { Idx = ParseAssignmentExpression(); if (Idx.isInvalid()) { SkipUntil(tok::r_square); return Idx; } } // Given an expression, we could either have a designator (if the next // tokens are '...' or ']' or an objc message send. If this is an objc // message send, handle it now. An objc-message send is the start of // an assignment-expression production. if (getLangOpts().ObjC1 && Tok.isNot(tok::ellipsis) && Tok.isNot(tok::r_square)) { CheckArrayDesignatorSyntax(*this, Tok.getLocation(), Desig); return ParseAssignmentExprWithObjCMessageExprStart(StartLoc, SourceLocation(), ParsedType(), Idx.take()); } // If this is a normal array designator, remember it. if (Tok.isNot(tok::ellipsis)) { Desig.AddDesignator(Designator::getArray(Idx.release(), StartLoc)); } else { // Handle the gnu array range extension. Diag(Tok, diag::ext_gnu_array_range); SourceLocation EllipsisLoc = ConsumeToken(); ExprResult RHS(ParseConstantExpression()); if (RHS.isInvalid()) { SkipUntil(tok::r_square); return RHS; } Desig.AddDesignator(Designator::getArrayRange(Idx.release(), RHS.release(), StartLoc, EllipsisLoc)); } T.consumeClose(); Desig.getDesignator(Desig.getNumDesignators() - 1).setRBracketLoc( T.getCloseLocation()); } // Okay, we're done with the designator sequence. We know that there must be // at least one designator, because the only case we can get into this method // without a designator is when we have an objc message send. That case is // handled and returned from above. assert(!Desig.empty() && "Designator is empty?"); // Handle a normal designator sequence end, which is an equal. if (Tok.is(tok::equal)) { SourceLocation EqualLoc = ConsumeToken(); return Actions.ActOnDesignatedInitializer(Desig, EqualLoc, false, ParseInitializer()); } // We read some number of designators and found something that isn't an = or // an initializer. If we have exactly one array designator, this // is the GNU 'designation: array-designator' extension. Otherwise, it is a // parse error. if (Desig.getNumDesignators() == 1 && (Desig.getDesignator(0).isArrayDesignator() || Desig.getDesignator(0).isArrayRangeDesignator())) { Diag(Tok, diag::ext_gnu_missing_equal_designator) << FixItHint::CreateInsertion(Tok.getLocation(), "= "); return Actions.ActOnDesignatedInitializer(Desig, Tok.getLocation(), true, ParseInitializer()); } Diag(Tok, diag::err_expected_equal_designator); return ExprError(); }
/// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable /// to hold function specific information. NamedMDNode *llvm::getOrInsertFnSpecificMDNode(Module &M, DISubprogram Fn) { SmallString<32> Name; fixupSubprogramName(Fn, Name); return M.getOrInsertNamedMetadata(Name.str()); }
/// EmitMatcher - Emit bytes for the specified matcher and return /// the number of bytes emitted. unsigned MatcherTableEmitter:: EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, raw_ostream &OS) { OS.indent(Indent*2); switch (N->getKind()) { case Matcher::Scope: { const ScopeMatcher *SM = cast<ScopeMatcher>(N); assert(SM->getNext() == nullptr && "Shouldn't have next after scope"); unsigned StartIdx = CurrentIdx; // Emit all of the children. for (unsigned i = 0, e = SM->getNumChildren(); i != e; ++i) { if (i == 0) { OS << "OPC_Scope, "; ++CurrentIdx; } else { if (!OmitComments) { OS << "/*" << format_decimal(CurrentIdx, IndexWidth) << "*/"; OS.indent(Indent*2) << "/*Scope*/ "; } else OS.indent(Indent*2); } // We need to encode the child and the offset of the failure code before // emitting either of them. Handle this by buffering the output into a // string while we get the size. Unfortunately, the offset of the // children depends on the VBR size of the child, so for large children we // have to iterate a bit. SmallString<128> TmpBuf; unsigned ChildSize = 0; unsigned VBRSize = 0; do { VBRSize = GetVBRSize(ChildSize); TmpBuf.clear(); raw_svector_ostream OS(TmpBuf); ChildSize = EmitMatcherList(SM->getChild(i), Indent+1, CurrentIdx+VBRSize, OS); } while (GetVBRSize(ChildSize) != VBRSize); assert(ChildSize != 0 && "Should not have a zero-sized child!"); CurrentIdx += EmitVBRValue(ChildSize, OS); if (!OmitComments) { OS << "/*->" << CurrentIdx+ChildSize << "*/"; if (i == 0) OS << " // " << SM->getNumChildren() << " children in Scope"; } OS << '\n' << TmpBuf; CurrentIdx += ChildSize; } // Emit a zero as a sentinel indicating end of 'Scope'. if (!OmitComments) OS << "/*" << format_decimal(CurrentIdx, IndexWidth) << "*/"; OS.indent(Indent*2) << "0, "; if (!OmitComments) OS << "/*End of Scope*/"; OS << '\n'; return CurrentIdx - StartIdx + 1; } case Matcher::RecordNode: OS << "OPC_RecordNode,"; if (!OmitComments) OS << " // #" << cast<RecordMatcher>(N)->getResultNo() << " = " << cast<RecordMatcher>(N)->getWhatFor(); OS << '\n'; return 1; case Matcher::RecordChild: OS << "OPC_RecordChild" << cast<RecordChildMatcher>(N)->getChildNo() << ','; if (!OmitComments) OS << " // #" << cast<RecordChildMatcher>(N)->getResultNo() << " = " << cast<RecordChildMatcher>(N)->getWhatFor(); OS << '\n'; return 1; case Matcher::RecordMemRef: OS << "OPC_RecordMemRef,\n"; return 1; case Matcher::CaptureGlueInput: OS << "OPC_CaptureGlueInput,\n"; return 1; case Matcher::MoveChild: { const auto *MCM = cast<MoveChildMatcher>(N); OS << "OPC_MoveChild"; // Handle the specialized forms. if (MCM->getChildNo() >= 8) OS << ", "; OS << MCM->getChildNo() << ",\n"; return (MCM->getChildNo() >= 8) ? 2 : 1; } case Matcher::MoveParent: OS << "OPC_MoveParent,\n"; return 1; case Matcher::CheckSame: OS << "OPC_CheckSame, " << cast<CheckSameMatcher>(N)->getMatchNumber() << ",\n"; return 2; case Matcher::CheckChildSame: OS << "OPC_CheckChild" << cast<CheckChildSameMatcher>(N)->getChildNo() << "Same, " << cast<CheckChildSameMatcher>(N)->getMatchNumber() << ",\n"; return 2; case Matcher::CheckPatternPredicate: { StringRef Pred =cast<CheckPatternPredicateMatcher>(N)->getPredicate(); OS << "OPC_CheckPatternPredicate, " << getPatternPredicate(Pred) << ','; if (!OmitComments) OS << " // " << Pred; OS << '\n'; return 2; } case Matcher::CheckPredicate: { TreePredicateFn Pred = cast<CheckPredicateMatcher>(N)->getPredicate(); unsigned OperandBytes = 0; if (Pred.usesOperands()) { unsigned NumOps = cast<CheckPredicateMatcher>(N)->getNumOperands(); OS << "OPC_CheckPredicateWithOperands, " << NumOps << "/*#Ops*/, "; for (unsigned i = 0; i < NumOps; ++i) OS << cast<CheckPredicateMatcher>(N)->getOperandNo(i) << ", "; OperandBytes = 1 + NumOps; } else { OS << "OPC_CheckPredicate, "; } OS << getNodePredicate(Pred) << ','; if (!OmitComments) OS << " // " << Pred.getFnName(); OS << '\n'; return 2 + OperandBytes; } case Matcher::CheckOpcode: OS << "OPC_CheckOpcode, TARGET_VAL(" << cast<CheckOpcodeMatcher>(N)->getOpcode().getEnumName() << "),\n"; return 3; case Matcher::SwitchOpcode: case Matcher::SwitchType: { unsigned StartIdx = CurrentIdx; unsigned NumCases; if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) { OS << "OPC_SwitchOpcode "; NumCases = SOM->getNumCases(); } else { OS << "OPC_SwitchType "; NumCases = cast<SwitchTypeMatcher>(N)->getNumCases(); } if (!OmitComments) OS << "/*" << NumCases << " cases */"; OS << ", "; ++CurrentIdx; // For each case we emit the size, then the opcode, then the matcher. for (unsigned i = 0, e = NumCases; i != e; ++i) { const Matcher *Child; unsigned IdxSize; if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) { Child = SOM->getCaseMatcher(i); IdxSize = 2; // size of opcode in table is 2 bytes. } else { Child = cast<SwitchTypeMatcher>(N)->getCaseMatcher(i); IdxSize = 1; // size of type in table is 1 byte. } // We need to encode the opcode and the offset of the case code before // emitting the case code. Handle this by buffering the output into a // string while we get the size. Unfortunately, the offset of the // children depends on the VBR size of the child, so for large children we // have to iterate a bit. SmallString<128> TmpBuf; unsigned ChildSize = 0; unsigned VBRSize = 0; do { VBRSize = GetVBRSize(ChildSize); TmpBuf.clear(); raw_svector_ostream OS(TmpBuf); ChildSize = EmitMatcherList(Child, Indent+1, CurrentIdx+VBRSize+IdxSize, OS); } while (GetVBRSize(ChildSize) != VBRSize); assert(ChildSize != 0 && "Should not have a zero-sized child!"); if (i != 0) { if (!OmitComments) OS << "/*" << format_decimal(CurrentIdx, IndexWidth) << "*/"; OS.indent(Indent*2); if (!OmitComments) OS << (isa<SwitchOpcodeMatcher>(N) ? "/*SwitchOpcode*/ " : "/*SwitchType*/ "); } // Emit the VBR. CurrentIdx += EmitVBRValue(ChildSize, OS); if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) OS << "TARGET_VAL(" << SOM->getCaseOpcode(i).getEnumName() << "),"; else OS << getEnumName(cast<SwitchTypeMatcher>(N)->getCaseType(i)) << ','; CurrentIdx += IdxSize; if (!OmitComments) OS << "// ->" << CurrentIdx+ChildSize; OS << '\n'; OS << TmpBuf; CurrentIdx += ChildSize; } // Emit the final zero to terminate the switch. if (!OmitComments) OS << "/*" << format_decimal(CurrentIdx, IndexWidth) << "*/"; OS.indent(Indent*2) << "0,"; if (!OmitComments) OS << (isa<SwitchOpcodeMatcher>(N) ? " // EndSwitchOpcode" : " // EndSwitchType"); OS << '\n'; ++CurrentIdx; return CurrentIdx-StartIdx; } case Matcher::CheckType: if (cast<CheckTypeMatcher>(N)->getResNo() == 0) { OS << "OPC_CheckType, " << getEnumName(cast<CheckTypeMatcher>(N)->getType()) << ",\n"; return 2; } OS << "OPC_CheckTypeRes, " << cast<CheckTypeMatcher>(N)->getResNo() << ", " << getEnumName(cast<CheckTypeMatcher>(N)->getType()) << ",\n"; return 3; case Matcher::CheckChildType: OS << "OPC_CheckChild" << cast<CheckChildTypeMatcher>(N)->getChildNo() << "Type, " << getEnumName(cast<CheckChildTypeMatcher>(N)->getType()) << ",\n"; return 2; case Matcher::CheckInteger: { OS << "OPC_CheckInteger, "; unsigned Bytes=1+EmitVBRValue(cast<CheckIntegerMatcher>(N)->getValue(), OS); OS << '\n'; return Bytes; } case Matcher::CheckChildInteger: { OS << "OPC_CheckChild" << cast<CheckChildIntegerMatcher>(N)->getChildNo() << "Integer, "; unsigned Bytes=1+EmitVBRValue(cast<CheckChildIntegerMatcher>(N)->getValue(), OS); OS << '\n'; return Bytes; } case Matcher::CheckCondCode: OS << "OPC_CheckCondCode, ISD::" << cast<CheckCondCodeMatcher>(N)->getCondCodeName() << ",\n"; return 2; case Matcher::CheckChild2CondCode: OS << "OPC_CheckChild2CondCode, ISD::" << cast<CheckChild2CondCodeMatcher>(N)->getCondCodeName() << ",\n"; return 2; case Matcher::CheckValueType: OS << "OPC_CheckValueType, MVT::" << cast<CheckValueTypeMatcher>(N)->getTypeName() << ",\n"; return 2; case Matcher::CheckComplexPat: { const CheckComplexPatMatcher *CCPM = cast<CheckComplexPatMatcher>(N); const ComplexPattern &Pattern = CCPM->getPattern(); OS << "OPC_CheckComplexPat, /*CP*/" << getComplexPat(Pattern) << ", /*#*/" << CCPM->getMatchNumber() << ','; if (!OmitComments) { OS << " // " << Pattern.getSelectFunc(); OS << ":$" << CCPM->getName(); for (unsigned i = 0, e = Pattern.getNumOperands(); i != e; ++i) OS << " #" << CCPM->getFirstResult()+i; if (Pattern.hasProperty(SDNPHasChain)) OS << " + chain result"; } OS << '\n'; return 3; } case Matcher::CheckAndImm: { OS << "OPC_CheckAndImm, "; unsigned Bytes=1+EmitVBRValue(cast<CheckAndImmMatcher>(N)->getValue(), OS); OS << '\n'; return Bytes; } case Matcher::CheckOrImm: { OS << "OPC_CheckOrImm, "; unsigned Bytes = 1+EmitVBRValue(cast<CheckOrImmMatcher>(N)->getValue(), OS); OS << '\n'; return Bytes; } case Matcher::CheckFoldableChainNode: OS << "OPC_CheckFoldableChainNode,\n"; return 1; case Matcher::CheckImmAllOnesV: OS << "OPC_CheckImmAllOnesV,\n"; return 1; case Matcher::CheckImmAllZerosV: OS << "OPC_CheckImmAllZerosV,\n"; return 1; case Matcher::EmitInteger: { int64_t Val = cast<EmitIntegerMatcher>(N)->getValue(); OS << "OPC_EmitInteger, " << getEnumName(cast<EmitIntegerMatcher>(N)->getVT()) << ", "; unsigned Bytes = 2+EmitVBRValue(Val, OS); OS << '\n'; return Bytes; } case Matcher::EmitStringInteger: { const std::string &Val = cast<EmitStringIntegerMatcher>(N)->getValue(); // These should always fit into one byte. OS << "OPC_EmitInteger, " << getEnumName(cast<EmitStringIntegerMatcher>(N)->getVT()) << ", " << Val << ",\n"; return 3; } case Matcher::EmitRegister: { const EmitRegisterMatcher *Matcher = cast<EmitRegisterMatcher>(N); const CodeGenRegister *Reg = Matcher->getReg(); // If the enum value of the register is larger than one byte can handle, // use EmitRegister2. if (Reg && Reg->EnumValue > 255) { OS << "OPC_EmitRegister2, " << getEnumName(Matcher->getVT()) << ", "; OS << "TARGET_VAL(" << getQualifiedName(Reg->TheDef) << "),\n"; return 4; } else { OS << "OPC_EmitRegister, " << getEnumName(Matcher->getVT()) << ", "; if (Reg) { OS << getQualifiedName(Reg->TheDef) << ",\n"; } else { OS << "0 "; if (!OmitComments) OS << "/*zero_reg*/"; OS << ",\n"; } return 3; } } case Matcher::EmitConvertToTarget: OS << "OPC_EmitConvertToTarget, " << cast<EmitConvertToTargetMatcher>(N)->getSlot() << ",\n"; return 2; case Matcher::EmitMergeInputChains: { const EmitMergeInputChainsMatcher *MN = cast<EmitMergeInputChainsMatcher>(N); // Handle the specialized forms OPC_EmitMergeInputChains1_0, 1_1, and 1_2. if (MN->getNumNodes() == 1 && MN->getNode(0) < 3) { OS << "OPC_EmitMergeInputChains1_" << MN->getNode(0) << ",\n"; return 1; } OS << "OPC_EmitMergeInputChains, " << MN->getNumNodes() << ", "; for (unsigned i = 0, e = MN->getNumNodes(); i != e; ++i) OS << MN->getNode(i) << ", "; OS << '\n'; return 2+MN->getNumNodes(); } case Matcher::EmitCopyToReg: OS << "OPC_EmitCopyToReg, " << cast<EmitCopyToRegMatcher>(N)->getSrcSlot() << ", " << getQualifiedName(cast<EmitCopyToRegMatcher>(N)->getDestPhysReg()) << ",\n"; return 3; case Matcher::EmitNodeXForm: { const EmitNodeXFormMatcher *XF = cast<EmitNodeXFormMatcher>(N); OS << "OPC_EmitNodeXForm, " << getNodeXFormID(XF->getNodeXForm()) << ", " << XF->getSlot() << ','; if (!OmitComments) OS << " // "<<XF->getNodeXForm()->getName(); OS <<'\n'; return 3; } case Matcher::EmitNode: case Matcher::MorphNodeTo: { auto NumCoveredBytes = 0; if (InstrumentCoverage) { if (const MorphNodeToMatcher *SNT = dyn_cast<MorphNodeToMatcher>(N)) { NumCoveredBytes = 3; OS << "OPC_Coverage, "; std::string src = GetPatFromTreePatternNode(SNT->getPattern().getSrcPattern()); std::string dst = GetPatFromTreePatternNode(SNT->getPattern().getDstPattern()); Record *PatRecord = SNT->getPattern().getSrcRecord(); std::string include_src = getIncludePath(PatRecord); unsigned Offset = getPatternIdxFromTable(src + " -> " + dst, std::move(include_src)); OS << "TARGET_VAL(" << Offset << "),\n"; OS.indent(FullIndexWidth + Indent * 2); } } const EmitNodeMatcherCommon *EN = cast<EmitNodeMatcherCommon>(N); OS << (isa<EmitNodeMatcher>(EN) ? "OPC_EmitNode" : "OPC_MorphNodeTo"); bool CompressVTs = EN->getNumVTs() < 3; if (CompressVTs) OS << EN->getNumVTs(); OS << ", TARGET_VAL(" << EN->getOpcodeName() << "), 0"; if (EN->hasChain()) OS << "|OPFL_Chain"; if (EN->hasInFlag()) OS << "|OPFL_GlueInput"; if (EN->hasOutFlag()) OS << "|OPFL_GlueOutput"; if (EN->hasMemRefs()) OS << "|OPFL_MemRefs"; if (EN->getNumFixedArityOperands() != -1) OS << "|OPFL_Variadic" << EN->getNumFixedArityOperands(); OS << ",\n"; OS.indent(FullIndexWidth + Indent*2+4); if (!CompressVTs) { OS << EN->getNumVTs(); if (!OmitComments) OS << "/*#VTs*/"; OS << ", "; } for (unsigned i = 0, e = EN->getNumVTs(); i != e; ++i) OS << getEnumName(EN->getVT(i)) << ", "; OS << EN->getNumOperands(); if (!OmitComments) OS << "/*#Ops*/"; OS << ", "; unsigned NumOperandBytes = 0; for (unsigned i = 0, e = EN->getNumOperands(); i != e; ++i) NumOperandBytes += EmitVBRValue(EN->getOperand(i), OS); if (!OmitComments) { // Print the result #'s for EmitNode. if (const EmitNodeMatcher *E = dyn_cast<EmitNodeMatcher>(EN)) { if (unsigned NumResults = EN->getNumVTs()) { OS << " // Results ="; unsigned First = E->getFirstResultSlot(); for (unsigned i = 0; i != NumResults; ++i) OS << " #" << First+i; } } OS << '\n'; if (const MorphNodeToMatcher *SNT = dyn_cast<MorphNodeToMatcher>(N)) { OS.indent(FullIndexWidth + Indent*2) << "// Src: " << *SNT->getPattern().getSrcPattern() << " - Complexity = " << SNT->getPattern().getPatternComplexity(CGP) << '\n'; OS.indent(FullIndexWidth + Indent*2) << "// Dst: " << *SNT->getPattern().getDstPattern() << '\n'; } } else OS << '\n'; return 5 + !CompressVTs + EN->getNumVTs() + NumOperandBytes + NumCoveredBytes; } case Matcher::CompleteMatch: { const CompleteMatchMatcher *CM = cast<CompleteMatchMatcher>(N); auto NumCoveredBytes = 0; if (InstrumentCoverage) { NumCoveredBytes = 3; OS << "OPC_Coverage, "; std::string src = GetPatFromTreePatternNode(CM->getPattern().getSrcPattern()); std::string dst = GetPatFromTreePatternNode(CM->getPattern().getDstPattern()); Record *PatRecord = CM->getPattern().getSrcRecord(); std::string include_src = getIncludePath(PatRecord); unsigned Offset = getPatternIdxFromTable(src + " -> " + dst, std::move(include_src)); OS << "TARGET_VAL(" << Offset << "),\n"; OS.indent(FullIndexWidth + Indent * 2); } OS << "OPC_CompleteMatch, " << CM->getNumResults() << ", "; unsigned NumResultBytes = 0; for (unsigned i = 0, e = CM->getNumResults(); i != e; ++i) NumResultBytes += EmitVBRValue(CM->getResult(i), OS); OS << '\n'; if (!OmitComments) { OS.indent(FullIndexWidth + Indent*2) << " // Src: " << *CM->getPattern().getSrcPattern() << " - Complexity = " << CM->getPattern().getPatternComplexity(CGP) << '\n'; OS.indent(FullIndexWidth + Indent*2) << " // Dst: " << *CM->getPattern().getDstPattern(); } OS << '\n'; return 2 + NumResultBytes + NumCoveredBytes; } } llvm_unreachable("Unreachable"); }
std::string Twine::str() const { SmallString<256> Vec; toVector(Vec); return std::string(Vec.begin(), Vec.end()); }
/// Returns true for failure to resolve. static bool passCursorInfoForDecl(const ValueDecl *VD, const Module *MainModule, const Type Ty, bool IsRef, Optional<unsigned> OrigBufferID, SwiftLangSupport &Lang, const CompilerInvocation &Invok, ArrayRef<ImmutableTextSnapshotRef> PreviousASTSnaps, std::function<void(const CursorInfo &)> Receiver) { if (AvailableAttr::isUnavailable(VD)) return true; SmallString<64> SS; unsigned NameBegin = SS.size(); { llvm::raw_svector_ostream OS(SS); SwiftLangSupport::printDisplayName(VD, OS); } unsigned NameEnd = SS.size(); unsigned USRBegin = SS.size(); { llvm::raw_svector_ostream OS(SS); SwiftLangSupport::printUSR(VD, OS); } unsigned USREnd = SS.size(); unsigned TypenameBegin = SS.size(); if (VD->hasType()) { llvm::raw_svector_ostream OS(SS); VD->getType().print(OS); } unsigned TypenameEnd = SS.size(); unsigned DocCommentBegin = SS.size(); { llvm::raw_svector_ostream OS(SS); ide::getDocumentationCommentAsXML(VD, OS); } unsigned DocCommentEnd = SS.size(); unsigned DeclBegin = SS.size(); { llvm::raw_svector_ostream OS(SS); printAnnotatedDeclaration(VD, OS); } unsigned DeclEnd = SS.size(); SmallVector<std::pair<unsigned, unsigned>, 4> OverUSROffs; ide::walkOverriddenDecls(VD, [&](llvm::PointerUnion<const ValueDecl*, const clang::NamedDecl*> D) { unsigned OverUSRBegin = SS.size(); { llvm::raw_svector_ostream OS(SS); if (auto VD = D.dyn_cast<const ValueDecl*>()) { if (SwiftLangSupport::printUSR(VD, OS)) return; } else { llvm::SmallString<128> Buf; if (clang::index::generateUSRForDecl( D.get<const clang::NamedDecl*>(), Buf)) return; OS << Buf.str(); } } unsigned OverUSREnd = SS.size(); OverUSROffs.push_back(std::make_pair(OverUSRBegin, OverUSREnd)); }); SmallVector<std::pair<unsigned, unsigned>, 4> RelDeclOffs; walkRelatedDecls(VD, [&](const ValueDecl *RelatedDecl, bool DuplicateName) { unsigned RelatedDeclBegin = SS.size(); { llvm::raw_svector_ostream OS(SS); OS<<"<RelatedName usr=\""; SwiftLangSupport::printUSR(RelatedDecl, OS); OS<<"\">"; if (isa<AbstractFunctionDecl>(RelatedDecl) && DuplicateName) { // Related decls are generally overloads, so print parameter types to // differentiate them. PrintOptions PO; PO.SkipAttributes = true; PO.SkipIntroducerKeywords = true; PO.ArgAndParamPrinting = PrintOptions::ArgAndParamPrintingMode::ArgumentOnly; XMLEscapingPrinter Printer(OS); RelatedDecl->print(Printer, PO); } else { llvm::SmallString<128> Buf; { llvm::raw_svector_ostream OSBuf(Buf); SwiftLangSupport::printDisplayName(RelatedDecl, OSBuf); } llvm::markup::appendWithXMLEscaping(OS, Buf); } OS<<"</RelatedName>"; } unsigned RelatedDeclEnd = SS.size(); RelDeclOffs.push_back(std::make_pair(RelatedDeclBegin, RelatedDeclEnd)); }); ASTContext &Ctx = VD->getASTContext(); ClangImporter *Importer = static_cast<ClangImporter*>( Ctx.getClangModuleLoader()); std::string ModuleName; auto ClangNode = VD->getClangNode(); if (ClangNode) { auto ClangMod = Importer->getClangOwningModule(ClangNode); ModuleName = ClangMod->getFullModuleName(); } else if (VD->getLoc().isInvalid() && VD->getModuleContext() != MainModule) { ModuleName = VD->getModuleContext()->getName().str(); } StringRef ModuleInterfaceName; if (auto IFaceGenRef = Lang.getIFaceGenContexts().find(ModuleName, Invok)) ModuleInterfaceName = IFaceGenRef->getDocumentName(); UIdent Kind = SwiftLangSupport::getUIDForDecl(VD, IsRef); StringRef Name = StringRef(SS.begin()+NameBegin, NameEnd-NameBegin); StringRef USR = StringRef(SS.begin()+USRBegin, USREnd-USRBegin); StringRef TypeName = StringRef(SS.begin()+TypenameBegin, TypenameEnd-TypenameBegin); StringRef DocComment = StringRef(SS.begin()+DocCommentBegin, DocCommentEnd-DocCommentBegin); StringRef AnnotatedDecl = StringRef(SS.begin()+DeclBegin, DeclEnd-DeclBegin); llvm::Optional<std::pair<unsigned, unsigned>> DeclarationLoc; StringRef Filename; getLocationInfo(VD, DeclarationLoc, Filename); if (DeclarationLoc.hasValue()) { DeclarationLoc = tryRemappingLocToLatestSnapshot(Lang, *DeclarationLoc, Filename, PreviousASTSnaps); if (!DeclarationLoc.hasValue()) return true; // failed to remap. } SmallVector<StringRef, 4> OverUSRs; for (auto Offs : OverUSROffs) { OverUSRs.push_back(StringRef(SS.begin()+Offs.first, Offs.second-Offs.first)); } SmallVector<StringRef, 4> AnnotatedRelatedDecls; for (auto Offs : RelDeclOffs) { AnnotatedRelatedDecls.push_back(StringRef(SS.begin() + Offs.first, Offs.second - Offs.first)); } bool IsSystem = VD->getModuleContext()->isSystemModule(); std::string TypeInterface; CursorInfo Info; Info.Kind = Kind; Info.Name = Name; Info.USR = USR; Info.TypeName = TypeName; Info.DocComment = DocComment; Info.AnnotatedDeclaration = AnnotatedDecl; Info.ModuleName = ModuleName; Info.ModuleInterfaceName = ModuleInterfaceName; Info.DeclarationLoc = DeclarationLoc; Info.Filename = Filename; Info.OverrideUSRs = OverUSRs; Info.AnnotatedRelatedDeclarations = AnnotatedRelatedDecls; Info.IsSystem = IsSystem; Info.TypeInteface = ASTPrinter::printTypeInterface(Ty, VD->getDeclContext(), TypeInterface) ? StringRef(TypeInterface) : StringRef(); Receiver(Info); return false; }
/// @brief Get the length of the string that represents @p num in Radix /// including the leading 0x or 0 for hexadecimal and octal respectively. static size_t getNumLengthAsString(uint64_t num) { APInt conv(64, num); SmallString<32> result; conv.toString(result, Radix, false, true); return result.size(); }
static MCSectionELF * selectELFSectionForGlobal(MCContext &Ctx, const GlobalValue *GV, SectionKind Kind, Mangler &Mang, const TargetMachine &TM, bool EmitUniqueSection, unsigned Flags, unsigned *NextUniqueID) { unsigned EntrySize = 0; if (Kind.isMergeableCString()) { if (Kind.isMergeable2ByteCString()) { EntrySize = 2; } else if (Kind.isMergeable4ByteCString()) { EntrySize = 4; } else { EntrySize = 1; assert(Kind.isMergeable1ByteCString() && "unknown string width"); } } else if (Kind.isMergeableConst()) { if (Kind.isMergeableConst4()) { EntrySize = 4; } else if (Kind.isMergeableConst8()) { EntrySize = 8; } else { assert(Kind.isMergeableConst16() && "unknown data width"); EntrySize = 16; } } StringRef Group = ""; if (const Comdat *C = getELFComdat(GV)) { Flags |= ELF::SHF_GROUP; Group = C->getName(); } bool UniqueSectionNames = TM.getUniqueSectionNames(); SmallString<128> Name; if (Kind.isMergeableCString()) { // We also need alignment here. // FIXME: this is getting the alignment of the character, not the // alignment of the global! unsigned Align = GV->getParent()->getDataLayout().getPreferredAlignment( cast<GlobalVariable>(GV)); std::string SizeSpec = ".rodata.str" + utostr(EntrySize) + "."; Name = SizeSpec + utostr(Align); } else if (Kind.isMergeableConst()) { Name = ".rodata.cst"; Name += utostr(EntrySize); } else { Name = getSectionPrefixForGlobal(Kind); } if (EmitUniqueSection && UniqueSectionNames) { Name.push_back('.'); TM.getNameWithPrefix(Name, GV, Mang, true); } unsigned UniqueID = ~0; if (EmitUniqueSection && !UniqueSectionNames) { UniqueID = *NextUniqueID; (*NextUniqueID)++; } return Ctx.getELFSection(Name, getELFSectionType(Name, Kind), Flags, EntrySize, Group, UniqueID); }
MCSymbol *MCContext::GetOrCreateSymbol(const Twine &Name) { SmallString<128> NameSV; Name.toVector(NameSV); return GetOrCreateSymbol(NameSV.str()); }
/// PasteTokens - Tok is the LHS of a ## operator, and CurToken is the ## /// operator. Read the ## and RHS, and paste the LHS/RHS together. If there /// are more ## after it, chomp them iteratively. Return the result as Tok. /// If this returns true, the caller should immediately return the token. bool TokenLexer::PasteTokens(Token &Tok) { SmallString<128> Buffer; const char *ResultTokStrPtr = nullptr; SourceLocation StartLoc = Tok.getLocation(); SourceLocation PasteOpLoc; do { // Consume the ## operator if any. PasteOpLoc = Tokens[CurToken].getLocation(); if (Tokens[CurToken].is(tok::hashhash)) ++CurToken; assert(!isAtEnd() && "No token on the RHS of a paste operator!"); // Get the RHS token. const Token &RHS = Tokens[CurToken]; // Allocate space for the result token. This is guaranteed to be enough for // the two tokens. Buffer.resize(Tok.getLength() + RHS.getLength()); // Get the spelling of the LHS token in Buffer. const char *BufPtr = &Buffer[0]; bool Invalid = false; unsigned LHSLen = PP.getSpelling(Tok, BufPtr, &Invalid); if (BufPtr != &Buffer[0]) // Really, we want the chars in Buffer! memcpy(&Buffer[0], BufPtr, LHSLen); if (Invalid) return true; BufPtr = Buffer.data() + LHSLen; unsigned RHSLen = PP.getSpelling(RHS, BufPtr, &Invalid); if (Invalid) return true; if (RHSLen && BufPtr != &Buffer[LHSLen]) // Really, we want the chars in Buffer! memcpy(&Buffer[LHSLen], BufPtr, RHSLen); // Trim excess space. Buffer.resize(LHSLen+RHSLen); // Plop the pasted result (including the trailing newline and null) into a // scratch buffer where we can lex it. Token ResultTokTmp; ResultTokTmp.startToken(); // Claim that the tmp token is a string_literal so that we can get the // character pointer back from CreateString in getLiteralData(). ResultTokTmp.setKind(tok::string_literal); PP.CreateString(Buffer, ResultTokTmp); SourceLocation ResultTokLoc = ResultTokTmp.getLocation(); ResultTokStrPtr = ResultTokTmp.getLiteralData(); // Lex the resultant pasted token into Result. Token Result; if (Tok.isAnyIdentifier() && RHS.isAnyIdentifier()) { // Common paste case: identifier+identifier = identifier. Avoid creating // a lexer and other overhead. PP.IncrementPasteCounter(true); Result.startToken(); Result.setKind(tok::raw_identifier); Result.setRawIdentifierData(ResultTokStrPtr); Result.setLocation(ResultTokLoc); Result.setLength(LHSLen+RHSLen); } else { PP.IncrementPasteCounter(false); assert(ResultTokLoc.isFileID() && "Should be a raw location into scratch buffer"); SourceManager &SourceMgr = PP.getSourceManager(); FileID LocFileID = SourceMgr.getFileID(ResultTokLoc); bool Invalid = false; const char *ScratchBufStart = SourceMgr.getBufferData(LocFileID, &Invalid).data(); if (Invalid) return false; // Make a lexer to lex this string from. Lex just this one token. // Make a lexer object so that we lex and expand the paste result. Lexer TL(SourceMgr.getLocForStartOfFile(LocFileID), PP.getLangOpts(), ScratchBufStart, ResultTokStrPtr, ResultTokStrPtr+LHSLen+RHSLen); // Lex a token in raw mode. This way it won't look up identifiers // automatically, lexing off the end will return an eof token, and // warnings are disabled. This returns true if the result token is the // entire buffer. bool isInvalid = !TL.LexFromRawLexer(Result); // If we got an EOF token, we didn't form even ONE token. For example, we // did "/ ## /" to get "//". isInvalid |= Result.is(tok::eof); // If pasting the two tokens didn't form a full new token, this is an // error. This occurs with "x ## +" and other stuff. Return with Tok // unmodified and with RHS as the next token to lex. if (isInvalid) { // Test for the Microsoft extension of /##/ turning into // here on the // error path. if (PP.getLangOpts().MicrosoftExt && Tok.is(tok::slash) && RHS.is(tok::slash)) { HandleMicrosoftCommentPaste(Tok); return true; } // Do not emit the error when preprocessing assembler code. if (!PP.getLangOpts().AsmPreprocessor) { // Explicitly convert the token location to have proper expansion // information so that the user knows where it came from. SourceManager &SM = PP.getSourceManager(); SourceLocation Loc = SM.createExpansionLoc(PasteOpLoc, ExpandLocStart, ExpandLocEnd, 2); // If we're in microsoft extensions mode, downgrade this from a hard // error to an extension that defaults to an error. This allows // disabling it. PP.Diag(Loc, PP.getLangOpts().MicrosoftExt ? diag::ext_pp_bad_paste_ms : diag::err_pp_bad_paste) << Buffer.str(); } // An error has occurred so exit loop. break; } // Turn ## into 'unknown' to avoid # ## # from looking like a paste // operator. if (Result.is(tok::hashhash)) Result.setKind(tok::unknown); } // Transfer properties of the LHS over the Result. Result.setFlagValue(Token::StartOfLine , Tok.isAtStartOfLine()); Result.setFlagValue(Token::LeadingSpace, Tok.hasLeadingSpace()); // Finally, replace LHS with the result, consume the RHS, and iterate. ++CurToken; Tok = Result; } while (!isAtEnd() && Tokens[CurToken].is(tok::hashhash)); SourceLocation EndLoc = Tokens[CurToken - 1].getLocation(); // The token's current location indicate where the token was lexed from. We // need this information to compute the spelling of the token, but any // diagnostics for the expanded token should appear as if the token was // expanded from the full ## expression. Pull this information together into // a new SourceLocation that captures all of this. SourceManager &SM = PP.getSourceManager(); if (StartLoc.isFileID()) StartLoc = getExpansionLocForMacroDefLoc(StartLoc); if (EndLoc.isFileID()) EndLoc = getExpansionLocForMacroDefLoc(EndLoc); FileID MacroFID = SM.getFileID(MacroExpansionStart); while (SM.getFileID(StartLoc) != MacroFID) StartLoc = SM.getImmediateExpansionRange(StartLoc).first; while (SM.getFileID(EndLoc) != MacroFID) EndLoc = SM.getImmediateExpansionRange(EndLoc).second; Tok.setLocation(SM.createExpansionLoc(Tok.getLocation(), StartLoc, EndLoc, Tok.getLength())); // Now that we got the result token, it will be subject to expansion. Since // token pasting re-lexes the result token in raw mode, identifier information // isn't looked up. As such, if the result is an identifier, look up id info. if (Tok.is(tok::raw_identifier)) { // Look up the identifier info for the token. We disabled identifier lookup // by saying we're skipping contents, so we need to do this manually. PP.LookUpIdentifierInfo(Tok); } return false; }
/// This method runs "Program", capturing the output of the program to a file, /// returning the filename of the file. A recommended filename may be /// optionally specified. Expected<std::string> BugDriver::executeProgram(const Module &Program, std::string OutputFile, std::string BitcodeFile, const std::string &SharedObj, AbstractInterpreter *AI) const { if (!AI) AI = Interpreter; assert(AI && "Interpreter should have been created already!"); if (BitcodeFile.empty()) { // Emit the program to a bitcode file... auto File = sys::fs::TempFile::create(OutputPrefix + "-test-program-%%%%%%%.bc"); if (!File) { errs() << ToolName << ": Error making unique filename: " << toString(File.takeError()) << "!\n"; exit(1); } DiscardTemp Discard{*File}; BitcodeFile = File->TmpName; if (writeProgramToFile(File->FD, Program)) { errs() << ToolName << ": Error emitting bitcode to file '" << BitcodeFile << "'!\n"; exit(1); } } if (OutputFile.empty()) OutputFile = OutputPrefix + "-execution-output-%%%%%%%"; // Check to see if this is a valid output filename... SmallString<128> UniqueFile; std::error_code EC = sys::fs::createUniqueFile(OutputFile, UniqueFile); if (EC) { errs() << ToolName << ": Error making unique filename: " << EC.message() << "\n"; exit(1); } OutputFile = UniqueFile.str(); // Figure out which shared objects to run, if any. std::vector<std::string> SharedObjs(AdditionalSOs); if (!SharedObj.empty()) SharedObjs.push_back(SharedObj); Expected<int> RetVal = AI->ExecuteProgram(BitcodeFile, InputArgv, InputFile, OutputFile, AdditionalLinkerArgs, SharedObjs, Timeout, MemoryLimit); if (Error E = RetVal.takeError()) return std::move(E); if (*RetVal == -1) { errs() << "<timeout>"; static bool FirstTimeout = true; if (FirstTimeout) { outs() << "\n" "*** Program execution timed out! This mechanism is designed to " "handle\n" " programs stuck in infinite loops gracefully. The -timeout " "option\n" " can be used to change the timeout threshold or disable it " "completely\n" " (with -timeout=0). This message is only displayed once.\n"; FirstTimeout = false; } } if (AppendProgramExitCode) { std::ofstream outFile(OutputFile.c_str(), std::ios_base::app); outFile << "exit " << *RetVal << '\n'; outFile.close(); } // Return the filename we captured the output to. return OutputFile; }
static std::string getImplibPath(StringRef Path) { SmallString<128> Out = StringRef("lib"); Out.append(Path); sys::path::replace_extension(Out, ".a"); return Out.str(); }
void llvm::write_double(raw_ostream &S, double N, FloatStyle Style, Optional<size_t> Precision) { size_t Prec = Precision.getValueOr(getDefaultPrecision(Style)); if (std::isnan(N)) { S << "nan"; return; } else if (std::isinf(N)) { S << "INF"; return; } char Letter; if (Style == FloatStyle::Exponent) Letter = 'e'; else if (Style == FloatStyle::ExponentUpper) Letter = 'E'; else Letter = 'f'; SmallString<8> Spec; llvm::raw_svector_ostream Out(Spec); Out << "%." << Prec << Letter; if (Style == FloatStyle::Exponent || Style == FloatStyle::ExponentUpper) { #ifdef _WIN32 // On MSVCRT and compatible, output of %e is incompatible to Posix // by default. Number of exponent digits should be at least 2. "%+03d" // FIXME: Implement our formatter to here or Support/Format.h! #if defined(__MINGW32__) // FIXME: It should be generic to C++11. if (N == 0.0 && std::signbit(N)) { char NegativeZero[] = "-0.000000e+00"; if (Style == FloatStyle::ExponentUpper) NegativeZero[strlen(NegativeZero) - 4] = 'E'; S << NegativeZero; return; } #else int fpcl = _fpclass(N); // negative zero if (fpcl == _FPCLASS_NZ) { char NegativeZero[] = "-0.000000e+00"; if (Style == FloatStyle::ExponentUpper) NegativeZero[strlen(NegativeZero) - 4] = 'E'; S << NegativeZero; return; } #endif char buf[32]; unsigned len; len = format(Spec.c_str(), N).snprint(buf, sizeof(buf)); if (len <= sizeof(buf) - 2) { if (len >= 5 && (buf[len - 5] == 'e' || buf[len - 5] == 'E') && buf[len - 3] == '0') { int cs = buf[len - 4]; if (cs == '+' || cs == '-') { int c1 = buf[len - 2]; int c0 = buf[len - 1]; if (isdigit(static_cast<unsigned char>(c1)) && isdigit(static_cast<unsigned char>(c0))) { // Trim leading '0': "...e+012" -> "...e+12\0" buf[len - 3] = c1; buf[len - 2] = c0; buf[--len] = 0; } } } S << buf; return; } #endif } if (Style == FloatStyle::Percent) N *= 100.0; char Buf[32]; format(Spec.c_str(), N).snprint(Buf, sizeof(Buf)); S << Buf; if (Style == FloatStyle::Percent) S << '%'; }
static MCSymbol *GetSymbolFromOperand(const MachineOperand &MO, AsmPrinter &AP){ const TargetMachine &TM = AP.TM; Mangler *Mang = AP.Mang; const DataLayout *DL = TM.getSubtargetImpl()->getDataLayout(); MCContext &Ctx = AP.OutContext; bool isDarwin = Triple(TM.getTargetTriple()).isOSDarwin(); SmallString<128> Name; StringRef Suffix; if (MO.getTargetFlags() == PPCII::MO_PLT_OR_STUB) { if (isDarwin) Suffix = "$stub"; } else if (MO.getTargetFlags() & PPCII::MO_NLP_FLAG) Suffix = "$non_lazy_ptr"; if (!Suffix.empty()) Name += DL->getPrivateGlobalPrefix(); unsigned PrefixLen = Name.size(); if (!MO.isGlobal()) { assert(MO.isSymbol() && "Isn't a symbol reference"); Mang->getNameWithPrefix(Name, MO.getSymbolName()); } else { const GlobalValue *GV = MO.getGlobal(); TM.getNameWithPrefix(Name, GV, *Mang); } unsigned OrigLen = Name.size() - PrefixLen; Name += Suffix; MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str()); StringRef OrigName = StringRef(Name).substr(PrefixLen, OrigLen); // If the target flags on the operand changes the name of the symbol, do that // before we return the symbol. if (MO.getTargetFlags() == PPCII::MO_PLT_OR_STUB && isDarwin) { MachineModuleInfoImpl::StubValueTy &StubSym = getMachOMMI(AP).getFnStubEntry(Sym); if (StubSym.getPointer()) return Sym; if (MO.isGlobal()) { StubSym = MachineModuleInfoImpl:: StubValueTy(AP.getSymbol(MO.getGlobal()), !MO.getGlobal()->hasInternalLinkage()); } else { StubSym = MachineModuleInfoImpl:: StubValueTy(Ctx.GetOrCreateSymbol(OrigName), false); } return Sym; } // If the symbol reference is actually to a non_lazy_ptr, not to the symbol, // then add the suffix. if (MO.getTargetFlags() & PPCII::MO_NLP_FLAG) { MachineModuleInfoMachO &MachO = getMachOMMI(AP); MachineModuleInfoImpl::StubValueTy &StubSym = (MO.getTargetFlags() & PPCII::MO_NLP_HIDDEN_FLAG) ? MachO.getHiddenGVStubEntry(Sym) : MachO.getGVStubEntry(Sym); if (!StubSym.getPointer()) { assert(MO.isGlobal() && "Extern symbol not handled yet"); StubSym = MachineModuleInfoImpl:: StubValueTy(AP.getSymbol(MO.getGlobal()), !MO.getGlobal()->hasInternalLinkage()); } return Sym; } return Sym; }
void MCELFStreamer::EmitInstToData(const MCInst &Inst) { MCAssembler &Assembler = getAssembler(); SmallVector<MCFixup, 4> Fixups; SmallString<256> Code; raw_svector_ostream VecOS(Code); Assembler.getEmitter().EncodeInstruction(Inst, VecOS, Fixups); VecOS.flush(); for (unsigned i = 0, e = Fixups.size(); i != e; ++i) fixSymbolsInTLSFixups(Fixups[i].getValue()); // There are several possibilities here: // // If bundling is disabled, append the encoded instruction to the current data // fragment (or create a new such fragment if the current fragment is not a // data fragment). // // If bundling is enabled: // - If we're not in a bundle-locked group, emit the instruction into a // fragment of its own. If there are no fixups registered for the // instruction, emit a MCCompactEncodedInstFragment. Otherwise, emit a // MCDataFragment. // - If we're in a bundle-locked group, append the instruction to the current // data fragment because we want all the instructions in a group to get into // the same fragment. Be careful not to do that for the first instruction in // the group, though. MCDataFragment *DF; if (Assembler.isBundlingEnabled()) { MCSectionData *SD = getCurrentSectionData(); if (SD->isBundleLocked() && !SD->isBundleGroupBeforeFirstInst()) // If we are bundle-locked, we re-use the current fragment. // The bundle-locking directive ensures this is a new data fragment. DF = cast<MCDataFragment>(getCurrentFragment()); else if (!SD->isBundleLocked() && Fixups.size() == 0) { // Optimize memory usage by emitting the instruction to a // MCCompactEncodedInstFragment when not in a bundle-locked group and // there are no fixups registered. MCCompactEncodedInstFragment *CEIF = new MCCompactEncodedInstFragment(); insert(CEIF); CEIF->getContents().append(Code.begin(), Code.end()); return; } else { DF = new MCDataFragment(); insert(DF); if (SD->getBundleLockState() == MCSectionData::BundleLockedAlignToEnd) { // If this is a new fragment created for a bundle-locked group, and the // group was marked as "align_to_end", set a flag in the fragment. DF->setAlignToBundleEnd(true); } } // We're now emitting an instruction in a bundle group, so this flag has // to be turned off. SD->setBundleGroupBeforeFirstInst(false); } else { DF = getOrCreateDataFragment(); } // Add the fixups and data. for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); DF->getFixups().push_back(Fixups[i]); } DF->setHasInstructions(true); DF->getContents().append(Code.begin(), Code.end()); }
void DereferenceChecker::reportBug(ProgramStateRef State, const Stmt *S, CheckerContext &C, bool IsBind) const { // Generate an error node. ExplodedNode *N = C.generateSink(State); if (!N) return; // We know that 'location' cannot be non-null. This is what // we call an "explicit" null dereference. if (!BT_null) BT_null.reset(new BuiltinBug("Dereference of null pointer")); SmallString<100> buf; SmallVector<SourceRange, 2> Ranges; // Walk through lvalue casts to get the original expression // that syntactically caused the load. if (const Expr *expr = dyn_cast<Expr>(S)) S = expr->IgnoreParenLValueCasts(); const MemRegion *sourceR = 0; if (IsBind) { if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(S)) { if (BO->isAssignmentOp()) S = BO->getRHS(); } else if (const DeclStmt *DS = dyn_cast<DeclStmt>(S)) { assert(DS->isSingleDecl() && "We process decls one by one"); if (const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl())) if (const Expr *Init = VD->getAnyInitializer()) S = Init; } } switch (S->getStmtClass()) { case Stmt::ArraySubscriptExprClass: { llvm::raw_svector_ostream os(buf); os << "Array access"; const ArraySubscriptExpr *AE = cast<ArraySubscriptExpr>(S); sourceR = AddDerefSource(os, Ranges, AE->getBase()->IgnoreParenCasts(), State.getPtr(), N->getLocationContext()); os << " results in a null pointer dereference"; break; } case Stmt::UnaryOperatorClass: { llvm::raw_svector_ostream os(buf); os << "Dereference of null pointer"; const UnaryOperator *U = cast<UnaryOperator>(S); sourceR = AddDerefSource(os, Ranges, U->getSubExpr()->IgnoreParens(), State.getPtr(), N->getLocationContext(), true); break; } case Stmt::MemberExprClass: { const MemberExpr *M = cast<MemberExpr>(S); if (M->isArrow()) { llvm::raw_svector_ostream os(buf); os << "Access to field '" << M->getMemberNameInfo() << "' results in a dereference of a null pointer"; sourceR = AddDerefSource(os, Ranges, M->getBase()->IgnoreParenCasts(), State.getPtr(), N->getLocationContext(), true); } break; } case Stmt::ObjCIvarRefExprClass: { const ObjCIvarRefExpr *IV = cast<ObjCIvarRefExpr>(S); if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(IV->getBase()->IgnoreParenCasts())) { if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { llvm::raw_svector_ostream os(buf); os << "Instance variable access (via '" << VD->getName() << "') results in a null pointer dereference"; } } Ranges.push_back(IV->getSourceRange()); break; } default: break; } BugReport *report = new BugReport(*BT_null, buf.empty() ? BT_null->getDescription() : buf.str(), N); bugreporter::trackNullOrUndefValue(N, bugreporter::GetDerefExpr(N), *report); for (SmallVectorImpl<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end(); I!=E; ++I) report->addRange(*I); if (sourceR) { report->markInteresting(sourceR); report->markInteresting(State->getRawSVal(loc::MemRegionVal(sourceR))); } C.EmitReport(report); }
void GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) { using namespace llvm; // Emit the file header. Stream.Emit((unsigned)'B', 8); Stream.Emit((unsigned)'C', 8); Stream.Emit((unsigned)'G', 8); Stream.Emit((unsigned)'I', 8); // Write the block-info block, which describes the records in this bitcode // file. emitBlockInfoBlock(Stream); Stream.EnterSubblock(GLOBAL_INDEX_BLOCK_ID, 3); // Write the metadata. SmallVector<uint64_t, 2> Record; Record.push_back(CurrentVersion); Stream.EmitRecord(INDEX_METADATA, Record); // Write the set of known module files. for (ModuleFilesMap::iterator M = ModuleFiles.begin(), MEnd = ModuleFiles.end(); M != MEnd; ++M) { Record.clear(); Record.push_back(M->second.ID); Record.push_back(M->first->getSize()); Record.push_back(M->first->getModificationTime()); // File name StringRef Name(M->first->getName()); Record.push_back(Name.size()); Record.append(Name.begin(), Name.end()); // Dependencies Record.push_back(M->second.Dependencies.size()); Record.append(M->second.Dependencies.begin(), M->second.Dependencies.end()); Stream.EmitRecord(MODULE, Record); } // Write the identifier -> module file mapping. { OnDiskChainedHashTableGenerator<IdentifierIndexWriterTrait> Generator; IdentifierIndexWriterTrait Trait; // Populate the hash table. for (InterestingIdentifierMap::iterator I = InterestingIdentifiers.begin(), IEnd = InterestingIdentifiers.end(); I != IEnd; ++I) { Generator.insert(I->first(), I->second, Trait); } // Create the on-disk hash table in a buffer. SmallString<4096> IdentifierTable; uint32_t BucketOffset; { llvm::raw_svector_ostream Out(IdentifierTable); // Make sure that no bucket is at offset 0 clang::io::Emit32(Out, 0); BucketOffset = Generator.Emit(Out, Trait); } // Create a blob abbreviation BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_INDEX)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned IDTableAbbrev = Stream.EmitAbbrev(Abbrev); // Write the identifier table Record.clear(); Record.push_back(IDENTIFIER_INDEX); Record.push_back(BucketOffset); Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable.str()); } Stream.ExitBlock(); }
/// GetSymbolFromOperand - Lower an MO_GlobalAddress or MO_ExternalSymbol /// operand to an MCSymbol. MCSymbol *X86MCInstLower:: GetSymbolFromOperand(const MachineOperand &MO) const { assert((MO.isGlobal() || MO.isSymbol()) && "Isn't a symbol reference"); SmallString<128> Name; if (!MO.isGlobal()) { assert(MO.isSymbol()); Name += AsmPrinter.MAI->getGlobalPrefix(); Name += MO.getSymbolName(); } else { const GlobalValue *GV = MO.getGlobal(); bool isImplicitlyPrivate = false; if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB || MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY || MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE || MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE) isImplicitlyPrivate = true; Mang->getNameWithPrefix(Name, GV, isImplicitlyPrivate); } // If the target flags on the operand changes the name of the symbol, do that // before we return the symbol. switch (MO.getTargetFlags()) { default: break; case X86II::MO_DLLIMPORT: { // Handle dllimport linkage. const char *Prefix = "__imp_"; Name.insert(Name.begin(), Prefix, Prefix+strlen(Prefix)); break; } case X86II::MO_DARWIN_NONLAZY: case X86II::MO_DARWIN_NONLAZY_PIC_BASE: { Name += "$non_lazy_ptr"; MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str()); MachineModuleInfoImpl::StubValueTy &StubSym = getMachOMMI().getGVStubEntry(Sym); if (StubSym.getPointer() == 0) { assert(MO.isGlobal() && "Extern symbol not handled yet"); StubSym = MachineModuleInfoImpl:: StubValueTy(AsmPrinter.Mang->getSymbol(MO.getGlobal()), !MO.getGlobal()->hasInternalLinkage()); } return Sym; } case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: { Name += "$non_lazy_ptr"; MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str()); MachineModuleInfoImpl::StubValueTy &StubSym = getMachOMMI().getHiddenGVStubEntry(Sym); if (StubSym.getPointer() == 0) { assert(MO.isGlobal() && "Extern symbol not handled yet"); StubSym = MachineModuleInfoImpl:: StubValueTy(AsmPrinter.Mang->getSymbol(MO.getGlobal()), !MO.getGlobal()->hasInternalLinkage()); } return Sym; } case X86II::MO_DARWIN_STUB: { Name += "$stub"; MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str()); MachineModuleInfoImpl::StubValueTy &StubSym = getMachOMMI().getFnStubEntry(Sym); if (StubSym.getPointer()) return Sym; if (MO.isGlobal()) { StubSym = MachineModuleInfoImpl:: StubValueTy(AsmPrinter.Mang->getSymbol(MO.getGlobal()), !MO.getGlobal()->hasInternalLinkage()); } else { Name.erase(Name.end()-5, Name.end()); StubSym = MachineModuleInfoImpl:: StubValueTy(Ctx.GetOrCreateSymbol(Name.str()), false); } return Sym; } } return Ctx.GetOrCreateSymbol(Name.str()); }
bool FrontendAction::BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input) { assert(!Instance && "Already processing a source file!"); assert(!Input.isEmpty() && "Unexpected empty filename!"); setCurrentInput(Input); setCompilerInstance(&CI); StringRef InputFile = Input.getFile(); bool HasBegunSourceFile = false; if (!BeginInvocation(CI)) goto failure; // AST files follow a very different path, since they share objects via the // AST unit. if (Input.getKind() == IK_AST) { assert(!usesPreprocessorOnly() && "Attempt to pass AST file to preprocessor only action!"); assert(hasASTFileSupport() && "This action does not have AST file support!"); IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics()); ASTUnit *AST = ASTUnit::LoadFromASTFile(InputFile, Diags, CI.getFileSystemOpts()); if (!AST) goto failure; setCurrentInput(Input, AST); // Inform the diagnostic client we are processing a source file. CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 0); HasBegunSourceFile = true; // Set the shared objects, these are reset when we finish processing the // file, otherwise the CompilerInstance will happily destroy them. CI.setFileManager(&AST->getFileManager()); CI.setSourceManager(&AST->getSourceManager()); CI.setPreprocessor(&AST->getPreprocessor()); CI.setASTContext(&AST->getASTContext()); // Initialize the action. if (!BeginSourceFileAction(CI, InputFile)) goto failure; // Create the AST consumer. CI.setASTConsumer(CreateWrappedASTConsumer(CI, InputFile)); if (!CI.hasASTConsumer()) goto failure; return true; } // Set up the file and source managers, if needed. if (!CI.hasFileManager()) CI.createFileManager(); if (!CI.hasSourceManager()) CI.createSourceManager(CI.getFileManager()); // IR files bypass the rest of initialization. if (Input.getKind() == IK_LLVM_IR) { assert(hasIRSupport() && "This action does not have IR file support!"); // Inform the diagnostic client we are processing a source file. CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 0); HasBegunSourceFile = true; // Initialize the action. if (!BeginSourceFileAction(CI, InputFile)) goto failure; return true; } // If the implicit PCH include is actually a directory, rather than // a single file, search for a suitable PCH file in that directory. if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { FileManager &FileMgr = CI.getFileManager(); PreprocessorOptions &PPOpts = CI.getPreprocessorOpts(); StringRef PCHInclude = PPOpts.ImplicitPCHInclude; if (const DirectoryEntry *PCHDir = FileMgr.getDirectory(PCHInclude)) { llvm::error_code EC; SmallString<128> DirNative; llvm::sys::path::native(PCHDir->getName(), DirNative); bool Found = false; for (llvm::sys::fs::directory_iterator Dir(DirNative.str(), EC), DirEnd; Dir != DirEnd && !EC; Dir.increment(EC)) { // Check whether this is an acceptable AST file. if (ASTReader::isAcceptableASTFile(Dir->path(), FileMgr, CI.getLangOpts(), CI.getTargetOpts(), CI.getPreprocessorOpts())) { PPOpts.ImplicitPCHInclude = Dir->path(); Found = true; break; } } if (!Found) { CI.getDiagnostics().Report(diag::err_fe_no_pch_in_dir) << PCHInclude; return true; } } } // Set up the preprocessor. CI.createPreprocessor(); // Inform the diagnostic client we are processing a source file. CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), &CI.getPreprocessor()); HasBegunSourceFile = true; // Initialize the action. if (!BeginSourceFileAction(CI, InputFile)) goto failure; // Create the AST context and consumer unless this is a preprocessor only // action. if (!usesPreprocessorOnly()) { CI.createASTContext(); OwningPtr<ASTConsumer> Consumer( CreateWrappedASTConsumer(CI, InputFile)); if (!Consumer) goto failure; CI.getASTContext().setASTMutationListener(Consumer->GetASTMutationListener()); if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) { // Convert headers to PCH and chain them. OwningPtr<ExternalASTSource> source; source.reset(ChainedIncludesSource::create(CI)); if (!source) goto failure; CI.setModuleManager(static_cast<ASTReader*>( &static_cast<ChainedIncludesSource*>(source.get())->getFinalReader())); CI.getASTContext().setExternalSource(source); } else if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { // Use PCH. assert(hasPCHSupport() && "This action does not have PCH support!"); ASTDeserializationListener *DeserialListener = Consumer->GetASTDeserializationListener(); if (CI.getPreprocessorOpts().DumpDeserializedPCHDecls) DeserialListener = new DeserializedDeclsDumper(DeserialListener); if (!CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn.empty()) DeserialListener = new DeserializedDeclsChecker(CI.getASTContext(), CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn, DeserialListener); CI.createPCHExternalASTSource( CI.getPreprocessorOpts().ImplicitPCHInclude, CI.getPreprocessorOpts().DisablePCHValidation, CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, DeserialListener); if (!CI.getASTContext().getExternalSource()) goto failure; } CI.setASTConsumer(Consumer.take()); if (!CI.hasASTConsumer()) goto failure; } // Initialize built-in info as long as we aren't using an external AST // source. if (!CI.hasASTContext() || !CI.getASTContext().getExternalSource()) { Preprocessor &PP = CI.getPreprocessor(); PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(), PP.getLangOpts()); } // If there is a layout overrides file, attach an external AST source that // provides the layouts from that file. if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() && CI.hasASTContext() && !CI.getASTContext().getExternalSource()) { OwningPtr<ExternalASTSource> Override(new LayoutOverrideSource( CI.getFrontendOpts().OverrideRecordLayoutsFile)); CI.getASTContext().setExternalSource(Override); } return true; // If we failed, reset state since the client will not end up calling the // matching EndSourceFile(). failure: if (isCurrentFileAST()) { CI.setASTContext(0); CI.setPreprocessor(0); CI.setSourceManager(0); CI.setFileManager(0); } if (HasBegunSourceFile) CI.getDiagnosticClient().EndSourceFile(); CI.clearOutputFiles(/*EraseFiles=*/true); setCurrentInput(FrontendInputFile()); setCompilerInstance(0); return false; }
/// \brief returns a printable representation of first item from input range /// /// This function returns a printable representation of the next item in a line /// of source. If the next byte begins a valid and printable character, that /// character is returned along with 'true'. /// /// Otherwise, if the next byte begins a valid, but unprintable character, a /// printable, escaped representation of the character is returned, along with /// 'false'. Otherwise a printable, escaped representation of the next byte /// is returned along with 'false'. /// /// \note The index is updated to be used with a subsequent call to /// printableTextForNextCharacter. /// /// \param SourceLine The line of source /// \param i Pointer to byte index, /// \param TabStop used to expand tabs /// \return pair(printable text, 'true' iff original text was printable) /// static std::pair<SmallString<16>, bool> printableTextForNextCharacter(StringRef SourceLine, size_t *i, unsigned TabStop) { assert(i && "i must not be null"); assert(*i<SourceLine.size() && "must point to a valid index"); if (SourceLine[*i]=='\t') { assert(0 < TabStop && TabStop <= DiagnosticOptions::MaxTabStop && "Invalid -ftabstop value"); unsigned col = bytesSincePreviousTabOrLineBegin(SourceLine, *i); unsigned NumSpaces = TabStop - col%TabStop; assert(0 < NumSpaces && NumSpaces <= TabStop && "Invalid computation of space amt"); ++(*i); SmallString<16> expandedTab; expandedTab.assign(NumSpaces, ' '); return std::make_pair(expandedTab, true); } // FIXME: this data is copied from the private implementation of ConvertUTF.h static const char trailingBytesForUTF8[256] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 }; unsigned char const *begin, *end; begin = reinterpret_cast<unsigned char const *>(&*(SourceLine.begin() + *i)); end = begin + SourceLine.size(); if (isLegalUTF8Sequence(begin, end)) { UTF32 c; UTF32 *cptr = &c; unsigned char const *original_begin = begin; char trailingBytes = trailingBytesForUTF8[(unsigned char)SourceLine[*i]]; unsigned char const *cp_end = begin+trailingBytes+1; ConversionResult res = ConvertUTF8toUTF32(&begin, cp_end, &cptr, cptr+1, strictConversion); (void)res; assert(conversionOK==res); assert(0 < begin-original_begin && "we must be further along in the string now"); *i += begin-original_begin; if (!llvm::sys::locale::isPrint(c)) { // If next character is valid UTF-8, but not printable SmallString<16> expandedCP("<U+>"); while (c) { expandedCP.insert(expandedCP.begin()+3, llvm::hexdigit(c%16)); c/=16; } while (expandedCP.size() < 8) expandedCP.insert(expandedCP.begin()+3, llvm::hexdigit(0)); return std::make_pair(expandedCP, false); } // If next character is valid UTF-8, and printable return std::make_pair(SmallString<16>(original_begin, cp_end), true); } // If next byte is not valid UTF-8 (and therefore not printable) SmallString<16> expandedByte("<XX>"); unsigned char byte = SourceLine[*i]; expandedByte[1] = llvm::hexdigit(byte / 16); expandedByte[2] = llvm::hexdigit(byte % 16); ++(*i); return std::make_pair(expandedByte, false); }
/// DoFrameworkLookup - Do a lookup of the specified file in the current /// DirectoryLookup, which is a framework directory. const FileEntry *DirectoryLookup::DoFrameworkLookup( StringRef Filename, HeaderSearch &HS, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, ModuleMap::KnownHeader *SuggestedModule, bool &InUserSpecifiedSystemFramework) const { FileManager &FileMgr = HS.getFileMgr(); // Framework names must have a '/' in the filename. size_t SlashPos = Filename.find('/'); if (SlashPos == StringRef::npos) return nullptr; // Find out if this is the home for the specified framework, by checking // HeaderSearch. Possible answers are yes/no and unknown. HeaderSearch::FrameworkCacheEntry &CacheEntry = HS.LookupFrameworkCache(Filename.substr(0, SlashPos)); // If it is known and in some other directory, fail. if (CacheEntry.Directory && CacheEntry.Directory != getFrameworkDir()) return nullptr; // Otherwise, construct the path to this framework dir. // FrameworkName = "/System/Library/Frameworks/" SmallString<1024> FrameworkName; FrameworkName += getFrameworkDir()->getName(); if (FrameworkName.empty() || FrameworkName.back() != '/') FrameworkName.push_back('/'); // FrameworkName = "/System/Library/Frameworks/Cocoa" StringRef ModuleName(Filename.begin(), SlashPos); FrameworkName += ModuleName; // FrameworkName = "/System/Library/Frameworks/Cocoa.framework/" FrameworkName += ".framework/"; // If the cache entry was unresolved, populate it now. if (!CacheEntry.Directory) { HS.IncrementFrameworkLookupCount(); // If the framework dir doesn't exist, we fail. const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkName); if (!Dir) return nullptr; // Otherwise, if it does, remember that this is the right direntry for this // framework. CacheEntry.Directory = getFrameworkDir(); // If this is a user search directory, check if the framework has been // user-specified as a system framework. if (getDirCharacteristic() == SrcMgr::C_User) { SmallString<1024> SystemFrameworkMarker(FrameworkName); SystemFrameworkMarker += ".system_framework"; if (llvm::sys::fs::exists(SystemFrameworkMarker)) { CacheEntry.IsUserSpecifiedSystemFramework = true; } } } // Set the 'user-specified system framework' flag. InUserSpecifiedSystemFramework = CacheEntry.IsUserSpecifiedSystemFramework; if (RelativePath) { RelativePath->clear(); RelativePath->append(Filename.begin()+SlashPos+1, Filename.end()); } // Check "/System/Library/Frameworks/Cocoa.framework/Headers/file.h" unsigned OrigSize = FrameworkName.size(); FrameworkName += "Headers/"; if (SearchPath) { SearchPath->clear(); // Without trailing '/'. SearchPath->append(FrameworkName.begin(), FrameworkName.end()-1); } FrameworkName.append(Filename.begin()+SlashPos+1, Filename.end()); const FileEntry *FE = FileMgr.getFile(FrameworkName, /*openFile=*/!SuggestedModule); if (!FE) { // Check "/System/Library/Frameworks/Cocoa.framework/PrivateHeaders/file.h" const char *Private = "Private"; FrameworkName.insert(FrameworkName.begin()+OrigSize, Private, Private+strlen(Private)); if (SearchPath) SearchPath->insert(SearchPath->begin()+OrigSize, Private, Private+strlen(Private)); FE = FileMgr.getFile(FrameworkName, /*openFile=*/!SuggestedModule); } // If we found the header and are allowed to suggest a module, do so now. if (FE && SuggestedModule) { // Find the framework in which this header occurs. StringRef FrameworkPath = FE->getDir()->getName(); bool FoundFramework = false; do { // Determine whether this directory exists. const DirectoryEntry *Dir = FileMgr.getDirectory(FrameworkPath); if (!Dir) break; // If this is a framework directory, then we're a subframework of this // framework. if (llvm::sys::path::extension(FrameworkPath) == ".framework") { FoundFramework = true; break; } // Get the parent directory name. FrameworkPath = llvm::sys::path::parent_path(FrameworkPath); if (FrameworkPath.empty()) break; } while (true); if (FoundFramework) { // Find the top-level framework based on this framework. SmallVector<std::string, 4> SubmodulePath; const DirectoryEntry *TopFrameworkDir = ::getTopFrameworkDir(FileMgr, FrameworkPath, SubmodulePath); // Determine the name of the top-level framework. StringRef ModuleName = llvm::sys::path::stem(TopFrameworkDir->getName()); // Load this framework module. If that succeeds, find the suggested module // for this header, if any. bool IsSystem = getDirCharacteristic() != SrcMgr::C_User; if (HS.loadFrameworkModule(ModuleName, TopFrameworkDir, IsSystem)) { *SuggestedModule = HS.findModuleForHeader(FE); } } else { *SuggestedModule = HS.findModuleForHeader(FE); } } return FE; }
// Get the location to use for Visual Studio binaries. The location priority // is: %VCINSTALLDIR% > %PATH% > newest copy of Visual Studio installed on // system (as reported by the registry). bool MSVCToolChain::getVisualStudioBinariesFolder(const char *clangProgramPath, std::string &path) const { path.clear(); SmallString<128> BinDir; // First check the environment variables that vsvars32.bat sets. llvm::Optional<std::string> VcInstallDir = llvm::sys::Process::GetEnv("VCINSTALLDIR"); if (VcInstallDir.hasValue()) { BinDir = VcInstallDir.getValue(); llvm::sys::path::append(BinDir, "bin"); } else { // Next walk the PATH, trying to find a cl.exe in the path. If we find one, // use that. However, make sure it's not clang's cl.exe. llvm::Optional<std::string> OptPath = llvm::sys::Process::GetEnv("PATH"); if (OptPath.hasValue()) { const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'}; SmallVector<StringRef, 8> PathSegments; llvm::SplitString(OptPath.getValue(), PathSegments, EnvPathSeparatorStr); for (StringRef PathSegment : PathSegments) { if (PathSegment.empty()) continue; SmallString<128> FilePath(PathSegment); llvm::sys::path::append(FilePath, "cl.exe"); if (llvm::sys::fs::can_execute(FilePath.c_str()) && !llvm::sys::fs::equivalent(FilePath.c_str(), clangProgramPath)) { // If we found it on the PATH, use it exactly as is with no // modifications. path = PathSegment; return true; } } } std::string installDir; // With no VCINSTALLDIR and nothing on the PATH, if we can't find it in the // registry then we have no choice but to fail. if (!getVisualStudioInstallDir(installDir)) return false; // Regardless of what binary we're ultimately trying to find, we make sure // that this is a Visual Studio directory by checking for cl.exe. We use // cl.exe instead of other binaries like link.exe because programs such as // GnuWin32 also have a utility called link.exe, so cl.exe is the least // ambiguous. BinDir = installDir; llvm::sys::path::append(BinDir, "VC", "bin"); SmallString<128> ClPath(BinDir); llvm::sys::path::append(ClPath, "cl.exe"); if (!llvm::sys::fs::can_execute(ClPath.c_str())) return false; } if (BinDir.empty()) return false; switch (getArch()) { case llvm::Triple::x86: break; case llvm::Triple::x86_64: llvm::sys::path::append(BinDir, "amd64"); break; case llvm::Triple::arm: llvm::sys::path::append(BinDir, "arm"); break; default: // Whatever this is, Visual Studio doesn't have a toolchain for it. return false; } path = BinDir.str(); return true; }
/// LookupFile - Given a "foo" or \<foo> reference, look up the indicated file, /// return null on failure. isAngled indicates whether the file reference is /// for system \#include's or not (i.e. using <> instead of ""). Includers, if /// non-empty, indicates where the \#including file(s) are, in case a relative /// search is needed. Microsoft mode will pass all \#including files. const FileEntry *HeaderSearch::LookupFile( StringRef Filename, SourceLocation IncludeLoc, bool isAngled, const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir, ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, ModuleMap::KnownHeader *SuggestedModule, bool SkipCache) { if (SuggestedModule) *SuggestedModule = ModuleMap::KnownHeader(); // If 'Filename' is absolute, check to see if it exists and no searching. if (llvm::sys::path::is_absolute(Filename)) { CurDir = nullptr; // If this was an #include_next "/absolute/file", fail. if (FromDir) return nullptr; if (SearchPath) SearchPath->clear(); if (RelativePath) { RelativePath->clear(); RelativePath->append(Filename.begin(), Filename.end()); } // Otherwise, just return the file. return FileMgr.getFile(Filename, /*openFile=*/true); } // This is the header that MSVC's header search would have found. const FileEntry *MSFE = nullptr; ModuleMap::KnownHeader MSSuggestedModule; // Unless disabled, check to see if the file is in the #includer's // directory. This cannot be based on CurDir, because each includer could be // a #include of a subdirectory (#include "foo/bar.h") and a subsequent // include of "baz.h" should resolve to "whatever/foo/baz.h". // This search is not done for <> headers. if (!Includers.empty() && !isAngled && !NoCurDirSearch) { SmallString<1024> TmpDir; bool First = true; for (const auto &IncluderAndDir : Includers) { const FileEntry *Includer = IncluderAndDir.first; // Concatenate the requested file onto the directory. // FIXME: Portability. Filename concatenation should be in sys::Path. TmpDir = IncluderAndDir.second->getName(); TmpDir.push_back('/'); TmpDir.append(Filename.begin(), Filename.end()); // FIXME: We don't cache the result of getFileInfo across the call to // getFileAndSuggestModule, because it's a reference to an element of // a container that could be reallocated across this call. // // FIXME: If we have no includer, that means we're processing a #include // from a module build. We should treat this as a system header if we're // building a [system] module. bool IncluderIsSystemHeader = Includer && getFileInfo(Includer).DirInfo != SrcMgr::C_User; if (const FileEntry *FE = getFileAndSuggestModule( *this, TmpDir, IncluderAndDir.second, IncluderIsSystemHeader, SuggestedModule)) { if (!Includer) { assert(First && "only first includer can have no file"); return FE; } // Leave CurDir unset. // This file is a system header or C++ unfriendly if the old file is. // // Note that we only use one of FromHFI/ToHFI at once, due to potential // reallocation of the underlying vector potentially making the first // reference binding dangling. HeaderFileInfo &FromHFI = getFileInfo(Includer); unsigned DirInfo = FromHFI.DirInfo; bool IndexHeaderMapHeader = FromHFI.IndexHeaderMapHeader; StringRef Framework = FromHFI.Framework; HeaderFileInfo &ToHFI = getFileInfo(FE); ToHFI.DirInfo = DirInfo; ToHFI.IndexHeaderMapHeader = IndexHeaderMapHeader; ToHFI.Framework = Framework; if (SearchPath) { StringRef SearchPathRef(IncluderAndDir.second->getName()); SearchPath->clear(); SearchPath->append(SearchPathRef.begin(), SearchPathRef.end()); } if (RelativePath) { RelativePath->clear(); RelativePath->append(Filename.begin(), Filename.end()); } if (First) return FE; // Otherwise, we found the path via MSVC header search rules. If // -Wmsvc-include is enabled, we have to keep searching to see if we // would've found this header in -I or -isystem directories. if (Diags.isIgnored(diag::ext_pp_include_search_ms, IncludeLoc)) { return FE; } else { MSFE = FE; if (SuggestedModule) { MSSuggestedModule = *SuggestedModule; *SuggestedModule = ModuleMap::KnownHeader(); } break; } } First = false; } } CurDir = nullptr; // If this is a system #include, ignore the user #include locs. unsigned i = isAngled ? AngledDirIdx : 0; // If this is a #include_next request, start searching after the directory the // file was found in. if (FromDir) i = FromDir-&SearchDirs[0]; // Cache all of the lookups performed by this method. Many headers are // multiply included, and the "pragma once" optimization prevents them from // being relex/pp'd, but they would still have to search through a // (potentially huge) series of SearchDirs to find it. LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename]; // If the entry has been previously looked up, the first value will be // non-zero. If the value is equal to i (the start point of our search), then // this is a matching hit. if (!SkipCache && CacheLookup.StartIdx == i+1) { // Skip querying potentially lots of directories for this lookup. i = CacheLookup.HitIdx; if (CacheLookup.MappedName) Filename = CacheLookup.MappedName; } else { // Otherwise, this is the first query, or the previous query didn't match // our search start. We will fill in our found location below, so prime the // start point value. CacheLookup.reset(/*StartIdx=*/i+1); } SmallString<64> MappedName; // Check each directory in sequence to see if it contains this file. for (; i != SearchDirs.size(); ++i) { bool InUserSpecifiedSystemFramework = false; bool HasBeenMapped = false; const FileEntry *FE = SearchDirs[i].LookupFile(Filename, *this, SearchPath, RelativePath, SuggestedModule, InUserSpecifiedSystemFramework, HasBeenMapped, MappedName); if (HasBeenMapped) { CacheLookup.MappedName = copyString(Filename, LookupFileCache.getAllocator()); } if (!FE) continue; CurDir = &SearchDirs[i]; // This file is a system header or C++ unfriendly if the dir is. HeaderFileInfo &HFI = getFileInfo(FE); HFI.DirInfo = CurDir->getDirCharacteristic(); // If the directory characteristic is User but this framework was // user-specified to be treated as a system framework, promote the // characteristic. if (HFI.DirInfo == SrcMgr::C_User && InUserSpecifiedSystemFramework) HFI.DirInfo = SrcMgr::C_System; // If the filename matches a known system header prefix, override // whether the file is a system header. for (unsigned j = SystemHeaderPrefixes.size(); j; --j) { if (Filename.startswith(SystemHeaderPrefixes[j-1].first)) { HFI.DirInfo = SystemHeaderPrefixes[j-1].second ? SrcMgr::C_System : SrcMgr::C_User; break; } } // If this file is found in a header map and uses the framework style of // includes, then this header is part of a framework we're building. if (CurDir->isIndexHeaderMap()) { size_t SlashPos = Filename.find('/'); if (SlashPos != StringRef::npos) { HFI.IndexHeaderMapHeader = 1; HFI.Framework = getUniqueFrameworkName(StringRef(Filename.begin(), SlashPos)); } } if (checkMSVCHeaderSearch(Diags, MSFE, FE, IncludeLoc)) { if (SuggestedModule) *SuggestedModule = MSSuggestedModule; return MSFE; } // Remember this location for the next lookup we do. CacheLookup.HitIdx = i; return FE; } // If we are including a file with a quoted include "foo.h" from inside // a header in a framework that is currently being built, and we couldn't // resolve "foo.h" any other way, change the include to <Foo/foo.h>, where // "Foo" is the name of the framework in which the including header was found. if (!Includers.empty() && Includers.front().first && !isAngled && Filename.find('/') == StringRef::npos) { HeaderFileInfo &IncludingHFI = getFileInfo(Includers.front().first); if (IncludingHFI.IndexHeaderMapHeader) { SmallString<128> ScratchFilename; ScratchFilename += IncludingHFI.Framework; ScratchFilename += '/'; ScratchFilename += Filename; const FileEntry *FE = LookupFile( ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir, CurDir, Includers.front(), SearchPath, RelativePath, SuggestedModule); if (checkMSVCHeaderSearch(Diags, MSFE, FE, IncludeLoc)) { if (SuggestedModule) *SuggestedModule = MSSuggestedModule; return MSFE; } LookupFileCacheInfo &CacheLookup = LookupFileCache[Filename]; CacheLookup.HitIdx = LookupFileCache[ScratchFilename].HitIdx; // FIXME: SuggestedModule. return FE; } } if (checkMSVCHeaderSearch(Diags, MSFE, nullptr, IncludeLoc)) { if (SuggestedModule) *SuggestedModule = MSSuggestedModule; return MSFE; } // Otherwise, didn't find it. Remember we didn't find this. CacheLookup.HitIdx = SearchDirs.size(); return nullptr; }
/// printSymbolOperand - Print a raw symbol reference operand. This handles /// jump tables, constant pools, global address and external symbols, all of /// which print to a label with various suffixes for relocation types etc. void X86AsmPrinter::printSymbolOperand(const MachineOperand &MO, raw_ostream &O) { switch (MO.getType()) { default: llvm_unreachable("unknown symbol type!"); case MachineOperand::MO_JumpTableIndex: O << *GetJTISymbol(MO.getIndex()); break; case MachineOperand::MO_ConstantPoolIndex: O << *GetCPISymbol(MO.getIndex()); printOffset(MO.getOffset(), O); break; case MachineOperand::MO_GlobalAddress: { const GlobalValue *GV = MO.getGlobal(); MCSymbol *GVSym; if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) GVSym = GetSymbolWithGlobalValueBase(GV, "$stub"); else if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY || MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE || MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE) GVSym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); else GVSym = Mang->getSymbol(GV); // Handle dllimport linkage. if (MO.getTargetFlags() == X86II::MO_DLLIMPORT) GVSym = OutContext.GetOrCreateSymbol(Twine("__imp_") + GVSym->getName()); if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY || MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE) { MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); MachineModuleInfoImpl::StubValueTy &StubSym = MMI->getObjFileInfo<MachineModuleInfoMachO>().getGVStubEntry(Sym); if (StubSym.getPointer() == 0) StubSym = MachineModuleInfoImpl:: StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage()); } else if (MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE){ MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); MachineModuleInfoImpl::StubValueTy &StubSym = MMI->getObjFileInfo<MachineModuleInfoMachO>().getHiddenGVStubEntry(Sym); if (StubSym.getPointer() == 0) StubSym = MachineModuleInfoImpl:: StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage()); } else if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) { MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$stub"); MachineModuleInfoImpl::StubValueTy &StubSym = MMI->getObjFileInfo<MachineModuleInfoMachO>().getFnStubEntry(Sym); if (StubSym.getPointer() == 0) StubSym = MachineModuleInfoImpl:: StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage()); } // If the name begins with a dollar-sign, enclose it in parens. We do this // to avoid having it look like an integer immediate to the assembler. if (GVSym->getName()[0] != '$') O << *GVSym; else O << '(' << *GVSym << ')'; printOffset(MO.getOffset(), O); break; } case MachineOperand::MO_ExternalSymbol: { const MCSymbol *SymToPrint; if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) { SmallString<128> TempNameStr; TempNameStr += StringRef(MO.getSymbolName()); TempNameStr += StringRef("$stub"); MCSymbol *Sym = GetExternalSymbolSymbol(TempNameStr.str()); MachineModuleInfoImpl::StubValueTy &StubSym = MMI->getObjFileInfo<MachineModuleInfoMachO>().getFnStubEntry(Sym); if (StubSym.getPointer() == 0) { TempNameStr.erase(TempNameStr.end()-5, TempNameStr.end()); StubSym = MachineModuleInfoImpl:: StubValueTy(OutContext.GetOrCreateSymbol(TempNameStr.str()), true); } SymToPrint = StubSym.getPointer(); } else { SymToPrint = GetExternalSymbolSymbol(MO.getSymbolName()); } // If the name begins with a dollar-sign, enclose it in parens. We do this // to avoid having it look like an integer immediate to the assembler. if (SymToPrint->getName()[0] != '$') O << *SymToPrint; else O << '(' << *SymToPrint << '('; break; } } switch (MO.getTargetFlags()) { default: llvm_unreachable("Unknown target flag on GV operand"); case X86II::MO_NO_FLAG: // No flag. break; case X86II::MO_DARWIN_NONLAZY: case X86II::MO_DLLIMPORT: case X86II::MO_DARWIN_STUB: // These affect the name of the symbol, not any suffix. break; case X86II::MO_GOT_ABSOLUTE_ADDRESS: O << " + [.-" << *MF->getPICBaseSymbol() << ']'; break; case X86II::MO_PIC_BASE_OFFSET: case X86II::MO_DARWIN_NONLAZY_PIC_BASE: case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: O << '-' << *MF->getPICBaseSymbol(); break; case X86II::MO_TLSGD: O << "@TLSGD"; break; case X86II::MO_TLSLD: O << "@TLSLD"; break; case X86II::MO_TLSLDM: O << "@TLSLDM"; break; case X86II::MO_GOTTPOFF: O << "@GOTTPOFF"; break; case X86II::MO_INDNTPOFF: O << "@INDNTPOFF"; break; case X86II::MO_TPOFF: O << "@TPOFF"; break; case X86II::MO_DTPOFF: O << "@DTPOFF"; break; case X86II::MO_NTPOFF: O << "@NTPOFF"; break; case X86II::MO_GOTNTPOFF: O << "@GOTNTPOFF"; break; case X86II::MO_GOTPCREL: O << "@GOTPCREL"; break; case X86II::MO_GOT: O << "@GOT"; break; case X86II::MO_GOTOFF: O << "@GOTOFF"; break; case X86II::MO_PLT: O << "@PLT"; break; case X86II::MO_TLVP: O << "@TLVP"; break; case X86II::MO_TLVP_PIC_BASE: O << "@TLVP" << '-' << *MF->getPICBaseSymbol(); break; case X86II::MO_SECREL: O << "@SECREL"; break; } }
/// \brief Collect the set of header includes needed to construct the given /// module and update the TopHeaders file set of the module. /// /// \param Module The module we're collecting includes from. /// /// \param Includes Will be augmented with the set of \#includes or \#imports /// needed to load all of the named headers. static llvm::error_code collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr, ModuleMap &ModMap, clang::Module *Module, SmallVectorImpl<char> &Includes) { // Don't collect any headers for unavailable modules. if (!Module->isAvailable()) return llvm::error_code::success(); // Add includes for each of these headers. for (unsigned I = 0, N = Module->NormalHeaders.size(); I != N; ++I) { const FileEntry *Header = Module->NormalHeaders[I]; Module->addTopHeader(Header); if (llvm::error_code Err = addHeaderInclude(Header, Includes, LangOpts, Module->IsExternC)) return Err; } // Note that Module->PrivateHeaders will not be a TopHeader. if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader()) { Module->addTopHeader(UmbrellaHeader); if (Module->Parent) { // Include the umbrella header for submodules. if (llvm::error_code Err = addHeaderInclude(UmbrellaHeader, Includes, LangOpts, Module->IsExternC)) return Err; } } else if (const DirectoryEntry *UmbrellaDir = Module->getUmbrellaDir()) { // Add all of the headers we find in this subdirectory. llvm::error_code EC; SmallString<128> DirNative; llvm::sys::path::native(UmbrellaDir->getName(), DirNative); for (llvm::sys::fs::recursive_directory_iterator Dir(DirNative.str(), EC), DirEnd; Dir != DirEnd && !EC; Dir.increment(EC)) { // Check whether this entry has an extension typically associated with // headers. if (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->path())) .Cases(".h", ".H", ".hh", ".hpp", true) .Default(false)) continue; // If this header is marked 'unavailable' in this module, don't include // it. if (const FileEntry *Header = FileMgr.getFile(Dir->path())) { if (ModMap.isHeaderUnavailableInModule(Header, Module)) continue; Module->addTopHeader(Header); } // Include this header as part of the umbrella directory. if (llvm::error_code Err = addHeaderInclude(Dir->path(), Includes, LangOpts, Module->IsExternC)) return Err; } if (EC) return EC; } // Recurse into submodules. for (clang::Module::submodule_iterator Sub = Module->submodule_begin(), SubEnd = Module->submodule_end(); Sub != SubEnd; ++Sub) if (llvm::error_code Err = collectModuleHeaderIncludes( LangOpts, FileMgr, ModMap, *Sub, Includes)) return Err; return llvm::error_code::success(); }