Skip to content

[llvm-project] Backport upstream version of lazy template loading #17722

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 8, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 2 additions & 2 deletions core/dictgen/src/Scanner.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,6 @@ inline static bool IsElementPresent(const std::vector<const T*> &v, T *el){
using namespace ROOT;
using namespace clang;

extern cling::Interpreter *gInterp;

const char* RScanner::fgClangDeclKey = "ClangDecl"; // property key used for connection with Clang objects
const char* RScanner::fgClangFuncKey = "ClangFunc"; // property key for demangled names

Expand Down Expand Up @@ -1059,6 +1057,8 @@ void RScanner::Scan(const clang::ASTContext &C)
std::cout<<"File name detected"<<std::endl;
}

cling::Interpreter::PushTransactionRAII RAII(const_cast<cling::Interpreter *>(&fInterpreter));

if (fScanType == EScanType::kTwoPasses)
TraverseDecl(C.getTranslationUnitDecl());

Expand Down
9 changes: 9 additions & 0 deletions interpreter/cling/lib/Interpreter/InterpreterCallbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,15 @@ namespace cling {
return m_Source->FindExternalVisibleDeclsByName(DC, Name);
}

bool LoadExternalSpecializations(const Decl* D, bool OnlyPartial) override {
return m_Source->LoadExternalSpecializations(D, OnlyPartial);
}

bool LoadExternalSpecializations(
const Decl* D, ArrayRef<TemplateArgument> TemplateArgs) override {
return m_Source->LoadExternalSpecializations(D, TemplateArgs);
}

virtual void completeVisibleDeclsMap(const DeclContext* DC) override {
m_Source->completeVisibleDeclsMap(DC);
}
Expand Down
39 changes: 7 additions & 32 deletions interpreter/llvm-project/clang/include/clang/AST/DeclTemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -267,9 +267,6 @@ class TemplateArgumentList final
static TemplateArgumentList *CreateCopy(ASTContext &Context,
ArrayRef<TemplateArgument> Args);

/// \brief Create hash for the given arguments.
static unsigned ComputeODRHash(ArrayRef<TemplateArgument> Args);

/// Construct a new, temporary template argument list on the stack.
///
/// The template argument list does not own the template arguments
Expand Down Expand Up @@ -752,25 +749,6 @@ class RedeclarableTemplateDecl : public TemplateDecl,
}

void anchor() override;
struct LazySpecializationInfo {
uint32_t DeclID = ~0U;
unsigned ODRHash = ~0U;
bool IsPartial = false;
LazySpecializationInfo(uint32_t ID, unsigned Hash = ~0U,
bool Partial = false)
: DeclID(ID), ODRHash(Hash), IsPartial(Partial) { }
LazySpecializationInfo() { }
bool operator<(const LazySpecializationInfo &Other) const {
return DeclID < Other.DeclID;
}
bool operator==(const LazySpecializationInfo &Other) const {
assert((DeclID != Other.DeclID || ODRHash == Other.ODRHash) &&
"Hashes differ!");
assert((DeclID != Other.DeclID || IsPartial == Other.IsPartial) &&
"Both must be the same kinds!");
return DeclID == Other.DeclID;
}
};

