]> granicus.if.org Git - clang/commitdiff
[PCH] When pre-validating the headers from the PCH, only validate non-system headers.
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Wed, 6 Mar 2013 18:12:50 +0000 (18:12 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Wed, 6 Mar 2013 18:12:50 +0000 (18:12 +0000)
Stat'ing all the headers from the PCH to make sure they are up-to-date takes significant time.
In a particular source file (whose PCH file included Cocoa.h) from total -fsyntax-only time
12% was just stat calls. Change pre-validation to only check non-system headers.

There are some notable disadvantages:

-If a system header, that is not include-guarded, changes after the PCH was created, we will not
find it in the header info table and we will #import it, effectively #importing it twice, thus
we will emit some error due to a multiple definition and after that the "header was modified" error will likely
be emitted, for example something like:

NSDictionary.h:12:1: error: duplicate interface definition for class 'NSDictionary'
@interface NSDictionary : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration>
^
NSDictionary.h:12:12: note: previous definition is here
@interface NSDictionary : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration>
           ^
fatal error: file 'NSDictionary.h' has been modified since the precompiled header was built

Though we get the "header was modified" error, this is a bit confusing.

-Theoretically it is possible that such a system header will cause no errors but it will just cause an
unfortunate semantic change, though I find this rather unlikely.

The advantages:

-Reduces compilation time when using a huge PCH like the Cocoa ones
-System headers change very infrequent and when they do, users/build systems should be able to know that
re-building from scratch is needed.

Addresses rdar://13056262

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@176567 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Serialization/ASTReader.cpp
lib/Serialization/ASTWriter.cpp

index d62c42bb1b898d32701e39935470686f8454051d..0389722bfd91c8735af6acec37d357d8972c0b9f 100644 (file)
@@ -1680,10 +1680,12 @@ ASTReader::ReadControlBlock(ModuleFile &F,
       Error("malformed block record in AST file");
       return Failure;
     case llvm::BitstreamEntry::EndBlock:
-      // Validate all of the input files.
+      // Validate all of the non-system input files.
       if (!DisableValidation) {
         bool Complain = (ClientLoadCapabilities & ARR_OutOfDate) == 0;
-        for (unsigned I = 0, N = Record[0]; I < N; ++I) {
+        // All user input files reside at the index range [0, Record[1]).
+        // Record is the one from INPUT_FILE_OFFSETS.
+        for (unsigned I = 0, N = Record[1]; I < N; ++I) {
           InputFile IF = getInputFile(F, I+1, Complain);
           if (!IF.getFile() || IF.isOutOfDate())
             return OutOfDate;
index 31af7626a81bfb599cdc7b4430170a4a48af4b53..815cf12f11741d8b0761963967f107d01547e5f3 100644 (file)
@@ -1232,8 +1232,9 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, StringRef isysroot) {
   IFAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // File name
   unsigned IFAbbrevCode = Stream.EmitAbbrev(IFAbbrev);
 
-  // Write out all of the input files.
-  std::vector<uint32_t> InputFileOffsets;
+  // 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;
   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);
@@ -1246,6 +1247,19 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, StringRef isysroot) {
     if (!Cache->OrigEntry)
       continue;
 
+    if (Cache->IsSystemFile)
+      SortedFiles.push_back(Cache);
+    else
+      SortedFiles.push_front(Cache);
+  }
+
+  unsigned UserFilesNum = 0;
+  // Write out all of the input files.
+  std::vector<uint32_t> InputFileOffsets;
+  for (std::deque<const SrcMgr::ContentCache *>::iterator
+         I = SortedFiles.begin(), E = SortedFiles.end(); I != E; ++I) {
+    const SrcMgr::ContentCache *Cache = *I;
+
     uint32_t &InputFileID = InputFileIDs[Cache->OrigEntry];
     if (InputFileID != 0)
       continue; // already recorded this file.
@@ -1255,6 +1269,9 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, StringRef isysroot) {
 
     InputFileID = InputFileOffsets.size();
 
+    if (!Cache->IsSystemFile)
+      ++UserFilesNum;
+
     Record.clear();
     Record.push_back(INPUT_FILE);
     Record.push_back(InputFileOffsets.size());
@@ -1290,6 +1307,8 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, StringRef isysroot) {
   BitCodeAbbrev *OffsetsAbbrev = new BitCodeAbbrev();
   OffsetsAbbrev->Add(BitCodeAbbrevOp(INPUT_FILE_OFFSETS));
   OffsetsAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # input files
+  OffsetsAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # non-system
+                                                                //   input files
   OffsetsAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));   // Array
   unsigned OffsetsAbbrevCode = Stream.EmitAbbrev(OffsetsAbbrev);
 
@@ -1297,6 +1316,7 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr, StringRef isysroot) {
   Record.clear();
   Record.push_back(INPUT_FILE_OFFSETS);
   Record.push_back(InputFileOffsets.size());
+  Record.push_back(UserFilesNum);
   Stream.EmitRecordWithBlob(OffsetsAbbrevCode, Record, data(InputFileOffsets));
 }