Reland 'Update llvm::Registry to work for LLVM shared library builds on windows' (#109024) (#112640)
Fix missing extern templates for llvm::Registry use in other projects of llvm Windows doesn't implicitly import and merge exported symbols across shared libraries like Linux does so we need to explicitly export/import each instantiation of llvm::Registry. Updated LLVM_INSTANTIATE_REGISTRY to just be a full explicit template instantiation. This is part of the work to enable LLVM_BUILD_LLVM_DYLIB and LLVM plugins on window.
This commit is contained in:
@@ -55,4 +55,8 @@ std::string getTagType(TagTypeKind AS);
|
||||
} // namespace doc
|
||||
} // namespace clang
|
||||
|
||||
namespace llvm {
|
||||
extern template class Registry<clang::doc::Generator>;
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_GENERATOR_H
|
||||
|
||||
@@ -18,4 +18,8 @@ using ClangTidyModuleRegistry = llvm::Registry<ClangTidyModule>;
|
||||
|
||||
} // namespace clang::tidy
|
||||
|
||||
namespace llvm {
|
||||
extern template class Registry<clang::tidy::ClangTidyModule>;
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYMODULEREGISTRY_H
|
||||
|
||||
@@ -133,4 +133,8 @@ typedef llvm::Registry<URIScheme> URISchemeRegistry;
|
||||
} // namespace clangd
|
||||
} // namespace clang
|
||||
|
||||
namespace llvm {
|
||||
extern template class Registry<clang::clangd::URIScheme>;
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_URI_H
|
||||
|
||||
@@ -147,4 +147,8 @@ prepareTweak(StringRef ID, const Tweak::Selection &S,
|
||||
} // namespace clangd
|
||||
} // namespace clang
|
||||
|
||||
namespace llvm {
|
||||
extern template class Registry<clang::clangd::Tweak>;
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
||||
|
||||
@@ -46,4 +46,8 @@ using IncludeSpellingStrategy = llvm::Registry<IncludeSpeller>;
|
||||
std::string spellHeader(const IncludeSpeller::Input &Input);
|
||||
} // namespace clang::include_cleaner
|
||||
|
||||
namespace llvm {
|
||||
extern template class Registry<clang::include_cleaner::IncludeSpeller>;
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "clang/Basic/AttrSubjectMatchRules.h"
|
||||
#include "clang/Basic/AttributeCommonInfo.h"
|
||||
#include "clang/Support/Compiler.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/Support/Registry.h"
|
||||
#include <climits>
|
||||
@@ -175,4 +176,8 @@ const std::list<std::unique_ptr<ParsedAttrInfo>> &getAttributePluginInstances();
|
||||
|
||||
} // namespace clang
|
||||
|
||||
namespace llvm {
|
||||
extern template class CLANG_TEMPLATE_ABI Registry<clang::ParsedAttrInfo>;
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_CLANG_BASIC_PARSEDATTRINFO_H
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#define LLVM_CLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H
|
||||
|
||||
#include "clang/Frontend/FrontendAction.h"
|
||||
#include "clang/Support/Compiler.h"
|
||||
#include "llvm/Support/Registry.h"
|
||||
|
||||
namespace clang {
|
||||
@@ -23,4 +24,8 @@ using FrontendPluginRegistry = llvm::Registry<PluginASTAction>;
|
||||
|
||||
} // namespace clang
|
||||
|
||||
namespace llvm {
|
||||
extern template class CLANG_TEMPLATE_ABI Registry<clang::PluginASTAction>;
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_CLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "clang/Lex/PPEmbedParameters.h"
|
||||
#include "clang/Lex/Token.h"
|
||||
#include "clang/Lex/TokenLexer.h"
|
||||
#include "clang/Support/Compiler.h"
|
||||
#include "llvm/ADT/APSInt.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
@@ -3060,4 +3061,8 @@ using PragmaHandlerRegistry = llvm::Registry<PragmaHandler>;
|
||||
|
||||
} // namespace clang
|
||||
|
||||
namespace llvm {
|
||||
extern template class CLANG_TEMPLATE_ABI Registry<clang::PragmaHandler>;
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_CLANG_LEX_PREPROCESSOR_H
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#ifndef LLVM_CLANG_TOOLING_COMPILATIONDATABASEPLUGINREGISTRY_H
|
||||
#define LLVM_CLANG_TOOLING_COMPILATIONDATABASEPLUGINREGISTRY_H
|
||||
|
||||
#include "clang/Support/Compiler.h"
|
||||
#include "clang/Tooling/CompilationDatabase.h"
|
||||
#include "llvm/Support/Registry.h"
|
||||
|
||||
@@ -42,4 +43,9 @@ using CompilationDatabasePluginRegistry =
|
||||
} // namespace tooling
|
||||
} // namespace clang
|
||||
|
||||
namespace llvm {
|
||||
extern template class CLANG_TEMPLATE_ABI
|
||||
Registry<clang::tooling::CompilationDatabasePlugin>;
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_CLANG_TOOLING_COMPILATIONDATABASEPLUGINREGISTRY_H
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#ifndef LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H
|
||||
#define LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H
|
||||
|
||||
#include "clang/Support/Compiler.h"
|
||||
#include "clang/Tooling/Execution.h"
|
||||
#include "llvm/Support/Registry.h"
|
||||
|
||||
@@ -20,4 +21,9 @@ using ToolExecutorPluginRegistry = llvm::Registry<ToolExecutorPlugin>;
|
||||
} // namespace tooling
|
||||
} // namespace clang
|
||||
|
||||
namespace llvm {
|
||||
extern template class CLANG_TEMPLATE_ABI
|
||||
Registry<clang::tooling::ToolExecutorPlugin>;
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H
|
||||
|
||||
@@ -25,4 +25,8 @@ using FrontendPluginRegistry = llvm::Registry<PluginParseTreeAction>;
|
||||
|
||||
} // namespace Fortran::frontend
|
||||
|
||||
namespace llvm {
|
||||
extern template class Registry<Fortran::frontend::PluginParseTreeAction>;
|
||||
}
|
||||
|
||||
#endif // FORTRAN_FRONTEND_FRONTENDPLUGINREGISTRY_H
|
||||
|
||||
@@ -34,6 +34,8 @@ class StackMaps;
|
||||
/// defaults from Registry.
|
||||
using GCMetadataPrinterRegistry = Registry<GCMetadataPrinter>;
|
||||
|
||||
extern template class LLVM_TEMPLATE_ABI Registry<GCMetadataPrinter>;
|
||||
|
||||
/// GCMetadataPrinter - Emits GC metadata as assembly code. Instances are
|
||||
/// created, managed, and owned by the AsmPrinter.
|
||||
class GCMetadataPrinter {
|
||||
|
||||
@@ -141,6 +141,8 @@ public:
|
||||
/// GCMetadataPrinterRegistery as well.
|
||||
using GCRegistry = Registry<GCStrategy>;
|
||||
|
||||
extern template class LLVM_TEMPLATE_ABI Registry<GCStrategy>;
|
||||
|
||||
/// Lookup the GCStrategy object associated with the given gc name.
|
||||
std::unique_ptr<GCStrategy> getGCStrategy(const StringRef Name);
|
||||
|
||||
|
||||
@@ -153,6 +153,12 @@
|
||||
/// exported when llvm is built as a shared library with everything else that is
|
||||
/// unannotated will have internal visibility.
|
||||
///
|
||||
/// LLVM_ABI_EXPORT is for the special case for things like plugin symbol
|
||||
/// declarations or definitions where we don't want the macro to be switching
|
||||
/// between dllexport and dllimport on windows based on what codebase is being
|
||||
/// built, it will only be dllexport. For non windows platforms this macro
|
||||
/// behaves the same as LLVM_ABI.
|
||||
///
|
||||
/// LLVM_EXPORT_TEMPLATE is used on explicit template instantiations in source
|
||||
/// files that were declared extern in a header. This macro is only set as a
|
||||
/// compiler export attribute on windows, on other platforms it does nothing.
|
||||
@@ -179,6 +185,7 @@
|
||||
#define LLVM_ABI
|
||||
#define LLVM_TEMPLATE_ABI
|
||||
#define LLVM_EXPORT_TEMPLATE
|
||||
#define LLVM_ABI_EXPORT
|
||||
#elif defined(_WIN32) && !defined(__MINGW32__)
|
||||
#if defined(LLVM_EXPORTS)
|
||||
#define LLVM_ABI __declspec(dllexport)
|
||||
@@ -189,19 +196,23 @@
|
||||
#define LLVM_TEMPLATE_ABI __declspec(dllimport)
|
||||
#define LLVM_EXPORT_TEMPLATE
|
||||
#endif
|
||||
#define LLVM_ABI_EXPORT __declspec(dllexport)
|
||||
#elif defined(__ELF__) || defined(__MINGW32__) || defined(_AIX)
|
||||
#define LLVM_ABI LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
|
||||
#define LLVM_TEMPLATE_ABI LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
|
||||
#define LLVM_EXPORT_TEMPLATE
|
||||
#define LLVM_ABI_EXPORT LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
|
||||
#elif defined(__MACH__) || defined(__WASM__)
|
||||
#define LLVM_ABI LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
|
||||
#define LLVM_TEMPLATE_ABI
|
||||
#define LLVM_EXPORT_TEMPLATE
|
||||
#define LLVM_ABI_EXPORT LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
|
||||
#endif
|
||||
#else
|
||||
#define LLVM_ABI
|
||||
#define LLVM_TEMPLATE_ABI
|
||||
#define LLVM_EXPORT_TEMPLATE
|
||||
#define LLVM_ABI_EXPORT
|
||||
#endif
|
||||
#define LLVM_C_ABI LLVM_ABI
|
||||
#endif
|
||||
|
||||
@@ -53,7 +53,13 @@ namespace llvm {
|
||||
Registry() = delete;
|
||||
|
||||
friend class node;
|
||||
static node *Head, *Tail;
|
||||
// These must be must two separate declarations to workaround a 20 year
|
||||
// old MSVC bug with dllexport and multiple static fields in the same
|
||||
// declaration causing error C2487 "member of dll interface class may not
|
||||
// be declared with dll interface".
|
||||
// https://developercommunity.visualstudio.com/t/c2487-in-dllexport-class-with-static-members/69878
|
||||
static node *Head;
|
||||
static node *Tail;
|
||||
|
||||
public:
|
||||
/// Node in linked list of entries.
|
||||
@@ -76,7 +82,13 @@ namespace llvm {
|
||||
/// add a node to the executable's registry. Therefore it's not defined here
|
||||
/// to avoid it being instantiated in the plugin and is instead defined in
|
||||
/// the executable (see LLVM_INSTANTIATE_REGISTRY below).
|
||||
static void add_node(node *N);
|
||||
static void add_node(node *N) {
|
||||
if (Tail)
|
||||
Tail->Next = N;
|
||||
else
|
||||
Head = N;
|
||||
Tail = N;
|
||||
}
|
||||
|
||||
/// Iterators for registry entries.
|
||||
///
|
||||
@@ -95,7 +107,7 @@ namespace llvm {
|
||||
|
||||
// begin is not defined here in order to avoid usage of an undefined static
|
||||
// data member, instead it's instantiated by LLVM_INSTANTIATE_REGISTRY.
|
||||
static iterator begin();
|
||||
static iterator begin() { return iterator(Head); }
|
||||
static iterator end() { return iterator(nullptr); }
|
||||
|
||||
static iterator_range<iterator> entries() {
|
||||
@@ -124,36 +136,28 @@ namespace llvm {
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#ifdef _WIN32
|
||||
/// Instantiate a registry class.
|
||||
///
|
||||
/// This provides template definitions of add_node, begin, and the Head and Tail
|
||||
/// pointers, then explicitly instantiates them. We could explicitly specialize
|
||||
/// them, instead of the two-step process of define then instantiate, but
|
||||
/// strictly speaking that's not allowed by the C++ standard (we would need to
|
||||
/// have explicit specialization declarations in all translation units where the
|
||||
/// specialization is used) so we don't.
|
||||
#define LLVM_INSTANTIATE_REGISTRY(REGISTRY_CLASS) \
|
||||
namespace llvm { \
|
||||
template<typename T> typename Registry<T>::node *Registry<T>::Head = nullptr;\
|
||||
template<typename T> typename Registry<T>::node *Registry<T>::Tail = nullptr;\
|
||||
template<typename T> \
|
||||
void Registry<T>::add_node(typename Registry<T>::node *N) { \
|
||||
if (Tail) \
|
||||
Tail->Next = N; \
|
||||
else \
|
||||
Head = N; \
|
||||
Tail = N; \
|
||||
} \
|
||||
template<typename T> typename Registry<T>::iterator Registry<T>::begin() { \
|
||||
return iterator(Head); \
|
||||
} \
|
||||
template REGISTRY_CLASS::node *Registry<REGISTRY_CLASS::type>::Head; \
|
||||
template REGISTRY_CLASS::node *Registry<REGISTRY_CLASS::type>::Tail; \
|
||||
template \
|
||||
void Registry<REGISTRY_CLASS::type>::add_node(REGISTRY_CLASS::node*); \
|
||||
template REGISTRY_CLASS::iterator Registry<REGISTRY_CLASS::type>::begin(); \
|
||||
#define LLVM_INSTANTIATE_REGISTRY(REGISTRY_CLASS) \
|
||||
namespace llvm { \
|
||||
template <typename T> \
|
||||
typename Registry<T>::node *Registry<T>::Head = nullptr; \
|
||||
template <typename T> \
|
||||
typename Registry<T>::node *Registry<T>::Tail = nullptr; \
|
||||
template class LLVM_ABI_EXPORT Registry<REGISTRY_CLASS::type>; \
|
||||
}
|
||||
#else
|
||||
#define LLVM_INSTANTIATE_REGISTRY(REGISTRY_CLASS) \
|
||||
namespace llvm { \
|
||||
template <typename T> \
|
||||
typename Registry<T>::node *Registry<T>::Head = nullptr; \
|
||||
template <typename T> \
|
||||
typename Registry<T>::node *Registry<T>::Tail = nullptr; \
|
||||
template class Registry<REGISTRY_CLASS::type>; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // LLVM_SUPPORT_REGISTRY_H
|
||||
|
||||
Reference in New Issue
Block a user