protected:
template <typename EntryType> struct SpecEntryTraits {
Expand Down Expand Up @@ -814,16 +792,20 @@ class RedeclarableTemplateDecl : public TemplateDecl,

void loadLazySpecializationsImpl(bool OnlyPartial = false) const;

void loadLazySpecializationsImpl(llvm::ArrayRef<TemplateArgument> Args,
bool loadLazySpecializationsImpl(llvm::ArrayRef<TemplateArgument> Args,
TemplateParameterList *TPL = nullptr) const;

Decl *loadLazySpecializationImpl(LazySpecializationInfo &LazySpecInfo) const;

template <class EntryType, typename ...ProfileArguments>
typename SpecEntryTraits<EntryType>::DeclType*
findSpecializationImpl(llvm::FoldingSetVector<EntryType> &Specs,
void *&InsertPos, ProfileArguments &&...ProfileArgs);

template <class EntryType, typename... ProfileArguments>
typename SpecEntryTraits<EntryType>::DeclType *
findSpecializationLocally(llvm::FoldingSetVector<EntryType> &Specs,
void *&InsertPos,
ProfileArguments &&...ProfileArgs);

template <class Derived, class EntryType>
void addSpecializationImpl(llvm::FoldingSetVector<EntryType> &Specs,
EntryType *Entry, void *InsertPos);
Expand All @@ -839,13 +821,6 @@ class RedeclarableTemplateDecl : public TemplateDecl,
llvm::PointerIntPair<RedeclarableTemplateDecl*, 1, bool>
InstantiatedFromMember;

/// If non-null, points to an array of specializations (including
/// partial specializations) known only by their external declaration IDs.
///
/// The first value in the array is the number of specializations/partial
/// specializations that follow.
LazySpecializationInfo *LazySpecializations = nullptr;

/// The set of "injected" template arguments used within this
/// template.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,21 @@
virtual bool
FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name);

/// Load all the external specializations for the Decl \param D if \param
/// OnlyPartial is false. Otherwise, load all the external **partial**
/// specializations for the \param D.
///
/// Return true if any new specializations get loaded. Return false otherwise.
virtual bool LoadExternalSpecializations(const Decl *D, bool OnlyPartial);

/// Load all the specializations for the Decl \param D with the same template
/// args specified by \param TemplateArgs.
///
/// Return true if any new specializations get loaded. Return false otherwise.
virtual bool
LoadExternalSpecializations(const Decl *D,
ArrayRef<TemplateArgument> TemplateArgs);

/// Ensures that the table of all visible declarations inside this
/// context is up to date.
///
Expand Down Expand Up @@ -375,7 +390,7 @@
if (isOffset()) {
assert(Source &&
"Cannot deserialize a lazy pointer without an AST source");
Ptr = reinterpret_cast<uint64_t>((Source->*Get)(Ptr >> 1));

Check warning on line 393 in interpreter/llvm-project/clang/include/clang/AST/ExternalASTSource.h

View workflow job for this annotation

GitHub Actions / fedora41 LLVM_ENABLE_ASSERTIONS=On

‘this’ pointer is null [-Wnonnull]

Check warning on line 393 in interpreter/llvm-project/clang/include/clang/AST/ExternalASTSource.h

View workflow job for this annotation

GitHub Actions / fedora41 LLVM_ENABLE_ASSERTIONS=On

‘this’ pointer is null [-Wnonnull]

Check warning on line 393 in interpreter/llvm-project/clang/include/clang/AST/ExternalASTSource.h

View workflow job for this annotation

GitHub Actions / fedora41 LLVM_ENABLE_ASSERTIONS=On

‘this’ pointer is null [-Wnonnull]

Check warning on line 393 in interpreter/llvm-project/clang/include/clang/AST/ExternalASTSource.h

View workflow job for this annotation

GitHub Actions / fedora41 LLVM_ENABLE_ASSERTIONS=On

‘this’ pointer is null [-Wnonnull]

Check warning on line 393 in interpreter/llvm-project/clang/include/clang/AST/ExternalASTSource.h

View workflow job for this annotation

GitHub Actions / fedora41 LLVM_ENABLE_ASSERTIONS=On

‘this’ pointer is null [-Wnonnull]

Check warning on line 393 in interpreter/llvm-project/clang/include/clang/AST/ExternalASTSource.h

View workflow job for this annotation

GitHub Actions / fedora41 LLVM_ENABLE_ASSERTIONS=On

‘this’ pointer is null [-Wnonnull]

Check warning on line 393 in interpreter/llvm-project/clang/include/clang/AST/ExternalASTSource.h

View workflow job for this annotation

GitHub Actions / fedora41 LLVM_ENABLE_ASSERTIONS=On

‘this’ pointer is null [-Wnonnull]

Check warning on line 393 in interpreter/llvm-project/clang/include/clang/AST/ExternalASTSource.h

View workflow job for this annotation

GitHub Actions / fedora41 LLVM_ENABLE_ASSERTIONS=On

‘this’ pointer is null [-Wnonnull]

Check warning on line 393 in interpreter/llvm-project/clang/include/clang/AST/ExternalASTSource.h

View workflow job for this annotation

GitHub Actions / fedora41 LLVM_ENABLE_ASSERTIONS=On

‘this’ pointer is null [-Wnonnull]

Check warning on line 393 in interpreter/llvm-project/clang/include/clang/AST/ExternalASTSource.h

View workflow job for this annotation

GitHub Actions / fedora41 LLVM_ENABLE_ASSERTIONS=On

‘this’ pointer is null [-Wnonnull]

Check warning on line 393 in interpreter/llvm-project/clang/include/clang/AST/ExternalASTSource.h

View workflow job for this annotation

GitHub Actions / debian125 LLVM_ENABLE_ASSERTIONS=On, CMAKE_CXX_STANDARD=20, dev=ON

‘this’ pointer is null [-Wnonnull]

Check warning on line 393 in interpreter/llvm-project/clang/include/clang/AST/ExternalASTSource.h

View workflow job for this annotation

GitHub Actions / debian125 LLVM_ENABLE_ASSERTIONS=On, CMAKE_CXX_STANDARD=20, dev=ON

‘this’ pointer is null [-Wnonnull]

Check warning on line 393 in interpreter/llvm-project/clang/include/clang/AST/ExternalASTSource.h

View workflow job for this annotation

GitHub Actions / debian125 LLVM_ENABLE_ASSERTIONS=On, CMAKE_CXX_STANDARD=20, dev=ON

‘this’ pointer is null [-Wnonnull]

Check warning on line 393 in interpreter/llvm-project/clang/include/clang/AST/ExternalASTSource.h

View workflow job for this annotation

GitHub Actions / debian125 LLVM_ENABLE_ASSERTIONS=On, CMAKE_CXX_STANDARD=20, dev=ON

‘this’ pointer is null [-Wnonnull]

Check warning on line 393 in interpreter/llvm-project/clang/include/clang/AST/ExternalASTSource.h

View workflow job for this annotation

GitHub Actions / debian125 LLVM_ENABLE_ASSERTIONS=On, CMAKE_CXX_STANDARD=20, dev=ON

‘this’ pointer is null [-Wnonnull]

Check warning on line 393 in interpreter/llvm-project/clang/include/clang/AST/ExternalASTSource.h

View workflow job for this annotation

GitHub Actions / debian125 LLVM_ENABLE_ASSERTIONS=On, CMAKE_CXX_STANDARD=20, dev=ON

‘this’ pointer is null [-Wnonnull]

Check warning on line 393 in interpreter/llvm-project/clang/include/clang/AST/ExternalASTSource.h

View workflow job for this annotation

GitHub Actions / debian125 LLVM_ENABLE_ASSERTIONS=On, CMAKE_CXX_STANDARD=20, dev=ON

‘this’ pointer is null [-Wnonnull]

Check warning on line 393 in interpreter/llvm-project/clang/include/clang/AST/ExternalASTSource.h

View workflow job for this annotation

GitHub Actions / debian125 LLVM_ENABLE_ASSERTIONS=On, CMAKE_CXX_STANDARD=20, dev=ON

‘this’ pointer is null [-Wnonnull]

Check warning on line 393 in interpreter/llvm-project/clang/include/clang/AST/ExternalASTSource.h

View workflow job for this annotation

GitHub Actions / debian125 LLVM_ENABLE_ASSERTIONS=On, CMAKE_CXX_STANDARD=20, dev=ON

‘this’ pointer is null [-Wnonnull]

Check warning on line 393 in interpreter/llvm-project/clang/include/clang/AST/ExternalASTSource.h

View workflow job for this annotation

GitHub Actions / debian125 LLVM_ENABLE_ASSERTIONS=On, CMAKE_CXX_STANDARD=20, dev=ON

‘this’ pointer is null [-Wnonnull]
}
return reinterpret_cast<T*>(Ptr);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ class MultiplexExternalSemaSource : public ExternalSemaSource {
bool FindExternalVisibleDeclsByName(const DeclContext *DC,
DeclarationName Name) override;

bool LoadExternalSpecializations(const Decl *D, bool OnlyPartial) override;

bool
LoadExternalSpecializations(const Decl *D,
ArrayRef<TemplateArgument> TemplateArgs) override;

/// Ensures that the table of all visible declarations inside this
/// context is up to date.
void completeVisibleDeclsMap(const DeclContext *DC) override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,13 @@ enum ASTRecordTypes {
/// Record code for an unterminated \#pragma clang assume_nonnull begin
/// recorded in a preamble.
PP_ASSUME_NONNULL_LOC = 67,

/// Record code for updated specialization
UPDATE_SPECIALIZATION = 73,

CXX_ADDED_TEMPLATE_SPECIALIZATION = 74,

CXX_ADDED_TEMPLATE_PARTIAL_SPECIALIZATION = 75,
};

/// Record types used within a source manager block.
Expand Down Expand Up @@ -1523,6 +1530,12 @@ enum DeclCode {
/// An ImplicitConceptSpecializationDecl record.
DECL_IMPLICIT_CONCEPT_SPECIALIZATION,

// A decls specilization record.
DECL_SPECIALIZATIONS,

// A decls specilization record.
DECL_PARTIAL_SPECIALIZATIONS,

DECL_LAST = DECL_IMPLICIT_CONCEPT_SPECIALIZATION
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,9 @@ class ASTIdentifierLookupTrait;
/// The on-disk hash table(s) used for DeclContext name lookup.
struct DeclContextLookupTable;

/// The on-disk hash table(s) used for specialization decls.
struct LazySpecializationInfoLookupTable;

} // namespace reader

} // namespace serialization
Expand Down Expand Up @@ -603,21 +606,41 @@ class ASTReader
llvm::DenseMap<const DeclContext *,
serialization::reader::DeclContextLookupTable> Lookups;

using SpecLookupTableTy =
llvm::DenseMap<const Decl *,
serialization::reader::LazySpecializationInfoLookupTable>;
/// Map from decls to specialized decls.
SpecLookupTableTy SpecializationsLookups;
/// Split partial specialization from specialization to speed up lookups.
SpecLookupTableTy PartialSpecializationsLookups;

bool LoadExternalSpecializationsImpl(SpecLookupTableTy &SpecLookups,
const Decl *D);
bool LoadExternalSpecializationsImpl(SpecLookupTableTy &SpecLookups,
const Decl *D,
ArrayRef<TemplateArgument> TemplateArgs);

// Updates for visible decls can occur for other contexts than just the
// TU, and when we read those update records, the actual context may not
// be available yet, so have this pending map using the ID as a key. It
// will be realized when the context is actually loaded.
struct PendingVisibleUpdate {
// will be realized when the data is actually loaded.
struct UpdateData {
ModuleFile *Mod;
const unsigned char *Data;
};
using DeclContextVisibleUpdates = SmallVector<PendingVisibleUpdate, 1>;
using DeclContextVisibleUpdates = SmallVector<UpdateData, 1>;

/// Updates to the visible declarations of declaration contexts that
/// haven't been loaded yet.
llvm::DenseMap<serialization::DeclID, DeclContextVisibleUpdates>
PendingVisibleUpdates;

using SpecializationsUpdate = SmallVector<UpdateData, 1>;
using SpecializationsUpdateMap =
llvm::DenseMap<serialization::GlobalDeclID, SpecializationsUpdate>;
SpecializationsUpdateMap PendingSpecializationsUpdates;
SpecializationsUpdateMap PendingPartialSpecializationsUpdates;

/// The set of C++ or Objective-C classes that have forward
/// declarations that have not yet been linked to their definitions.
llvm::SmallPtrSet<Decl *, 4> PendingDefinitions;
Expand All @@ -644,6 +667,11 @@ class ASTReader
llvm::BitstreamCursor &Cursor,
uint64_t Offset, serialization::DeclID ID);

bool ReadSpecializations(ModuleFile &M, llvm::BitstreamCursor &Cursor,
uint64_t Offset, Decl *D, bool IsPartial);
void AddSpecializations(const Decl *D, const unsigned char *Data,
ModuleFile &M, bool IsPartial);

/// A vector containing identifiers that have already been
/// loaded.
///
Expand Down Expand Up @@ -1350,6 +1378,14 @@ class ASTReader
const serialization::reader::DeclContextLookupTable *
getLoadedLookupTables(DeclContext *Primary) const;

/// Get the loaded specializations lookup tables for \p D,
/// if any.
serialization::reader::LazySpecializationInfoLookupTable *
getLoadedSpecializationsLookupTables(const Decl *D, bool IsPartial);

/// If we have any unloaded specialization for \p D
bool haveUnloadedSpecializations(const Decl *D) const;

private:
struct ImportedModule {
ModuleFile *Mod;
Expand Down Expand Up @@ -1989,6 +2025,12 @@ class ASTReader
unsigned BlockID,
uint64_t *StartOfBlockOffset = nullptr);

bool LoadExternalSpecializations(const Decl *D, bool OnlyPartial) override;

bool
LoadExternalSpecializations(const Decl *D,
ArrayRef<TemplateArgument> TemplateArgs) override;

/// Finds all the visible declarations with a given name.
/// The current implementation of this method just loads the entire
/// lookup table as unmaterialized references.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,13 @@ class ASTWriter : public ASTDeserializationListener,
/// record containing modifications to them.
DeclUpdateMap DeclUpdates;

/// Mapping from decl templates and its new specialization in the
/// current TU.
using SpecializationUpdateMap =
llvm::MapVector<const NamedDecl *, SmallVector<const Decl *>>;
SpecializationUpdateMap SpecializationsUpdates;
SpecializationUpdateMap PartialSpecializationsUpdates;

using FirstLatestDeclMap = llvm::DenseMap<Decl *, Decl *>;

/// Map of first declarations from a chained PCH that point to the
Expand Down Expand Up @@ -527,6 +534,12 @@ class ASTWriter : public ASTDeserializationListener,
bool isLookupResultExternal(StoredDeclsList &Result, DeclContext *DC);
bool isLookupResultEntirelyExternal(StoredDeclsList &Result, DeclContext *DC);

void GenerateSpecializationInfoLookupTable(
const NamedDecl *D, llvm::SmallVectorImpl<const Decl *> &Specializations,
llvm::SmallVectorImpl<char> &LookupTable, bool IsPartial);
uint64_t WriteSpecializationInfoLookupTable(
const NamedDecl *D, llvm::SmallVectorImpl<const Decl *> &Specializations,
bool IsPartial);
void GenerateNameLookupTable(const DeclContext *DC,
llvm::SmallVectorImpl<char> &LookupTable);
uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC);
Expand All @@ -538,6 +551,7 @@ class ASTWriter : public ASTDeserializationListener,
void WriteReferencedSelectorsPool(Sema &SemaRef);
void WriteIdentifierTable(Preprocessor &PP, IdentifierResolver &IdResolver,
bool IsModule);
void WriteSpecializationsUpdates(bool IsPartial);
void WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord);
void WriteDeclContextVisibleUpdate(const DeclContext *DC);
void WriteFPPragmaOptions(const FPOptionsOverride &Opts);
Expand All @@ -564,6 +578,9 @@ class ASTWriter : public ASTDeserializationListener,
unsigned DeclEnumAbbrev = 0;
unsigned DeclObjCIvarAbbrev = 0;
unsigned DeclCXXMethodAbbrev = 0;
unsigned DeclSpecializationsAbbrev = 0;
unsigned DeclPartialSpecializationsAbbrev = 0;

unsigned DeclDependentNonTemplateCXXMethodAbbrev = 0;
unsigned DeclTemplateCXXMethodAbbrev = 0;
unsigned DeclMemberSpecializedCXXMethodAbbrev = 0;
Expand Down
Loading
Loading