summaryrefslogtreecommitdiff
path: root/lib/Serialization
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2015-08-18 23:42:23 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2015-08-18 23:42:23 +0000
commit52dd46213d6c78575cfa543afe7db83fdbd4b36c (patch)
tree0d9474f9710541cdb3a2079ca6cd96645f060d31 /lib/Serialization
parent673861a3c68537a1bd889860e4cec5773ecdc754 (diff)
downloadclang-52dd46213d6c78575cfa543afe7db83fdbd4b36c.tar.gz
[modules] Fix HeaderFileInfo serialization to store all the known owning modules for a header, not just the current favourite.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@245390 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Serialization')
-rw-r--r--lib/Serialization/ASTReader.cpp65
-rw-r--r--lib/Serialization/ASTWriter.cpp74
2 files changed, 73 insertions, 66 deletions
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 6d41d155c5..fc9d29a908 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -1556,14 +1556,15 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
using namespace llvm::support;
HeaderFileInfo HFI;
unsigned Flags = *d++;
- HFI.HeaderRole = static_cast<ModuleMap::ModuleHeaderRole>
- ((Flags >> 6) & 0x03);
- HFI.isImport = (Flags >> 5) & 0x01;
- HFI.isPragmaOnce = (Flags >> 4) & 0x01;
- HFI.DirInfo = (Flags >> 2) & 0x03;
- HFI.Resolved = (Flags >> 1) & 0x01;
+ // FIXME: Refactor with mergeHeaderFileInfo in HeaderSearch.cpp.
+ HFI.isImport |= (Flags >> 4) & 0x01;
+ HFI.isPragmaOnce |= (Flags >> 3) & 0x01;
+ HFI.DirInfo = (Flags >> 1) & 0x03;
HFI.IndexHeaderMapHeader = Flags & 0x01;
- HFI.NumIncludes = endian::readNext<uint16_t, little, unaligned>(d);
+ // FIXME: Find a better way to handle this. Maybe just store a
+ // "has been included" flag?
+ HFI.NumIncludes = std::max(endian::readNext<uint16_t, little, unaligned>(d),
+ HFI.NumIncludes);
HFI.ControllingMacroID = Reader.getGlobalIdentifierID(
M, endian::readNext<uint32_t, little, unaligned>(d));
if (unsigned FrameworkOffset =
@@ -1573,32 +1574,32 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
StringRef FrameworkName(FrameworkStrings + FrameworkOffset - 1);
HFI.Framework = HS->getUniqueFrameworkName(FrameworkName);
}
-
- if (d != End) {
+
+ assert((End - d) % 4 == 0 &&
+ "Wrong data length in HeaderFileInfo deserialization");
+ while (d != End) {
uint32_t LocalSMID = endian::readNext<uint32_t, little, unaligned>(d);
- if (LocalSMID) {
- // This header is part of a module. Associate it with the module to enable
- // implicit module import.
- SubmoduleID GlobalSMID = Reader.getGlobalSubmoduleID(M, LocalSMID);
- Module *Mod = Reader.getSubmodule(GlobalSMID);
- HFI.isModuleHeader = true;
- FileManager &FileMgr = Reader.getFileManager();
- ModuleMap &ModMap =
- Reader.getPreprocessor().getHeaderSearchInfo().getModuleMap();
- // FIXME: This information should be propagated through the
- // SUBMODULE_HEADER etc records rather than from here.
- // FIXME: We don't ever mark excluded headers.
- std::string Filename = key.Filename;
- if (key.Imported)
- Reader.ResolveImportedPath(M, Filename);
- Module::Header H = { key.Filename, FileMgr.getFile(Filename) };
- ModMap.addHeader(Mod, H, HFI.getHeaderRole());
- }
- }
-
- assert(End == d && "Wrong data length in HeaderFileInfo deserialization");
- (void)End;
-
+ auto HeaderRole = static_cast<ModuleMap::ModuleHeaderRole>(LocalSMID & 3);
+ LocalSMID >>= 2;
+
+ // This header is part of a module. Associate it with the module to enable
+ // implicit module import.
+ SubmoduleID GlobalSMID = Reader.getGlobalSubmoduleID(M, LocalSMID);
+ Module *Mod = Reader.getSubmodule(GlobalSMID);
+ FileManager &FileMgr = Reader.getFileManager();
+ ModuleMap &ModMap =
+ Reader.getPreprocessor().getHeaderSearchInfo().getModuleMap();
+
+ std::string Filename = key.Filename;
+ if (key.Imported)
+ Reader.ResolveImportedPath(M, Filename);
+ // FIXME: This is not always the right filename-as-written, but we're not
+ // going to use this information to rebuild the module, so it doesn't make
+ // a lot of difference.
+ Module::Header H = { key.Filename, FileMgr.getFile(Filename) };
+ ModMap.addHeader(Mod, H, HeaderRole);
+ }
+
// This HeaderFileInfo was externally loaded.
HFI.External = true;
return HFI;
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 0aceb08293..b554f5f1cc 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -1637,13 +1637,14 @@ namespace {
std::pair<unsigned,unsigned>
EmitKeyDataLength(raw_ostream& Out, key_type_ref key, data_type_ref Data) {
using namespace llvm::support;
- endian::Writer<little> Writer(Out);
+ endian::Writer<little> LE(Out);
unsigned KeyLen = strlen(key.Filename) + 1 + 8 + 8;
- Writer.write<uint16_t>(KeyLen);
+ LE.write<uint16_t>(KeyLen);
unsigned DataLen = 1 + 2 + 4 + 4;
- if (Data.isModuleHeader)
- DataLen += 4;
- Writer.write<uint8_t>(DataLen);
+ for (auto ModInfo : HS.getModuleMap().findAllModulesForHeader(key.FE))
+ if (Writer.getLocalOrImportedSubmoduleID(ModInfo.getModule()))
+ DataLen += 4;
+ LE.write<uint8_t>(DataLen);
return std::make_pair(KeyLen, DataLen);
}
@@ -1663,11 +1664,9 @@ namespace {
endian::Writer<little> LE(Out);
uint64_t Start = Out.tell(); (void)Start;
- unsigned char Flags = (Data.HeaderRole << 6)
- | (Data.isImport << 5)
- | (Data.isPragmaOnce << 4)
- | (Data.DirInfo << 2)
- | (Data.Resolved << 1)
+ unsigned char Flags = (Data.isImport << 4)
+ | (Data.isPragmaOnce << 3)
+ | (Data.DirInfo << 1)
| Data.IndexHeaderMapHeader;
LE.write<uint8_t>(Flags);
LE.write<uint16_t>(Data.NumIncludes);
@@ -1694,9 +1693,15 @@ namespace {
}
LE.write<uint32_t>(Offset);
- if (Data.isModuleHeader) {
- Module *Mod = HS.findModuleForHeader(key.FE).getModule();
- LE.write<uint32_t>(Writer.getExistingSubmoduleID(Mod));
+ // FIXME: If the header is excluded, we should write out some
+ // record of that fact.
+ for (auto ModInfo : HS.getModuleMap().findAllModulesForHeader(key.FE)) {
+ if (uint32_t ModID =
+ Writer.getLocalOrImportedSubmoduleID(ModInfo.getModule())) {
+ uint32_t Value = (ModID << 2) | (unsigned)ModInfo.getRole();
+ assert((Value >> 2) == ModID && "overflow in header module info");
+ LE.write<uint32_t>(Value);
+ }
}
assert(Out.tell() - Start == DataLen && "Wrong data length");
@@ -1726,12 +1731,15 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
if (!File)
continue;
- // Use HeaderSearch's getFileInfo to make sure we get the HeaderFileInfo
- // from the external source if it was not provided already.
- HeaderFileInfo HFI;
- if (!HS.tryGetFileInfo(File, HFI) ||
- (HFI.External && Chain) ||
- (HFI.isModuleHeader && !HFI.isCompilingModuleHeader))
+ // Get the file info. This will load info from the external source if
+ // necessary. Skip emitting this file if we have no information on it
+ // as a header file (in which case HFI will be null) or if it hasn't
+ // changed since it was loaded. Also skip it if it's for a modular header
+ // from a different module; in that case, we rely on the module(s)
+ // containing the header to provide this information.
+ const HeaderFileInfo *HFI = HS.getExistingFileInfo(File);
+ if (!HFI || (HFI->External && Chain) ||
+ (HFI->isModuleHeader && !HFI->isCompilingModuleHeader))
continue;
// Massage the file path into an appropriate form.
@@ -1745,7 +1753,7 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
}
HeaderFileInfoTrait::key_type key = { File, Filename };
- Generator.insert(key, HFI, GeneratorTrait);
+ Generator.insert(key, *HFI, GeneratorTrait);
++NumHeaderSearchEntries;
}
@@ -2283,27 +2291,28 @@ void ASTWriter::WritePreprocessorDetail(PreprocessingRecord &PPRec) {
}
}
-unsigned ASTWriter::getSubmoduleID(Module *Mod) {
+unsigned ASTWriter::getLocalOrImportedSubmoduleID(Module *Mod) {
if (!Mod)
return 0;
llvm::DenseMap<Module *, unsigned>::iterator Known = SubmoduleIDs.find(Mod);
if (Known != SubmoduleIDs.end())
return Known->second;
-
- return SubmoduleIDs[Mod] = NextSubmoduleID++;
-}
-unsigned ASTWriter::getExistingSubmoduleID(Module *Mod) const {
- if (!Mod)
+ if (Mod->getTopLevelModule() != WritingModule)
return 0;
- llvm::DenseMap<Module *, unsigned>::const_iterator
- Known = SubmoduleIDs.find(Mod);
- if (Known != SubmoduleIDs.end())
- return Known->second;
+ return SubmoduleIDs[Mod] = NextSubmoduleID++;
+}
- return 0;
+unsigned ASTWriter::getSubmoduleID(Module *Mod) {
+ // FIXME: This can easily happen, if we have a reference to a submodule that
+ // did not result in us loading a module file for that submodule. For
+ // instance, a cross-top-level-module 'conflict' declaration will hit this.
+ unsigned ID = getLocalOrImportedSubmoduleID(Mod);
+ assert((ID || !Mod) &&
+ "asked for module ID for non-local, non-imported module");
+ return ID;
}
/// \brief Compute the number of modules within the given tree (including the
@@ -2542,9 +2551,6 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
Stream.ExitBlock();
- // FIXME: This can easily happen, if we have a reference to a submodule that
- // did not result in us loading a module file for that submodule. For
- // instance, a cross-top-level-module 'conflict' declaration will hit this.
assert((NextSubmoduleID - FirstSubmoduleID ==
getNumberOfModules(WritingModule)) &&
"Wrong # of submodules; found a reference to a non-local, "