Keep track of which modules have been loaded directly (e.g., via

-import-module) vs. loaded because some other module depends on
them. As part of doing this, pass down the module that caused a module
to be loaded directly, rather than assuming that we're loading a
chain. Finally, write out all of the directly-loaded modules when
serializing an AST file (using the new IMPORTS record), so that an AST
file can depend on more than one other AST file, all of which will be
loaded when that AST file is loaded. This allows us to form and load a
tree of modules, but we can't yet load a DAG of modules.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@137923 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2011-08-18 04:12:04 +00:00
Родитель 1cb4f664fd
Коммит 10bc00fd45
3 изменённых файлов: 59 добавлений и 33 удалений

Просмотреть файл

@ -190,6 +190,10 @@ public:
/// \brief The file name of the module file.
std::string FileName;
/// \brief Whether this module has been directly imported by the
/// user.
bool DirectlyImported;
/// \brief The memory buffer that stores the data associated with
/// this AST file.
llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
@ -418,7 +422,11 @@ public:
/// \brief List of modules which this module depends on
llvm::SetVector<Module *> Imports;
/// \brief Determine whether this module was directly imported at
/// any point during translation.
bool isDirectlyImported() const { return DirectlyImported; }
/// \brief Dump debugging output for this module.
void dump();
};
@ -490,8 +498,17 @@ public:
/// \brief Number of modules loaded
unsigned size() const { return Chain.size(); }
/// \brief Creates a new module and adds it to the list of known modules
Module &addModule(StringRef FileName, ModuleKind Type);
/// \brief Attempts to create a new module and add it to the list of known
/// modules.
///
/// \param FileName The file name of the module to be loaded.
///
/// \param Type The kind of module being loaded.
///
/// \param ImportedBy The module that is importing this module, or NULL if
/// this module is imported directly by the user.
Module &addModule(StringRef FileName, ModuleKind Type,
Module *ImportedBy);
/// \brief Add an in-memory buffer the list of known buffers
void addInMemoryBuffer(StringRef FileName, llvm::MemoryBuffer *Buffer);
@ -1007,7 +1024,8 @@ private:
void MaybeAddSystemRootToFilename(std::string &Filename);
ASTReadResult ReadASTCore(StringRef FileName, ModuleKind Type);
ASTReadResult ReadASTCore(StringRef FileName, ModuleKind Type,
Module *ImportedBy);
ASTReadResult ReadASTBlock(Module &F);
bool CheckPredefinesBuffers();
bool ParseLineTable(Module &F, SmallVectorImpl<uint64_t> &Record);
@ -1104,8 +1122,7 @@ public:
bool DisableValidation = false, bool DisableStatCache = false);
~ASTReader();
/// \brief Load the precompiled header designated by the given file
/// name.
/// \brief Load the AST file designated by the given file name.
ASTReadResult ReadAST(const std::string &FileName, ModuleKind Type);
/// \brief Checks that no file that is stored in PCH is out-of-sync with

Просмотреть файл

