Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 53 additions & 1 deletion clang/include/clang/Lex/ExternalPreprocessorSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,64 @@ class ExternalPreprocessorSource {
/// Return the identifier associated with the given ID number.
///
/// The ID 0 is associated with the NULL identifier.
virtual IdentifierInfo *GetIdentifier(unsigned ID) = 0;
virtual IdentifierInfo *GetIdentifier(uint64_t ID) = 0;

/// Map a module ID to a module.
virtual Module *getModule(unsigned ModuleID) = 0;
};

// Either a pointer to an IdentifierInfo of the controlling macro or the ID
// number of the controlling macro.
class LazyIdentifierInfoPtr {
// If the low bit is clear, a pointer to the IdentifierInfo. If the low
// bit is set, the upper 63 bits are the ID number.
mutable uint64_t Ptr = 0;

public:
LazyIdentifierInfoPtr() = default;

explicit LazyIdentifierInfoPtr(const IdentifierInfo *Ptr)
: Ptr(reinterpret_cast<uint64_t>(Ptr)) {}

explicit LazyIdentifierInfoPtr(uint64_t ID) : Ptr((ID << 1) | 0x01) {
assert((ID << 1 >> 1) == ID && "ID must require < 63 bits");
if (ID == 0)
Ptr = 0;
}

LazyIdentifierInfoPtr &operator=(const IdentifierInfo *Ptr) {
this->Ptr = reinterpret_cast<uint64_t>(Ptr);
return *this;
}

LazyIdentifierInfoPtr &operator=(uint64_t ID) {
assert((ID << 1 >> 1) == ID && "IDs must require < 63 bits");
if (ID == 0)
Ptr = 0;
else
Ptr = (ID << 1) | 0x01;

return *this;
}

/// Whether this pointer is non-NULL.
///
/// This operation does not require the AST node to be deserialized.
bool isValid() const { return Ptr != 0; }

/// Whether this pointer is currently stored as ID.
bool isID() const { return Ptr & 0x01; }

IdentifierInfo *getPtr() const {
assert(!isID());
return reinterpret_cast<IdentifierInfo *>(Ptr);
}

uint64_t getID() const {
assert(isID());
return Ptr >> 1;
}
};
}

