forked from OSchip/llvm-project
When writing a module file, keep track of the set of (sub)modules that
it imports, establishing dependencies at the (sub)module granularity. This is not a user-visible change (yet). llvm-svn: 145808
This commit is contained in:
parent
e6efe405de
commit
0093b3c7bf
|
@ -78,6 +78,10 @@ public:
|
|||
|
||||
///\ brief The visibility of names within this particular module.
|
||||
NameVisibilityKind NameVisibility;
|
||||
|
||||
/// \brief The set of modules imported by this module, and on which this
|
||||
/// module depends.
|
||||
llvm::SmallVector<Module *, 2> Imports;
|
||||
|
||||
/// \brief Describes an exported module.
|
||||
///
|
||||
|
@ -89,7 +93,7 @@ public:
|
|||
llvm::SmallVector<ExportDecl, 2> Exports;
|
||||
|
||||
/// \brief Describes an exported module that has not yet been resolved
|
||||
/// (perhaps because the module it refers to has not yet been loaded).
|
||||
/// (perhaps because tASThe module it refers to has not yet been loaded).
|
||||
struct UnresolvedExportDecl {
|
||||
/// \brief The location of the 'export' keyword in the module map file.
|
||||
SourceLocation ExportLoc;
|
||||
|
|
|
@ -167,6 +167,16 @@ public:
|
|||
/// false otherwise.
|
||||
bool resolveExports(Module *Mod, bool Complain);
|
||||
|
||||
/// \brief Infers the (sub)module based on the given source location and
|
||||
/// source manager.
|
||||
///
|
||||
/// \param Loc The location within the source that we are querying, along
|
||||
/// with its source manager.
|
||||
///
|
||||
/// \returns The module that owns this source location, or null if no
|
||||
/// module owns this source location.
|
||||
Module *inferModuleFromLocation(FullSourceLoc Loc);
|
||||
|
||||
/// \brief Parse the given module map file, and record any modules we
|
||||
/// encounter.
|
||||
///
|
||||
|
|
|
@ -517,9 +517,12 @@ namespace clang {
|
|||
SUBMODULE_HEADER = 2,
|
||||
/// \brief Metadata for submodules as a whole.
|
||||
SUBMODULE_METADATA = 3,
|
||||
/// \brief Specifies the submodules that are imported by this
|
||||
/// submodule.
|
||||
SUBMODULE_IMPORTS = 4,
|
||||
/// \brief Specifies the submodules that are re-exported from this
|
||||
/// submodule.
|
||||
SUBMODULE_EXPORTS = 4
|
||||
SUBMODULE_EXPORTS = 5
|
||||
};
|
||||
|
||||
/// \defgroup ASTAST AST file AST constants
|
||||
|
|
|
@ -393,21 +393,29 @@ private:
|
|||
/// declarations in that submodule that could be made visible.
|
||||
HiddenNamesMapType HiddenNamesMap;
|
||||
|
||||
/// \brief A module export that hasn't yet been resolved.
|
||||
struct UnresolvedModuleExport {
|
||||
|
||||
/// \brief A module import or export that hasn't yet been resolved.
|
||||
struct UnresolvedModuleImportExport {
|
||||
/// \brief The file in which this module resides.
|
||||
ModuleFile *File;
|
||||
|
||||
/// \brief The module that is exporting, along with a bit that specifies
|
||||
/// whether this is a wildcard export.
|
||||
llvm::PointerIntPair<Module *, 1, bool> ModuleAndWildcard;
|
||||
/// \brief The module that is importing or exporting.
|
||||
Module *Mod;
|
||||
|
||||
/// \brief The local ID of the module that is being exported.
|
||||
unsigned ExportedID;
|
||||
unsigned ID;
|
||||
|
||||
/// \brief Whether this is an import (vs. an export).
|
||||
unsigned IsImport : 1;
|
||||
|
||||
/// \brief Whether this is a wildcard export.
|
||||
unsigned IsWildcard : 1;
|
||||
};
|
||||
|
||||
/// \brief The set of module exports that still need to be resolved.
|
||||
llvm::SmallVector<UnresolvedModuleExport, 2> UnresolvedModuleExports;
|
||||
/// \brief The set of module imports and exports that still need to be
|
||||
/// resolved.
|
||||
llvm::SmallVector<UnresolvedModuleImportExport, 2>
|
||||
UnresolvedModuleImportExports;
|
||||
|
||||
/// \brief A vector containing selectors that have already been loaded.
|
||||
///
|
||||
|
|
|
@ -238,6 +238,26 @@ bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
|
|||
return HadError;
|
||||
}
|
||||
|
||||
Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
|
||||
if (Loc.isInvalid())
|
||||
return 0;
|
||||
|
||||
// Use the expansion location to determine which module we're in.
|
||||
FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
|
||||
if (!ExpansionLoc.isFileID())
|
||||
return 0;
|
||||
|
||||
|
||||
const SourceManager &SrcMgr = Loc.getManager();
|
||||
FileID ExpansionFileID = ExpansionLoc.getFileID();
|
||||
const FileEntry *ExpansionFile = SrcMgr.getFileEntryForID(ExpansionFileID);
|
||||
if (!ExpansionFile)
|
||||
return 0;
|
||||
|
||||
// Find the module that owns this header.
|
||||
return findModuleForHeader(ExpansionFile);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Module map file parser
|
||||
//----------------------------------------------------------------------------//
|
||||
|
|
|
@ -2560,17 +2560,18 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
|
|||
Id->second->setOutOfDate(true);
|
||||
|
||||
// Resolve any unresolved module exports.
|
||||
for (unsigned I = 0, N = UnresolvedModuleExports.size(); I != N; ++I) {
|
||||
UnresolvedModuleExport &Unresolved = UnresolvedModuleExports[I];
|
||||
SubmoduleID GlobalID = getGlobalSubmoduleID(*Unresolved.File,
|
||||
Unresolved.ExportedID);
|
||||
if (Module *Exported = getSubmodule(GlobalID)) {
|
||||
Module *Exportee = Unresolved.ModuleAndWildcard.getPointer();
|
||||
bool Wildcard = Unresolved.ModuleAndWildcard.getInt();
|
||||
Exportee->Exports.push_back(Module::ExportDecl(Exported, Wildcard));
|
||||
for (unsigned I = 0, N = UnresolvedModuleImportExports.size(); I != N; ++I) {
|
||||
UnresolvedModuleImportExport &Unresolved = UnresolvedModuleImportExports[I];
|
||||
SubmoduleID GlobalID = getGlobalSubmoduleID(*Unresolved.File,Unresolved.ID);
|
||||
if (Module *ResolvedMod = getSubmodule(GlobalID)) {
|
||||
if (Unresolved.IsImport)
|
||||
Unresolved.Mod->Imports.push_back(ResolvedMod);
|
||||
else
|
||||
Unresolved.Mod->Exports.push_back(
|
||||
Module::ExportDecl(ResolvedMod, Unresolved.IsWildcard));
|
||||
}
|
||||
}
|
||||
UnresolvedModuleExports.clear();
|
||||
UnresolvedModuleImportExports.clear();
|
||||
|
||||
InitializeContext();
|
||||
|
||||
|
@ -3097,6 +3098,27 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
|
|||
break;
|
||||
}
|
||||
|
||||
case SUBMODULE_IMPORTS: {
|
||||
if (First) {
|
||||
Error("missing submodule metadata record at beginning of block");
|
||||
return Failure;
|
||||
}
|
||||
|
||||
if (!CurrentModule)
|
||||
break;
|
||||
|
||||
for (unsigned Idx = 0; Idx != Record.size(); ++Idx) {
|
||||
UnresolvedModuleImportExport Unresolved;
|
||||
Unresolved.File = &F;
|
||||
Unresolved.Mod = CurrentModule;
|
||||
Unresolved.ID = Record[Idx];
|
||||
Unresolved.IsImport = true;
|
||||
Unresolved.IsWildcard = false;
|
||||
UnresolvedModuleImportExports.push_back(Unresolved);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SUBMODULE_EXPORTS: {
|
||||
if (First) {
|
||||
Error("missing submodule metadata record at beginning of block");
|
||||
|
@ -3107,12 +3129,13 @@ ASTReader::ASTReadResult ASTReader::ReadSubmoduleBlock(ModuleFile &F) {
|
|||
break;
|
||||
|
||||
for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) {
|
||||
UnresolvedModuleExport Unresolved;
|
||||
UnresolvedModuleImportExport Unresolved;
|
||||
Unresolved.File = &F;
|
||||
Unresolved.ModuleAndWildcard.setPointer(CurrentModule);
|
||||
Unresolved.ModuleAndWildcard.setInt(Record[Idx + 1]);
|
||||
Unresolved.ExportedID = Record[Idx];
|
||||
UnresolvedModuleExports.push_back(Unresolved);
|
||||
Unresolved.Mod = CurrentModule;
|
||||
Unresolved.ID = Record[Idx];
|
||||
Unresolved.IsImport = false;
|
||||
Unresolved.IsWildcard = Record[Idx + 1];
|
||||
UnresolvedModuleImportExports.push_back(Unresolved);
|
||||
}
|
||||
|
||||
// Once we've loaded the set of exports, there's no reason to keep
|
||||
|
|
|
@ -1858,6 +1858,22 @@ static unsigned getNumberOfModules(Module *Mod) {
|
|||
}
|
||||
|
||||
void ASTWriter::WriteSubmodules(Module *WritingModule) {
|
||||
//
|
||||
// FIXME: This feels like it belongs somewhere else, but there are no
|
||||
// other consumers of this information.
|
||||
SourceManager &SrcMgr = PP->getSourceManager();
|
||||
ModuleMap &ModMap = PP->getHeaderSearchInfo().getModuleMap();
|
||||
for (ASTContext::import_iterator I = Context->local_import_begin(),
|
||||
IEnd = Context->local_import_end();
|
||||
I != IEnd; ++I) {
|
||||
assert(SubmoduleIDs.find(I->getImportedModule()) != SubmoduleIDs.end());
|
||||
if (Module *ImportedFrom
|
||||
= ModMap.inferModuleFromLocation(FullSourceLoc(I->getLocation(),
|
||||
SrcMgr))) {
|
||||
ImportedFrom->Imports.push_back(I->getImportedModule());
|
||||
}
|
||||
}
|
||||
|
||||
// Enter the submodule description block.
|
||||
Stream.EnterSubblock(SUBMODULE_BLOCK_ID, NUM_ALLOWED_ABBREVS_SIZE);
|
||||
|
||||
|
@ -1924,7 +1940,18 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
|
|||
Stream.EmitRecordWithBlob(HeaderAbbrev, Record,
|
||||
Mod->Headers[I]->getName());
|
||||
}
|
||||
|
||||
|
||||
// Emit the imports.
|
||||
if (!Mod->Imports.empty()) {
|
||||
Record.clear();
|
||||
for (unsigned I = 0, N = Mod->Imports.size(); I != N; ++I) {
|
||||
unsigned ImportedID = SubmoduleIDs[Mod->Imports[I]];
|
||||
assert(ImportedID && "Unknown submodule!");
|
||||
Record.push_back(ImportedID);
|
||||
}
|
||||
Stream.EmitRecord(SUBMODULE_IMPORTS, Record);
|
||||
}
|
||||
|
||||
// Emit the exports.
|
||||
if (!Mod->Exports.empty()) {
|
||||
Record.clear();
|
||||
|
@ -1960,22 +1987,11 @@ serialization::SubmoduleID
|
|||
ASTWriter::inferSubmoduleIDFromLocation(SourceLocation Loc) {
|
||||
if (Loc.isInvalid() || SubmoduleIDs.empty())
|
||||
return 0; // No submodule
|
||||
|
||||
// Use the expansion location to determine which module we're in.
|
||||
SourceManager &SrcMgr = PP->getSourceManager();
|
||||
SourceLocation ExpansionLoc = SrcMgr.getExpansionLoc(Loc);
|
||||
if (!ExpansionLoc.isFileID())
|
||||
return 0;
|
||||
|
||||
|
||||
FileID ExpansionFileID = SrcMgr.getFileID(ExpansionLoc);
|
||||
const FileEntry *ExpansionFile = SrcMgr.getFileEntryForID(ExpansionFileID);
|
||||
if (!ExpansionFile)
|
||||
return 0;
|
||||
|
||||
// Find the module that owns this header.
|
||||
|
||||
// Find the module that owns this location.
|
||||
ModuleMap &ModMap = PP->getHeaderSearchInfo().getModuleMap();
|
||||
Module *OwningMod = ModMap.findModuleForHeader(ExpansionFile);
|
||||
Module *OwningMod
|
||||
= ModMap.inferModuleFromLocation(FullSourceLoc(Loc,PP->getSourceManager()));
|
||||
if (!OwningMod)
|
||||
return 0;
|
||||
|
||||
|
|
Loading…
Reference in New Issue