@ -2045,7 +2045,7 @@ ASTReader::ReadASTBlock(Module &F) {
Idx += Length;
// Load the AST file.
switch(ReadASTCore(ImportedFile, ImportedKind)) {
switch(ReadASTCore(ImportedFile, ImportedKind, &F)) {
case Failure: return Failure;
// If we have to ignore the dependency, we'll have to ignore this too.
case IgnorePCH: return IgnorePCH;
@ -2724,7 +2724,7 @@ ASTReader::ASTReadResult ASTReader::validateFileEntries() {
ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
ModuleKind Type) {
switch(ReadASTCore(FileName, Type)) {
switch(ReadASTCore(FileName, Type, /*ImportedBy=*/0)) {
case Failure: return Failure;
case IgnorePCH: return IgnorePCH;
case Success: break;
@ -2829,8 +2829,9 @@ ASTReader::ASTReadResult ASTReader::ReadAST(const std::string &FileName,
}
ASTReader::ASTReadResult ASTReader::ReadASTCore(StringRef FileName,
ModuleKind Type) {
Module &F = ModuleMgr.addModule(FileName, Type);
ModuleKind Type,
Module *ImportedBy) {
Module &F = ModuleMgr.addModule(FileName, Type, ImportedBy);
if (FileName != "-") {
CurrentDir = llvm::sys::path::parent_path(FileName);
@ -5610,7 +5611,8 @@ ASTReader::~ASTReader() {
}
Module::Module(ModuleKind Kind)
: Kind(Kind), SizeInBits(0), LocalNumSLocEntries(0), SLocEntryBaseID(0),
: Kind(Kind), DirectlyImported(false), SizeInBits(0),
LocalNumSLocEntries(0), SLocEntryBaseID(0),
SLocEntryBaseOffset(0), SLocEntryOffsets(0),
SLocFileOffsets(0), LocalNumIdentifiers(0),
IdentifierOffsets(0), BaseIdentifierID(0), IdentifierTableData(0),
@ -5708,19 +5710,21 @@ llvm::MemoryBuffer *ModuleManager::lookupBuffer(StringRef Name) {
}
/// \brief Creates a new module and adds it to the list of known modules
Module &ModuleManager::addModule(StringRef FileName, ModuleKind Type) {
Module *Prev = !size() ? 0 : &getLastModule();
Module &ModuleManager::addModule(StringRef FileName, ModuleKind Type,
Module *ImportedBy) {
Module *Current = new Module(Type);
Current->FileName = FileName.str();
Chain.push_back(Current);
const FileEntry *Entry = FileMgr.getFile(FileName);
// FIXME: Check whether we already loaded this module, before
Modules[Entry] = Current;
if (Prev) {
Current->ImportedBy.insert(Prev);
Prev->Imports.insert(Current);
if (ImportedBy) {
Current->ImportedBy.insert(ImportedBy);
ImportedBy->Imports.insert(Current);
} else {
Current->DirectlyImported = true;
}
return *Current;

Просмотреть файл

@ -972,18 +972,23 @@ void ASTWriter::WriteMetadata(ASTContext &Context, StringRef isysroot,
Stream.EmitRecordWithBlob(MetaAbbrevCode, Record, Triple);
if (Chain) {
// FIXME: Add all of the "directly imported" modules, not just
// "the one we're chaining to".
serialization::ModuleManager &Mgr = Chain->getModuleManager();
llvm::SmallVector<char, 128> ModulePaths;
Record.clear();
Module &PrimaryModule = Mgr.getPrimaryModule();
Record.push_back((unsigned)PrimaryModule.Kind); // FIXME: Stable encoding
// FIXME: Write import location, once it matters.
// FIXME: This writes the absolute path for AST files we depend on.
const std::string &MainFileName = PrimaryModule.FileName;
Record.push_back(MainFileName.size());
Record.append(MainFileName.begin(), MainFileName.end());
for (ModuleManager::ModuleIterator M = Mgr.begin(), MEnd = Mgr.end();
M != MEnd; ++M) {
// Skip modules that weren't directly imported.
if (!(*M)->isDirectlyImported())
continue;
Record.push_back((unsigned)(*M)->Kind); // FIXME: Stable encoding
// FIXME: Write import location, once it matters.
// FIXME: This writes the absolute path for AST files we depend on.
const std::string &FileName = (*M)->FileName;
Record.push_back(FileName.size());
Record.append(FileName.begin(), FileName.end());
}
Stream.EmitRecord(IMPORTS, Record);
}
@ -3855,7 +3860,7 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec
void ASTWriter::ReaderInitialized(ASTReader *Reader) {
assert(Reader && "Cannot remove chain");
assert(!Chain && "Cannot replace chain");
assert((!Chain || Chain == Reader) && "Cannot replace chain");
assert(FirstDeclID == NextDeclID &&
FirstTypeID == NextTypeID &&
FirstIdentID == NextIdentID &&
@ -3865,11 +3870,11 @@ void ASTWriter::ReaderInitialized(ASTReader *Reader) {
Chain = Reader;
FirstDeclID += Chain->getTotalNumDecls();
FirstTypeID += Chain->getTotalNumTypes();
FirstIdentID += Chain->getTotalNumIdentifiers();
FirstSelectorID += Chain->getTotalNumSelectors();
FirstMacroID += Chain->getTotalNumMacroDefinitions();
FirstDeclID = NUM_PREDEF_DECL_IDS + Chain->getTotalNumDecls();
FirstTypeID = NUM_PREDEF_TYPE_IDS + Chain->getTotalNumTypes();
FirstIdentID = NUM_PREDEF_IDENT_IDS + Chain->getTotalNumIdentifiers();
FirstSelectorID = NUM_PREDEF_SELECTOR_IDS + Chain->getTotalNumSelectors();
FirstMacroID = NUM_PREDEF_MACRO_IDS + Chain->getTotalNumMacroDefinitions();
NextDeclID = FirstDeclID;
NextTypeID = FirstTypeID;
NextIdentID = FirstIdentID;