From: Chris Lattner Date: Mon, 26 Jan 2009 07:57:50 +0000 (+0000) Subject: start plumbing together the line table information. So far we just X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5b9a504720fb52594ca3686e10eb6c0cfa2e7d62;p=clang start plumbing together the line table information. So far we just unique the Filenames in #line directives, assigning them UIDs. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63010 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index a58662443d..d8c17e11da 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -31,6 +31,7 @@ class SourceManager; class FileManager; class FileEntry; class IdentifierTokenInfo; +class LineTableInfo; /// SrcMgr - Public enums and private classes that are part of the /// SourceManager implementation. @@ -224,7 +225,6 @@ namespace SrcMgr { return E; } }; - } // end SrcMgr namespace. } // end clang namespace @@ -275,6 +275,10 @@ class SourceManager { /// is very common to look up many tokens from the same file. mutable FileID LastFileIDLookup; + /// LineTable - This holds information for #line directives. It is referenced + /// by indices from SLocEntryTable. + LineTableInfo *LineTable; + /// LastLineNo - These ivars serve as a cache used in the getLineNumber /// method which is used to speedup getLineNumber calls to nearby locations. mutable FileID LastLineNoFileIDQuery; @@ -292,23 +296,13 @@ class SourceManager { explicit SourceManager(const SourceManager&); void operator=(const SourceManager&); public: - SourceManager() : NumLinearScans(0), NumBinaryProbes(0) { + SourceManager() : LineTable(0), NumLinearScans(0), NumBinaryProbes(0) { clearIDTables(); } - ~SourceManager() {} - - void clearIDTables() { - MainFileID = FileID(); - SLocEntryTable.clear(); - LastLineNoFileIDQuery = FileID(); - LastLineNoContentCache = 0; - LastFileIDLookup = FileID(); - - // Use up FileID #0 as an invalid instantiation. - NextOffset = 0; - createInstantiationLoc(SourceLocation(), SourceLocation(), 1); - } - + ~SourceManager(); + + void clearIDTables(); + //===--------------------------------------------------------------------===// // MainFileID creation and querying methods. //===--------------------------------------------------------------------===// @@ -552,6 +546,15 @@ public: return getFileCharacteristic(Loc) != SrcMgr::C_User; } + //===--------------------------------------------------------------------===// + // Line Table Manipulation Routines + //===--------------------------------------------------------------------===// + + /// getLineTableFilenameID - Return the uniqued ID for the specified filename. + /// + unsigned getLineTableFilenameID(const char *Ptr, unsigned Len); + + //===--------------------------------------------------------------------===// // Other miscellaneous methods. //===--------------------------------------------------------------------===// diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp index fcca97774d..42e6040b74 100644 --- a/lib/Basic/SourceManager.cpp +++ b/lib/Basic/SourceManager.cpp @@ -58,10 +58,86 @@ const llvm::MemoryBuffer *ContentCache::getBuffer() const { return Buffer; } +//===--------------------------------------------------------------------===// +// Line Table Implementation +//===--------------------------------------------------------------------===// + +namespace clang { +/// LineTableInfo - This class is used to hold and unique data used to +/// represent #line information. +class LineTableInfo { + /// FilenameIDs - This map is used to assign unique IDs to filenames in + /// #line directives. This allows us to unique the filenames that + /// frequently reoccur and reference them with indices. FilenameIDs holds + /// the mapping from string -> ID, and FilenamesByID holds the mapping of ID + /// to string. + llvm::StringMap FilenameIDs; + std::vector*> FilenamesByID; +public: + LineTableInfo() { + } + + void clear() { + FilenameIDs.clear(); + FilenamesByID.clear(); + } + + ~LineTableInfo() {} + + unsigned getLineTableFilenameID(const char *Ptr, unsigned Len); + +}; +} // namespace clang + + + + +unsigned LineTableInfo::getLineTableFilenameID(const char *Ptr, unsigned Len) { + // Look up the filename in the string table, returning the pre-existing value + // if it exists. + llvm::StringMapEntry &Entry = + FilenameIDs.GetOrCreateValue(Ptr, Ptr+Len, ~0U); + if (Entry.getValue() != ~0U) + return Entry.getValue(); + + // Otherwise, assign this the next available ID. + Entry.setValue(FilenamesByID.size()); + FilenamesByID.push_back(&Entry); + return FilenamesByID.size()-1; +} + +/// getLineTableFilenameID - Return the uniqued ID for the specified filename. +/// +unsigned SourceManager::getLineTableFilenameID(const char *Ptr, unsigned Len) { + if (LineTable == 0) + LineTable = new LineTableInfo(); + return LineTable->getLineTableFilenameID(Ptr, Len); +} + + //===--------------------------------------------------------------------===// // Private 'Create' methods. //===--------------------------------------------------------------------===// +SourceManager::~SourceManager() { + delete LineTable; +} + +void SourceManager::clearIDTables() { + MainFileID = FileID(); + SLocEntryTable.clear(); + LastLineNoFileIDQuery = FileID(); + LastLineNoContentCache = 0; + LastFileIDLookup = FileID(); + + if (LineTable) + LineTable->clear(); + + // Use up FileID #0 as an invalid instantiation. + NextOffset = 0; + createInstantiationLoc(SourceLocation(), SourceLocation(), 1); +} + /// getOrCreateContentCache - Create or return a cached ContentCache for the /// specified file. const ContentCache * diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index 5b45ddd35e..099dfb4aef 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -621,6 +621,7 @@ void Preprocessor::HandleLineDirective(Token &Tok) { if (LineNo >= LineLimit) Diag(DigitTok, diag::ext_pp_line_too_big) << LineLimit; + int FilenameID = -1; Token StrTok; Lex(StrTok); @@ -633,6 +634,18 @@ void Preprocessor::HandleLineDirective(Token &Tok) { DiscardUntilEndOfDirective(); return; } else { + // Parse and validate the string, converting it into a unique ID. + StringLiteralParser Literal(&StrTok, 1, *this); + assert(!Literal.AnyWide && "Didn't allow wide strings in"); + if (Literal.hadError) + return DiscardUntilEndOfDirective(); + if (Literal.Pascal) { + Diag(StrTok, diag::err_pp_linemarker_invalid_filename); + return DiscardUntilEndOfDirective(); + } + FilenameID = SourceMgr.getLineTableFilenameID(Literal.GetString(), + Literal.GetStringLength()); + // Verify that there is nothing after the string, other than EOM. CheckEndOfDirective("#line"); } @@ -671,6 +684,7 @@ static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit, // We must have 3 if there are still flags. if (FlagVal != 3) { PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_flag); + PP.DiscardUntilEndOfDirective(); return true; } @@ -684,6 +698,7 @@ static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit, // We must have 4 if there is yet another flag. if (FlagVal != 4) { PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_flag); + PP.DiscardUntilEndOfDirective(); return true; } @@ -694,6 +709,7 @@ static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit, // There are no more valid flags here. PP.Diag(FlagTok, diag::err_pp_linemarker_invalid_flag); + PP.DiscardUntilEndOfDirective(); return true; } @@ -717,22 +733,32 @@ void Preprocessor::HandleDigitDirective(Token &DigitTok) { bool IsFileEntry = false, IsFileExit = false; bool IsSystemHeader = false, IsExternCHeader = false; - + int FilenameID = -1; + // If the StrTok is "eom", then it wasn't present. Otherwise, it must be a // string followed by eom. if (StrTok.is(tok::eom)) ; // ok else if (StrTok.isNot(tok::string_literal)) { Diag(StrTok, diag::err_pp_linemarker_invalid_filename); - DiscardUntilEndOfDirective(); - return; + return DiscardUntilEndOfDirective(); } else { + // Parse and validate the string, converting it into a unique ID. + StringLiteralParser Literal(&StrTok, 1, *this); + assert(!Literal.AnyWide && "Didn't allow wide strings in"); + if (Literal.hadError) + return DiscardUntilEndOfDirective(); + if (Literal.Pascal) { + Diag(StrTok, diag::err_pp_linemarker_invalid_filename); + return DiscardUntilEndOfDirective(); + } + FilenameID = SourceMgr.getLineTableFilenameID(Literal.GetString(), + Literal.GetStringLength()); + // If a filename was present, read any flags that are present. if (ReadLineMarkerFlags(IsFileEntry, IsFileExit, - IsSystemHeader, IsExternCHeader, *this)) { - DiscardUntilEndOfDirective(); + IsSystemHeader, IsExternCHeader, *this)) return; - } } // FIXME: do something with the #line info.