void StringTableBuilder::write(raw_ostream &OS) const { assert(isFinalized()); SmallString<0> Data; Data.resize(getSize()); write((uint8_t *)&Data[0]); OS << Data; }
MCSymbol *MCContext::createSymbol(StringRef Name, bool AlwaysAddSuffix, bool CanBeUnnamed) { if (CanBeUnnamed && !UseNamesOnTempLabels) return createSymbolImpl(nullptr, true); // Determine whether this is an user writter assembler temporary or normal // label, if used. bool IsTemporary = CanBeUnnamed; if (AllowTemporaryLabels && !IsTemporary) IsTemporary = Name.startswith(MAI->getPrivateGlobalPrefix()); SmallString<128> NewName = Name; bool AddSuffix = AlwaysAddSuffix; unsigned &NextUniqueID = NextID[Name]; for (;;) { if (AddSuffix) { NewName.resize(Name.size()); raw_svector_ostream(NewName) << NextUniqueID++; } auto NameEntry = UsedNames.insert(std::make_pair(NewName, true)); if (NameEntry.second) { // Ok, we found a name. Have the MCSymbol object itself refer to the copy // of the string that is embedded in the UsedNames entry. return createSymbolImpl(&*NameEntry.first, IsTemporary); } assert(IsTemporary && "Cannot rename non-temporary symbols"); AddSuffix = true; } llvm_unreachable("Infinite loop"); }
// getSpelling - Get the spelling of the AsmTok token. static StringRef getSpelling(Sema &SemaRef, Token AsmTok) { StringRef Asm; SmallString<512> TokenBuf; TokenBuf.resize(512); bool StringInvalid = false; Asm = SemaRef.PP.getSpelling(AsmTok, TokenBuf, &StringInvalid); assert (!StringInvalid && "Expected valid string!"); return Asm; }
// This function is an adaptation from StringLiteral::getLocationOfByte in llvm-3.7.1\src\tools\clang\lib\AST\Expr.cpp std::vector<std::string> splitStringLiteral(StringLiteral *S, const SourceManager &SM, const LangOptions &Features, const TargetInfo &Target) { // Loop over all of the tokens in this string until we find the one that // contains the byte we're looking for. unsigned TokNo = 0; std::vector<std::string> result; for (TokNo = 0; TokNo < S->getNumConcatenated(); ++TokNo) { SourceLocation StrTokLoc = S->getStrTokenLoc(TokNo); // Get the spelling of the string so that we can get the data that makes up // the string literal, not the identifier for the macro it is potentially // expanded through. SourceLocation StrTokSpellingLoc = SM.getSpellingLoc(StrTokLoc); // Re-lex the token to get its length and original spelling. std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(StrTokSpellingLoc); bool Invalid = false; StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid); if (Invalid) continue; // We ignore this part const char *StrData = Buffer.data() + LocInfo.second; // Create a lexer starting at the beginning of this token. Lexer TheLexer(SM.getLocForStartOfFile(LocInfo.first), Features, Buffer.begin(), StrData, Buffer.end()); Token TheTok; TheLexer.LexFromRawLexer(TheTok); if (TheTok.isAnyIdentifier()) { // It should not be, since we are parsing inside a string literal, but it can happen with special macros such as __func__ // of __PRETTY_FUNCTION__ that are not resolved at this time. In that case, we just ignore them... continue; } // Get the spelling of the token. SmallString<32> SpellingBuffer; SpellingBuffer.resize(TheTok.getLength()); bool StringInvalid = false; const char *SpellingPtr = &SpellingBuffer[0]; unsigned TokLen = Lexer::getSpelling(TheTok, SpellingPtr, SM, Features, &StringInvalid); if (StringInvalid) continue; const char *SpellingStart = SpellingPtr; const char *SpellingEnd = SpellingPtr + TokLen; result.push_back(std::string(SpellingStart, SpellingEnd)); } return result; }
MCSymbol *MCContext::CreateSymbol(StringRef Name) { // Determine whether this is an assembler temporary or normal label, if used. bool isTemporary = false; if (AllowTemporaryLabels) isTemporary = Name.startswith(MAI->getPrivateGlobalPrefix()); StringMapEntry<bool> *NameEntry = &UsedNames.GetOrCreateValue(Name); if (NameEntry->getValue()) { assert(isTemporary && "Cannot rename non-temporary symbols"); SmallString<128> NewName = Name; do { NewName.resize(Name.size()); raw_svector_ostream(NewName) << NextUniqueID++; NameEntry = &UsedNames.GetOrCreateValue(NewName); } while (NameEntry->getValue()); } NameEntry->setValue(true); // Ok, the entry doesn't already exist. Have the MCSymbol object itself refer // to the copy of the string that is embedded in the UsedNames entry. MCSymbol *Result = new (*this) MCSymbol(NameEntry->getKey(), isTemporary); return Result; }
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: 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::Win32: switch (triple.getEnvironment()) { default: llvm_unreachable("Include management is handled in the driver."); case llvm::Triple::Cygnus: AddPath("/usr/include/w32api", System, false); break; case llvm::Triple::GNU: // 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(LLVM_ON_WIN32) AddPath("c:/mingw/include", System, false); #endif break; } break; default: break; } if ( os != llvm::Triple::RTEMS ) AddPath("/usr/include", ExternCSystem, false); }
/// 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 = 0; SourceLocation StartLoc = Tok.getLocation(); SourceLocation PasteOpLoc; do { // Consume the ## operator. PasteOpLoc = Tokens[CurToken].getLocation(); ++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[LHSLen]; unsigned RHSLen = PP.getSpelling(RHS, BufPtr, &Invalid); if (Invalid) return true; if (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[0], Buffer.size(), 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 a warning that defaults to an error. This allows // disabling it. PP.Diag(Loc, PP.getLangOpts().MicrosoftExt ? diag::err_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 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); 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; }
C2::ExprResult C2Sema::ActOnNumericConstant(const Token& Tok) { #ifdef SEMA_DEBUG std::cerr << COL_SEMA << "SEMA: numeric constant" << ANSI_NORMAL"\n"; #endif // Fast path for a single digit (which is quite common). A single digit // cannot have a trigraph, escaped newline, radix prefix, or suffix. if (Tok.getLength() == 1) { const char Val = PP.getSpellingOfSingleCharacterNumericConstant(Tok); return ActOnIntegerConstant(Tok.getLocation(), Val-'0'); } SmallString<128> SpellingBuffer; // NumericLiteralParser wants to overread by one character. Add padding to // the buffer in case the token is copied to the buffer. If getSpelling() // returns a StringRef to the memory buffer, it should have a null char at // the EOF, so it is also safe. SpellingBuffer.resize(Tok.getLength() + 1); // Get the spelling of the token, which eliminates trigraphs, etc. bool Invalid = false; StringRef TokSpelling = PP.getSpelling(Tok, SpellingBuffer, &Invalid); if (Invalid) return ExprError(); NumericLiteralParser Literal(TokSpelling, Tok.getLocation(), PP); if (Literal.hadError) return ExprError(); if (Literal.hasUDSuffix()) { assert(0 && "HUH?"); } Expr* Res; if (Literal.isFloatingLiteral()) { // clang::Sema::BuildFloatingLiteral() // TEMP Hardcoded const llvm::fltSemantics& Format = llvm::APFloat::IEEEsingle; APFloat Val(Format); APFloat::opStatus result = Literal.GetFloatValue(Val); // Overflow is always an error, but underflow is only an error if // we underflowed to zero (APFloat reports denormals as underflow). if ((result & APFloat::opOverflow) || ((result & APFloat::opUnderflow) && Val.isZero())) { assert(0 && "TODO"); #if 0 unsigned diagnostic; SmallString<20> buffer; if (result & APFloat::opOverflow) { diagnostic = diag::warn_float_overflow; APFloat::getLargest(Format).toString(buffer); } else { diagnostic = diag::warn_float_underflow; APFloat::getSmallest(Format).toString(buffer); } Diag(Tok.getLocation(), diagnostic) << Ty << StringRef(buffer.data(), buffer.size()); #endif } //bool isExact = (result == APFloat::opOK); //return FloatingLiteral::Create(S.Context, Val, isExact, Ty, Loc); Res = new FloatingLiteral(Tok.getLocation(), Val); } else if (!Literal.isIntegerLiteral()) { return ExprError(); } else { QualType ty; const unsigned MaxWidth = 64; // for now limit to 64 bits llvm::APInt ResultVal(MaxWidth, 0); if (Literal.GetIntegerValue(ResultVal)) { Diag(Tok.getLocation(), diag::err_integer_literal_too_large) << 1; } else { #if 0 // Octal, Hexadecimal, and integers with a U suffix are allowed to // be an unsigned. bool AllowUnsigned = Literal.isUnsigned || Literal.getRadix() != 10; // Check from smallest to largest, picking the smallest type we can. unsigned Width = 0; if (!Literal.isLong && !Literal.isLongLong) { // Are int/unsigned possibilities? unsigned IntSize = 64; // Does it fit in a unsigned? if (ResultVal.isIntN(IntSize)) { // Does it fit in a signed int? #if 0 if (!Literal.isUnsigned && ResultVal[IntSize-1] == 0) Ty = Context.IntTy; else if (AllowUnsigned) Ty = Context.UnsignedIntTy; #endif Width = IntSize; } } // Check long long if needed. if (Width == 0) { if (ResultVal.isIntN(64)) { #if 0 if (!Literal.isUnsigned && (ResultVal[LongLongSize-1] == 0 || (getLangOpts().MicrosoftExt && Literal.isLongLong))) Ty = Context.LongLongTy; else if (AllowUnsigned) Ty = Context.UnsignedLongLongTy; #endif Width = 64; } } if (Width == 0) { fprintf(stderr, "TOO LARGE\n"); assert(0 && "TODO"); } // set correct width if (ResultVal.getBitWidth() != Width) { ResultVal = ResultVal.trunc(Width); } #endif } Res = new IntegerLiteral(Tok.getLocation(), ResultVal, Literal.getRadix()); } return ExprResult(Res); }
/// StringifyArgument - Implement C99 6.10.3.2p2, converting a sequence of /// tokens into the literal string token that should be produced by the C # /// preprocessor operator. If Charify is true, then it should be turned into /// a character literal for the Microsoft charize (#@) extension. /// Token MacroArgs::StringifyArgument(const Token *ArgToks, Preprocessor &PP, bool Charify, SourceLocation ExpansionLocStart, SourceLocation ExpansionLocEnd) { Token Tok; Tok.startToken(); Tok.setKind(Charify ? tok::char_constant : tok::string_literal); const Token *ArgTokStart = ArgToks; // Stringify all the tokens. SmallString<128> Result; Result += "\""; bool isFirst = true; for (; ArgToks->isNot(tok::eof); ++ArgToks) { const Token &Tok = *ArgToks; if (!isFirst && (Tok.hasLeadingSpace() || Tok.isAtStartOfLine())) Result += ' '; isFirst = false; // If this is a string or character constant, escape the token as specified // by 6.10.3.2p2. if (tok::isStringLiteral(Tok.getKind()) || // "foo", u8R"x(foo)x"_bar, etc. Tok.is(tok::char_constant) || // 'x' Tok.is(tok::wide_char_constant) || // L'x'. Tok.is(tok::utf8_char_constant) || // u8'x'. Tok.is(tok::utf16_char_constant) || // u'x'. Tok.is(tok::utf32_char_constant)) { // U'x'. bool Invalid = false; std::string TokStr = PP.getSpelling(Tok, &Invalid); if (!Invalid) { std::string Str = Lexer::Stringify(TokStr); Result.append(Str.begin(), Str.end()); } } else if (Tok.is(tok::code_completion)) { PP.CodeCompleteNaturalLanguage(); } else { // Otherwise, just append the token. Do some gymnastics to get the token // in place and avoid copies where possible. unsigned CurStrLen = Result.size(); Result.resize(CurStrLen+Tok.getLength()); const char *BufPtr = Result.data() + CurStrLen; bool Invalid = false; unsigned ActualTokLen = PP.getSpelling(Tok, BufPtr, &Invalid); if (!Invalid) { // If getSpelling returned a pointer to an already uniqued version of // the string instead of filling in BufPtr, memcpy it onto our string. if (ActualTokLen && BufPtr != &Result[CurStrLen]) memcpy(&Result[CurStrLen], BufPtr, ActualTokLen); // If the token was dirty, the spelling may be shorter than the token. if (ActualTokLen != Tok.getLength()) Result.resize(CurStrLen+ActualTokLen); } } } // If the last character of the string is a \, and if it isn't escaped, this // is an invalid string literal, diagnose it as specified in C99. if (Result.back() == '\\') { // Count the number of consecutive \ characters. If even, then they are // just escaped backslashes, otherwise it's an error. unsigned FirstNonSlash = Result.size()-2; // Guaranteed to find the starting " if nothing else. while (Result[FirstNonSlash] == '\\') --FirstNonSlash; if ((Result.size()-1-FirstNonSlash) & 1) { // Diagnose errors for things like: #define F(X) #X / F(\) PP.Diag(ArgToks[-1], diag::pp_invalid_string_literal); Result.pop_back(); // remove one of the \'s. } } Result += '"'; // If this is the charify operation and the result is not a legal character // constant, diagnose it. if (Charify) { // First step, turn double quotes into single quotes: Result[0] = '\''; Result[Result.size()-1] = '\''; // Check for bogus character. bool isBad = false; if (Result.size() == 3) isBad = Result[1] == '\''; // ''' is not legal. '\' already fixed above. else isBad = (Result.size() != 4 || Result[1] != '\\'); // Not '\x' if (isBad) { PP.Diag(ArgTokStart[0], diag::err_invalid_character_to_charify); Result = "' '"; // Use something arbitrary, but legal. } } PP.CreateString(Result, Tok, ExpansionLocStart, ExpansionLocEnd); return Tok; }
/// \brief Parse a header declaration. /// /// header-declaration: /// 'umbrella'[opt] 'header' string-literal void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc) { assert(Tok.is(MMToken::HeaderKeyword)); consumeToken(); bool Umbrella = UmbrellaLoc.isValid(); // Parse the header name. if (!Tok.is(MMToken::StringLiteral)) { Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) << "header"; HadError = true; return; } std::string FileName = Tok.getString(); SourceLocation FileNameLoc = consumeToken(); // Check whether we already have an umbrella. if (Umbrella && ActiveModule->Umbrella) { Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash) << ActiveModule->getFullModuleName(); HadError = true; return; } // Look for this file. const FileEntry *File = 0; const FileEntry *BuiltinFile = 0; SmallString<128> PathName; if (llvm::sys::path::is_absolute(FileName)) { PathName = FileName; File = SourceMgr.getFileManager().getFile(PathName); } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) { PathName = Dir->getName(); llvm::sys::path::append(PathName, FileName); File = SourceMgr.getFileManager().getFile(PathName); } else { // Search for the header file within the search directory. PathName = Directory->getName(); unsigned PathLength = PathName.size(); if (ActiveModule->isPartOfFramework()) { appendSubframeworkPaths(ActiveModule, PathName); // Check whether this file is in the public headers. llvm::sys::path::append(PathName, "Headers"); llvm::sys::path::append(PathName, FileName); File = SourceMgr.getFileManager().getFile(PathName); if (!File) { // Check whether this file is in the private headers. PathName.resize(PathLength); llvm::sys::path::append(PathName, "PrivateHeaders"); llvm::sys::path::append(PathName, FileName); File = SourceMgr.getFileManager().getFile(PathName); } } else { // Lookup for normal headers. llvm::sys::path::append(PathName, FileName); File = SourceMgr.getFileManager().getFile(PathName); // If this is a system module with a top-level header, this header // may have a counterpart (or replacement) in the set of headers // supplied by Clang. Find that builtin header. if (ActiveModule->IsSystem && !Umbrella && BuiltinIncludeDir && BuiltinIncludeDir != Directory && isBuiltinHeader(FileName)) { SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName()); llvm::sys::path::append(BuiltinPathName, FileName); BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName); // If Clang supplies this header but the underlying system does not, // just silently swap in our builtin version. Otherwise, we'll end // up adding both (later). if (!File && BuiltinFile) { File = BuiltinFile; BuiltinFile = 0; } } } } // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. // Come up with a lazy way to do this. if (File) { if (const Module *OwningModule = Map.Headers[File]) { Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) << FileName << OwningModule->getFullModuleName(); HadError = true; } else if (Umbrella) { const DirectoryEntry *UmbrellaDir = File->getDir(); if ((OwningModule = Map.UmbrellaDirs[UmbrellaDir])) { Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) << OwningModule->getFullModuleName(); HadError = true; } else { // Record this umbrella header. Map.setUmbrellaHeader(ActiveModule, File); } } else { // Record this header. Map.addHeader(ActiveModule, File); // If there is a builtin counterpart to this file, add it now. if (BuiltinFile) Map.addHeader(ActiveModule, BuiltinFile); } } else { Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) << Umbrella << FileName; HadError = true; } }
void DwarfStreamer::emitLineTableForUnit(MCDwarfLineTableParams Params, StringRef PrologueBytes, unsigned MinInstLength, std::vector<DWARFDebugLine::Row> &Rows, unsigned PointerSize) { // Switch to the section where the table will be emitted into. MS->SwitchSection(MC->getObjectFileInfo()->getDwarfLineSection()); MCSymbol *LineStartSym = MC->createTempSymbol(); MCSymbol *LineEndSym = MC->createTempSymbol(); // The first 4 bytes is the total length of the information for this // compilation unit (not including these 4 bytes for the length). Asm->EmitLabelDifference(LineEndSym, LineStartSym, 4); Asm->OutStreamer->EmitLabel(LineStartSym); // Copy Prologue. MS->EmitBytes(PrologueBytes); LineSectionSize += PrologueBytes.size() + 4; SmallString<128> EncodingBuffer; raw_svector_ostream EncodingOS(EncodingBuffer); if (Rows.empty()) { // We only have the dummy entry, dsymutil emits an entry with a 0 // address in that case. MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0, EncodingOS); MS->EmitBytes(EncodingOS.str()); LineSectionSize += EncodingBuffer.size(); MS->EmitLabel(LineEndSym); return; } // Line table state machine fields unsigned FileNum = 1; unsigned LastLine = 1; unsigned Column = 0; unsigned IsStatement = 1; unsigned Isa = 0; uint64_t Address = -1ULL; unsigned RowsSinceLastSequence = 0; for (unsigned Idx = 0; Idx < Rows.size(); ++Idx) { auto &Row = Rows[Idx]; int64_t AddressDelta; if (Address == -1ULL) { MS->EmitIntValue(dwarf::DW_LNS_extended_op, 1); MS->EmitULEB128IntValue(PointerSize + 1); MS->EmitIntValue(dwarf::DW_LNE_set_address, 1); MS->EmitIntValue(Row.Address, PointerSize); LineSectionSize += 2 + PointerSize + getULEB128Size(PointerSize + 1); AddressDelta = 0; } else { AddressDelta = (Row.Address - Address) / MinInstLength; } // FIXME: code copied and transformed from MCDwarf.cpp::EmitDwarfLineTable. // We should find a way to share this code, but the current compatibility // requirement with classic dsymutil makes it hard. Revisit that once this // requirement is dropped. if (FileNum != Row.File) { FileNum = Row.File; MS->EmitIntValue(dwarf::DW_LNS_set_file, 1); MS->EmitULEB128IntValue(FileNum); LineSectionSize += 1 + getULEB128Size(FileNum); } if (Column != Row.Column) { Column = Row.Column; MS->EmitIntValue(dwarf::DW_LNS_set_column, 1); MS->EmitULEB128IntValue(Column); LineSectionSize += 1 + getULEB128Size(Column); } // FIXME: We should handle the discriminator here, but dsymutil doesn't // consider it, thus ignore it for now. if (Isa != Row.Isa) { Isa = Row.Isa; MS->EmitIntValue(dwarf::DW_LNS_set_isa, 1); MS->EmitULEB128IntValue(Isa); LineSectionSize += 1 + getULEB128Size(Isa); } if (IsStatement != Row.IsStmt) { IsStatement = Row.IsStmt; MS->EmitIntValue(dwarf::DW_LNS_negate_stmt, 1); LineSectionSize += 1; } if (Row.BasicBlock) { MS->EmitIntValue(dwarf::DW_LNS_set_basic_block, 1); LineSectionSize += 1; } if (Row.PrologueEnd) { MS->EmitIntValue(dwarf::DW_LNS_set_prologue_end, 1); LineSectionSize += 1; } if (Row.EpilogueBegin) { MS->EmitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1); LineSectionSize += 1; } int64_t LineDelta = int64_t(Row.Line) - LastLine; if (!Row.EndSequence) { MCDwarfLineAddr::Encode(*MC, Params, LineDelta, AddressDelta, EncodingOS); MS->EmitBytes(EncodingOS.str()); LineSectionSize += EncodingBuffer.size(); EncodingBuffer.resize(0); Address = Row.Address; LastLine = Row.Line; RowsSinceLastSequence++; } else { if (LineDelta) { MS->EmitIntValue(dwarf::DW_LNS_advance_line, 1); MS->EmitSLEB128IntValue(LineDelta); LineSectionSize += 1 + getSLEB128Size(LineDelta); } if (AddressDelta) { MS->EmitIntValue(dwarf::DW_LNS_advance_pc, 1); MS->EmitULEB128IntValue(AddressDelta); LineSectionSize += 1 + getULEB128Size(AddressDelta); } MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0, EncodingOS); MS->EmitBytes(EncodingOS.str()); LineSectionSize += EncodingBuffer.size(); EncodingBuffer.resize(0); Address = -1ULL; LastLine = FileNum = IsStatement = 1; RowsSinceLastSequence = Column = Isa = 0; } } if (RowsSinceLastSequence) { MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0, EncodingOS); MS->EmitBytes(EncodingOS.str()); LineSectionSize += EncodingBuffer.size(); EncodingBuffer.resize(0); } MS->EmitLabel(LineEndSym); }