Skip to content

Commit

Permalink
[HeaderSearch] Introduce LazyIdentifierInfoPtr for Controlling Macro …
Browse files Browse the repository at this point in the history
…in HeaderFileInfo

This patch is helpful to reduce 32 bits for HeaderFileInfo by combining
a uint32_t and pointer into a tagged pointer.

This is reviewed as part of
#92085 and required to be split
as a separate commit
  • Loading branch information
ChuanqiXu9 committed Jun 20, 2024
1 parent 480a788 commit da2ad44
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 30 deletions.
52 changes: 52 additions & 0 deletions clang/include/clang/Lex/ExternalPreprocessorSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,58 @@ class ExternalPreprocessorSource {
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 @@ -121,13 +122,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 @@ -136,7 +130,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 @@ -582,7 +576,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
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 @@ -1348,10 +1350,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 @@ -1426,8 +1426,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
2 changes: 1 addition & 1 deletion clang/lib/Serialization/ASTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2092,7 +2092,7 @@ HeaderFileInfoTrait::ReadData(internal_key_ref key, const unsigned char *d,
HFI.isPragmaOnce |= (Flags >> 4) & 0x01;
HFI.DirInfo = (Flags >> 1) & 0x07;
HFI.IndexHeaderMapHeader = Flags & 0x01;
HFI.ControllingMacroID = Reader.getGlobalIdentifierID(
HFI.LazyControllingMacro = Reader.getGlobalIdentifierID(
M, endian::readNext<uint32_t, llvm::endianness::little>(d));
if (unsigned FrameworkOffset =
endian::readNext<uint32_t, llvm::endianness::little>(d)) {
Expand Down
7 changes: 4 additions & 3 deletions clang/lib/Serialization/ASTWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2028,10 +2028,11 @@ namespace {
| Data.HFI.IndexHeaderMapHeader;
LE.write<uint8_t>(Flags);

if (!Data.HFI.ControllingMacro)
LE.write<uint32_t>(Data.HFI.ControllingMacroID);
if (Data.HFI.LazyControllingMacro.isID())
LE.write<IdentifierID>(Data.HFI.LazyControllingMacro.getID());
else
LE.write<uint32_t>(Writer.getIdentifierRef(Data.HFI.ControllingMacro));
LE.write<IdentifierID>(
Writer.getIdentifierRef(Data.HFI.LazyControllingMacro.getPtr()));

unsigned Offset = 0;
if (!Data.HFI.Framework.empty()) {
Expand Down

0 comments on commit da2ad44

Please sign in to comment.