diff options
author | Douglas Gregor <dgregor@apple.com> | 2013-03-15 22:15:07 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2013-03-15 22:15:07 +0000 |
commit | 4a18c3b25a2d7eb7f770ce91ee5e14433b2a1cb6 (patch) | |
tree | 05f938df7bed796c64ae56c7a4ed72821a7e68d9 /lib/Serialization/ASTWriter.cpp | |
parent | 9de50947ba381561a5236b3c878c83e4bb8c1088 (diff) |
<rdar://problem/13426257> Introduce SDKSettings.plist as an input file dependency for PCH/modules.
When we're building a precompiled header or module against an SDK on
Darwin, there will be a file SDKSettings.plist in the sysroot. Since
stat()'ing every system header on which a module or PCH file depends
is performance suicide, we instead stat() just SDKSettings.plist. This
hack works well on Darwin; it's unclear how we want to handle this on
other platforms. If there is a canonical file, we should use it; if
not, we either have to take the performance hit of stat()'ing system
headers repeatedly or roll the dice by not checking anything.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@177194 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Serialization/ASTWriter.cpp')
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 61 |
1 files changed, 46 insertions, 15 deletions
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 10a80444a2..b113c76f44 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -1213,11 +1213,24 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, Stream.EmitRecordWithBlob(AbbrevCode, Record, origDir); } - WriteInputFiles(Context.SourceMgr, isysroot); + WriteInputFiles(Context.SourceMgr, + PP.getHeaderSearchInfo().getHeaderSearchOpts(), + isysroot); Stream.ExitBlock(); } -void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, StringRef isysroot) { +namespace { + /// \brief An input file. + struct InputFileEntry { + const FileEntry *File; + bool IsSystemFile; + bool BufferOverridden; + }; +} + +void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, + HeaderSearchOptions &HSOpts, + StringRef isysroot) { using namespace llvm; Stream.EnterSubblock(INPUT_FILES_BLOCK_ID, 4); RecordData Record; @@ -1234,7 +1247,7 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, StringRef isysroot) { // Get all ContentCache objects for files, sorted by whether the file is a // system one or not. System files go at the back, users files at the front. - std::deque<const SrcMgr::ContentCache *> SortedFiles; + std::deque<InputFileEntry> SortedFiles; for (unsigned I = 1, N = SourceMgr.local_sloc_entry_size(); I != N; ++I) { // Get this source location entry. const SrcMgr::SLocEntry *SLoc = &SourceMgr.getLocalSLocEntry(I); @@ -1247,20 +1260,38 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, StringRef isysroot) { if (!Cache->OrigEntry) continue; + InputFileEntry Entry; + Entry.File = Cache->OrigEntry; + Entry.IsSystemFile = Cache->IsSystemFile; + Entry.BufferOverridden = Cache->BufferOverridden; if (Cache->IsSystemFile) - SortedFiles.push_back(Cache); + SortedFiles.push_back(Entry); else - SortedFiles.push_front(Cache); + SortedFiles.push_front(Entry); + } + + // If we have an isysroot for a Darwin SDK, include its SDKSettings.plist in + // the set of (non-system) input files. This is simple heuristic for + // detecting whether the system headers may have changed, because it is too + // expensive to stat() all of the system headers. + FileManager &FileMgr = SourceMgr.getFileManager(); + if (!HSOpts.Sysroot.empty()) { + llvm::SmallString<128> SDKSettingsFileName(HSOpts.Sysroot); + llvm::sys::path::append(SDKSettingsFileName, "SDKSettings.plist"); + if (const FileEntry *SDKSettingsFile = FileMgr.getFile(SDKSettingsFileName)) { + InputFileEntry Entry = { SDKSettingsFile, false, false }; + SortedFiles.push_front(Entry); + } } unsigned UserFilesNum = 0; // Write out all of the input files. std::vector<uint32_t> InputFileOffsets; - for (std::deque<const SrcMgr::ContentCache *>::iterator + for (std::deque<InputFileEntry>::iterator I = SortedFiles.begin(), E = SortedFiles.end(); I != E; ++I) { - const SrcMgr::ContentCache *Cache = *I; + const InputFileEntry &Entry = *I; - uint32_t &InputFileID = InputFileIDs[Cache->OrigEntry]; + uint32_t &InputFileID = InputFileIDs[Entry.File]; if (InputFileID != 0) continue; // already recorded this file. @@ -1269,7 +1300,7 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, StringRef isysroot) { InputFileID = InputFileOffsets.size(); - if (!Cache->IsSystemFile) + if (!Entry.IsSystemFile) ++UserFilesNum; Record.clear(); @@ -1277,19 +1308,19 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, StringRef isysroot) { Record.push_back(InputFileOffsets.size()); // Emit size/modification time for this file. - Record.push_back(Cache->OrigEntry->getSize()); - Record.push_back(Cache->OrigEntry->getModificationTime()); + Record.push_back(Entry.File->getSize()); + Record.push_back(Entry.File->getModificationTime()); // Whether this file was overridden. - Record.push_back(Cache->BufferOverridden); + Record.push_back(Entry.BufferOverridden); // Turn the file name into an absolute path, if it isn't already. - const char *Filename = Cache->OrigEntry->getName(); + const char *Filename = Entry.File->getName(); SmallString<128> FilePath(Filename); // Ask the file manager to fixup the relative path for us. This will // honor the working directory. - SourceMgr.getFileManager().FixupRelativePath(FilePath); + FileMgr.FixupRelativePath(FilePath); // FIXME: This call to make_absolute shouldn't be necessary, the // call to FixupRelativePath should always return an absolute path. @@ -1300,7 +1331,7 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, StringRef isysroot) { Stream.EmitRecordWithBlob(IFAbbrevCode, Record, Filename); } - + Stream.ExitBlock(); // Create input file offsets abbreviation. |