#endif
12 changes: 3 additions & 9 deletions clang/include/clang/Lex/HeaderSearch.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/DirectoryLookup.h"
#include "clang/Lex/ExternalPreprocessorSource.h"
#include "clang/Lex/HeaderMap.h"
#include "clang/Lex/ModuleMap.h"
#include "llvm/ADT/ArrayRef.h"
Expand Down Expand Up @@ -119,13 +120,6 @@ struct HeaderFileInfo {
LLVM_PREFERRED_TYPE(bool)
unsigned IsValid : 1;

/// The ID number of the controlling macro.
///
/// This ID number will be non-zero when there is a controlling
/// macro whose IdentifierInfo may not yet have been loaded from
/// external storage.
unsigned ControllingMacroID = 0;

/// If this file has a \#ifndef XXX (or equivalent) guard that
/// protects the entire contents of the file, this is the identifier
/// for the macro that controls whether or not it has any effect.
Expand All @@ -134,7 +128,7 @@ struct HeaderFileInfo {
/// the controlling macro of this header, since
/// getControllingMacro() is able to load a controlling macro from
/// external storage.
const IdentifierInfo *ControllingMacro = nullptr;
LazyIdentifierInfoPtr LazyControllingMacro;

/// If this header came from a framework include, this is the name
/// of the framework.
Expand Down Expand Up @@ -580,7 +574,7 @@ class HeaderSearch {
/// no-op \#includes.
void SetFileControllingMacro(FileEntryRef File,
const IdentifierInfo *ControllingMacro) {
getFileInfo(File).ControllingMacro = ControllingMacro;
getFileInfo(File).LazyControllingMacro = ControllingMacro;
}

/// Determine whether this file is intended to be safe from
Expand Down
34 changes: 25 additions & 9 deletions clang/include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "clang/Serialization/SourceLocationEncoding.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/Bitstream/BitCodes.h"
#include "llvm/Support/MathExtras.h"
#include <cassert>
#include <cstdint>

Expand Down Expand Up @@ -59,7 +60,7 @@ const unsigned VERSION_MINOR = 1;
///
/// The ID numbers of identifiers are consecutive (in order of discovery)
/// and start at 1. 0 is reserved for NULL.
using IdentifierID = uint32_t;
using IdentifierID = uint64_t;

/// The number of predefined identifier IDs.
const unsigned int NUM_PREDEF_IDENT_IDS = 1;
Expand All @@ -70,38 +71,53 @@ using DeclID = DeclIDBase::DeclID;

/// An ID number that refers to a type in an AST file.
///
/// The ID of a type is partitioned into two parts: the lower
/// The ID of a type is partitioned into three parts:
/// - the lower
/// three bits are used to store the const/volatile/restrict
/// qualifiers (as with QualType) and the upper bits provide a
/// type index. The type index values are partitioned into two
/// qualifiers (as with QualType).
/// - the upper 29 bits provide a type index in the corresponding
/// module file.
/// - the upper 32 bits provide a module file index.
///
/// The type index values are partitioned into two
/// sets. The values below NUM_PREDEF_TYPE_IDs are predefined type
/// IDs (based on the PREDEF_TYPE_*_ID constants), with 0 as a
/// placeholder for "no type". Values from NUM_PREDEF_TYPE_IDs are
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: maybe explain in a comment that predefined types always have a module file index of 0 (i.e. do not belong to any module file)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

/// other types that have serialized representations.
using TypeID = uint32_t;
using TypeID = uint64_t;

/// A type index; the type ID with the qualifier bits removed.
/// Keep structure alignment 32-bit since the blob is assumed as 32-bit
/// aligned.
class TypeIdx {
uint32_t ModuleFileIndex = 0;
uint32_t Idx = 0;

public:
TypeIdx() = default;
explicit TypeIdx(uint32_t index) : Idx(index) {}
explicit TypeIdx(uint32_t Idx) : ModuleFileIndex(0), Idx(Idx) {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we explicitly pass 0 to the ModuleFileIndex instead? It's very uncommon to have defaulted parameters at the start of the parameter list rather than at the end.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


explicit TypeIdx(uint32_t ModuleFileIdx, uint32_t Idx)
: ModuleFileIndex(ModuleFileIdx), Idx(Idx) {}

uint32_t getModuleFileIndex() const { return ModuleFileIndex; }

uint32_t getIndex() const { return Idx; }
uint64_t getValue() const { return ((uint64_t)ModuleFileIndex << 32) | Idx; }

TypeID asTypeID(unsigned FastQuals) const {
if (Idx == uint32_t(-1))
return TypeID(-1);

return (Idx << Qualifiers::FastWidth) | FastQuals;
unsigned Index = (Idx << Qualifiers::FastWidth) | FastQuals;
return ((uint64_t)ModuleFileIndex << 32) | Index;
}

static TypeIdx fromTypeID(TypeID ID) {
if (ID == TypeID(-1))
return TypeIdx(-1);

return TypeIdx(ID >> Qualifiers::FastWidth);
return TypeIdx(ID >> 32, (ID & llvm::maskTrailingOnes<TypeID>(32)) >>
Qualifiers::FastWidth);
}
};

Expand Down
42 changes: 19 additions & 23 deletions clang/include/clang/Serialization/ASTReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -490,14 +490,6 @@ class ASTReader
/// ID = (I + 1) << FastQual::Width has already been loaded
llvm::PagedVector<QualType> TypesLoaded;

using GlobalTypeMapType =
ContinuousRangeMap<serialization::TypeID, ModuleFile *, 4>;

/// Mapping from global type IDs to the module in which the
/// type resides along with the offset that should be added to the
/// global type ID to produce a local ID.
GlobalTypeMapType GlobalTypeMap;

/// Declarations that have already been loaded from the chain.
///
/// When the pointer at index I is non-NULL, the declaration with ID
Expand Down Expand Up @@ -660,14 +652,6 @@ class ASTReader
/// been loaded.
std::vector<IdentifierInfo *> IdentifiersLoaded;

using GlobalIdentifierMapType =
ContinuousRangeMap<serialization::IdentifierID, ModuleFile *, 4>;

/// Mapping from global identifier IDs to the module in which the
/// identifier resides along with the offset that should be added to the
/// global identifier ID to produce a local ID.
GlobalIdentifierMapType GlobalIdentifierMap;

/// A vector containing macros that have already been
/// loaded.
///
Expand Down Expand Up @@ -1431,8 +1415,8 @@ class ASTReader
RecordLocation(ModuleFile *M, uint64_t O) : F(M), Offset(O) {}
};

QualType readTypeRecord(unsigned Index);
RecordLocation TypeCursorForIndex(unsigned Index);
QualType readTypeRecord(serialization::TypeID ID);
RecordLocation TypeCursorForIndex(serialization::TypeID ID);
void LoadedDecl(unsigned Index, Decl *D);
Decl *ReadDeclRecord(GlobalDeclID ID);
void markIncompleteDeclChain(Decl *D);
Expand Down Expand Up @@ -1539,6 +1523,16 @@ class ASTReader
/// Translate a \param GlobalDeclID to the index of DeclsLoaded array.
unsigned translateGlobalDeclIDToIndex(GlobalDeclID ID) const;

/// Translate an \param IdentifierID ID to the index of IdentifiersLoaded
/// array and the corresponding module file.
std::pair<ModuleFile *, unsigned>
translateIdentifierIDToIndex(serialization::IdentifierID ID) const;

/// Translate an \param TypeID ID to the index of TypesLoaded
/// array and the corresponding module file.
std::pair<ModuleFile *, unsigned>
translateTypeIDToIndex(serialization::TypeID ID) const;

public:
/// Load the AST file and validate its contents against the given
/// Preprocessor.
Expand Down Expand Up @@ -1887,10 +1881,11 @@ class ASTReader
QualType GetType(serialization::TypeID ID);

/// Resolve a local type ID within a given AST file into a type.
QualType getLocalType(ModuleFile &F, unsigned LocalID);
QualType getLocalType(ModuleFile &F, serialization::TypeID LocalID);

/// Map a local type ID within a given AST file into a global type ID.
serialization::TypeID getGlobalTypeID(ModuleFile &F, unsigned LocalID) const;
serialization::TypeID getGlobalTypeID(ModuleFile &F,
serialization::TypeID LocalID) const;

/// Read a type from the current position in the given record, which
/// was read from the given AST file.
Expand All @@ -1912,6 +1907,7 @@ class ASTReader
/// if the declaration is not from a module file.
ModuleFile *getOwningModuleFile(const Decl *D) const;
ModuleFile *getOwningModuleFile(GlobalDeclID ID) const;
ModuleFile *getOwningModuleFile(serialization::TypeID ID) const;

/// Returns the source location for the decl \p ID.
SourceLocation getSourceLocationForDeclID(GlobalDeclID ID);
Expand Down Expand Up @@ -2123,7 +2119,7 @@ class ASTReader
/// Load a selector from disk, registering its ID if it exists.
void LoadSelector(Selector Sel);

void SetIdentifierInfo(unsigned ID, IdentifierInfo *II);
void SetIdentifierInfo(serialization::IdentifierID ID, IdentifierInfo *II);
void SetGloballyVisibleDecls(IdentifierInfo *II,
const SmallVectorImpl<GlobalDeclID> &DeclIDs,
SmallVectorImpl<Decl *> *Decls = nullptr);
Expand All @@ -2150,10 +2146,10 @@ class ASTReader
return DecodeIdentifierInfo(ID);
}

IdentifierInfo *getLocalIdentifier(ModuleFile &M, unsigned LocalID);
IdentifierInfo *getLocalIdentifier(ModuleFile &M, uint64_t LocalID);

serialization::IdentifierID getGlobalIdentifierID(ModuleFile &M,
unsigned LocalID);
uint64_t LocalID);

void resolvePendingMacro(IdentifierInfo *II, const PendingMacroInfo &PMInfo);

Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Serialization/ASTRecordReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ class ASTRecordReader
void readTypeLoc(TypeLoc TL, LocSeq *Seq = nullptr);

/// Map a local type ID within a given AST file to a global type ID.
serialization::TypeID getGlobalTypeID(unsigned LocalID) const {
serialization::TypeID getGlobalTypeID(serialization::TypeID LocalID) const {
return Reader->getGlobalTypeID(*F, LocalID);
}

Expand Down
6 changes: 0 additions & 6 deletions clang/include/clang/Serialization/ModuleFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,9 +310,6 @@ class ModuleFile {
/// Base identifier ID for identifiers local to this module.
serialization::IdentifierID BaseIdentifierID = 0;

/// Remapping table for identifier IDs in this module.
ContinuousRangeMap<uint32_t, int, 2> IdentifierRemap;

/// Actual data for the on-disk hash table of identifiers.
///
/// This pointer points into a memory buffer, where the on-disk hash
Expand Down Expand Up @@ -485,9 +482,6 @@ class ModuleFile {
/// the global type ID space.
serialization::TypeID BaseTypeIndex = 0;

/// Remapping table for type IDs in this module.
ContinuousRangeMap<uint32_t, int, 2> TypeRemap;

// === Miscellaneous ===

/// Diagnostic IDs and their mappings that the user changed.
Expand Down
33 changes: 16 additions & 17 deletions clang/lib/Lex/HeaderSearch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,19 +60,21 @@ ALWAYS_ENABLED_STATISTIC(NumSubFrameworkLookups,

const IdentifierInfo *
HeaderFileInfo::getControllingMacro(ExternalPreprocessorSource *External) {
if (ControllingMacro) {
if (ControllingMacro->isOutOfDate()) {
assert(External && "We must have an external source if we have a "
"controlling macro that is out of date.");
External->updateOutOfDateIdentifier(*ControllingMacro);
}
return ControllingMacro;
}
if (LazyControllingMacro.isID()) {
if (!External)
return nullptr;

if (!ControllingMacroID || !External)
return nullptr;
LazyControllingMacro =
External->GetIdentifier(LazyControllingMacro.getID());
return LazyControllingMacro.getPtr();
}

ControllingMacro = External->GetIdentifier(ControllingMacroID);
IdentifierInfo *ControllingMacro = LazyControllingMacro.getPtr();
if (ControllingMacro && ControllingMacro->isOutOfDate()) {
assert(External && "We must have an external source if we have a "
"controlling macro that is out of date.");
External->updateOutOfDateIdentifier(*ControllingMacro);
}
return ControllingMacro;
}

Expand Down Expand Up @@ -1341,10 +1343,8 @@ static void mergeHeaderFileInfo(HeaderFileInfo &HFI,
mergeHeaderFileInfoModuleBits(HFI, OtherHFI.isModuleHeader,
OtherHFI.isTextualModuleHeader);

if (!HFI.ControllingMacro && !HFI.ControllingMacroID) {
HFI.ControllingMacro = OtherHFI.ControllingMacro;
HFI.ControllingMacroID = OtherHFI.ControllingMacroID;
}
if (!HFI.LazyControllingMacro.isValid())
HFI.LazyControllingMacro = OtherHFI.LazyControllingMacro;

HFI.DirInfo = OtherHFI.DirInfo;
HFI.External = (!HFI.IsValid || HFI.External);
Expand Down Expand Up @@ -1419,8 +1419,7 @@ bool HeaderSearch::isFileMultipleIncludeGuarded(FileEntryRef File) const {
// once. Note that we dor't check for #import, because that's not a property
// of the file itself.
if (auto *HFI = getExistingFileInfo(File))
return HFI->isPragmaOnce || HFI->ControllingMacro ||
HFI->ControllingMacroID;
return HFI->isPragmaOnce || HFI->LazyControllingMacro.isValid();
return false;
}

Expand Down
Loading