Skip to content

Commit 00cd1a0

Browse files
fsfodcompnerd
andauthored
Update llvm::Registry to work for LLVM shared library builds on windows (#109024)
This is part of the effort to support for enabling plugins on windows by adding better support for building llvm and clang as a DLL. Since windows doesn't implicitly import and merge exported symbols across shared libraries like other platforms we need to explicitly add a extern template declaration for each instantiation of llvm::Registry to force the registry symbols to be dllimport'ed. I've added a new visibility macro that doesn't switch between dllimport and dllexport on windows since the existing macro would be in the wrong mode for llvm::Registry's declared in Clang. This PR also depends Clang symbol visibility macros that will be added by #108276 --------- Co-authored-by: Saleem Abdulrasool <[email protected]>
1 parent 3860e29 commit 00cd1a0

File tree

9 files changed

+76
-30
lines changed

9 files changed

+76
-30
lines changed

clang/include/clang/Basic/ParsedAttrInfo.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "clang/Basic/AttrSubjectMatchRules.h"
1919
#include "clang/Basic/AttributeCommonInfo.h"
20+
#include "clang/Support/Compiler.h"
2021
#include "llvm/ADT/ArrayRef.h"
2122
#include "llvm/Support/Registry.h"
2223
#include <climits>
@@ -175,4 +176,8 @@ const std::list<std::unique_ptr<ParsedAttrInfo>> &getAttributePluginInstances();
175176

176177
} // namespace clang
177178

179+
namespace llvm {
180+
extern template class CLANG_TEMPLATE_ABI Registry<clang::ParsedAttrInfo>;
181+
} // namespace llvm
182+
178183
#endif // LLVM_CLANG_BASIC_PARSEDATTRINFO_H

clang/include/clang/Frontend/FrontendPluginRegistry.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define LLVM_CLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H
1515

1616
#include "clang/Frontend/FrontendAction.h"
17+
#include "clang/Support/Compiler.h"
1718
#include "llvm/Support/Registry.h"
1819

1920
namespace clang {
@@ -23,4 +24,8 @@ using FrontendPluginRegistry = llvm::Registry<PluginASTAction>;
2324

2425
} // namespace clang
2526

27+
namespace llvm {
28+
extern template class CLANG_TEMPLATE_ABI Registry<clang::PluginASTAction>;
29+
} // namespace llvm
30+
2631
#endif // LLVM_CLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H

clang/include/clang/Lex/Preprocessor.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "clang/Lex/PPEmbedParameters.h"
3333
#include "clang/Lex/Token.h"
3434
#include "clang/Lex/TokenLexer.h"
35+
#include "clang/Support/Compiler.h"
3536
#include "llvm/ADT/APSInt.h"
3637
#include "llvm/ADT/ArrayRef.h"
3738
#include "llvm/ADT/DenseMap.h"
@@ -3060,4 +3061,8 @@ using PragmaHandlerRegistry = llvm::Registry<PragmaHandler>;
30603061

30613062
} // namespace clang
30623063

3064+
namespace llvm {
3065+
extern template class CLANG_TEMPLATE_ABI Registry<clang::PragmaHandler>;
3066+
} // namespace llvm
3067+
30633068
#endif // LLVM_CLANG_LEX_PREPROCESSOR_H

clang/include/clang/Tooling/CompilationDatabasePluginRegistry.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef LLVM_CLANG_TOOLING_COMPILATIONDATABASEPLUGINREGISTRY_H
1010
#define LLVM_CLANG_TOOLING_COMPILATIONDATABASEPLUGINREGISTRY_H
1111

12+
#include "clang/Support/Compiler.h"
1213
#include "clang/Tooling/CompilationDatabase.h"
1314
#include "llvm/Support/Registry.h"
1415

@@ -42,4 +43,9 @@ using CompilationDatabasePluginRegistry =
4243
} // namespace tooling
4344
} // namespace clang
4445

46+
namespace llvm {
47+
extern template class CLANG_TEMPLATE_ABI
48+
Registry<clang::tooling::CompilationDatabasePlugin>;
49+
} // namespace llvm
50+
4551
#endif // LLVM_CLANG_TOOLING_COMPILATIONDATABASEPLUGINREGISTRY_H

clang/include/clang/Tooling/ToolExecutorPluginRegistry.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H
1010
#define LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H
1111

12+
#include "clang/Support/Compiler.h"
1213
#include "clang/Tooling/Execution.h"
1314
#include "llvm/Support/Registry.h"
1415

@@ -20,4 +21,9 @@ using ToolExecutorPluginRegistry = llvm::Registry<ToolExecutorPlugin>;
2021
} // namespace tooling
2122
} // namespace clang
2223

24+
namespace llvm {
25+
extern template class CLANG_TEMPLATE_ABI
26+
Registry<clang::tooling::ToolExecutorPlugin>;
27+
} // namespace llvm
28+
2329
#endif // LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H

llvm/include/llvm/CodeGen/GCMetadataPrinter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ class StackMaps;
3434
/// defaults from Registry.
3535
using GCMetadataPrinterRegistry = Registry<GCMetadataPrinter>;
3636

37+
extern template class LLVM_TEMPLATE_ABI Registry<GCMetadataPrinter>;
38+
3739
/// GCMetadataPrinter - Emits GC metadata as assembly code. Instances are
3840
/// created, managed, and owned by the AsmPrinter.
3941
class GCMetadataPrinter {

llvm/include/llvm/IR/GCStrategy.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ class GCStrategy {
141141
/// GCMetadataPrinterRegistery as well.
142142
using GCRegistry = Registry<GCStrategy>;
143143

144+
extern template class LLVM_TEMPLATE_ABI Registry<GCStrategy>;
145+
144146
/// Lookup the GCStrategy object associated with the given gc name.
145147
std::unique_ptr<GCStrategy> getGCStrategy(const StringRef Name);
146148

llvm/include/llvm/Support/Compiler.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,12 @@
153153
/// exported when llvm is built as a shared library with everything else that is
154154
/// unannotated will have internal visibility.
155155
///
156+
/// LLVM_ABI_EXPORT is for the special case for things like plugin symbol
157+
/// declarations or definitions where we don't want the macro to be switching
158+
/// between dllexport and dllimport on windows based on what codebase is being
159+
/// built, it will only be dllexport. For non windows platforms this macro
160+
/// behaves the same as LLVM_ABI.
161+
///
156162
/// LLVM_EXPORT_TEMPLATE is used on explicit template instantiations in source
157163
/// files that were declared extern in a header. This macro is only set as a
158164
/// compiler export attribute on windows, on other platforms it does nothing.
@@ -179,6 +185,7 @@
179185
#define LLVM_ABI
180186
#define LLVM_TEMPLATE_ABI
181187
#define LLVM_EXPORT_TEMPLATE
188+
#define LLVM_ABI_EXPORT
182189
#elif defined(_WIN32) && !defined(__MINGW32__)
183190
#if defined(LLVM_EXPORTS)
184191
#define LLVM_ABI __declspec(dllexport)
@@ -189,19 +196,23 @@
189196
#define LLVM_TEMPLATE_ABI __declspec(dllimport)
190197
#define LLVM_EXPORT_TEMPLATE
191198
#endif
199+
#define LLVM_ABI_EXPORT __declspec(dllexport)
192200
#elif defined(__ELF__) || defined(__MINGW32__) || defined(_AIX)
193201
#define LLVM_ABI LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
194202
#define LLVM_TEMPLATE_ABI LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
195203
#define LLVM_EXPORT_TEMPLATE
204+
#define LLVM_ABI_EXPORT LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
196205
#elif defined(__MACH__) || defined(__WASM__)
197206
#define LLVM_ABI LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
198207
#define LLVM_TEMPLATE_ABI
199208
#define LLVM_EXPORT_TEMPLATE
209+
#define LLVM_ABI_EXPORT LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
200210
#endif
201211
#else
202212
#define LLVM_ABI
203213
#define LLVM_TEMPLATE_ABI
204214
#define LLVM_EXPORT_TEMPLATE
215+
#define LLVM_ABI_EXPORT
205216
#endif
206217
#define LLVM_C_ABI LLVM_ABI
207218
#endif

llvm/include/llvm/Support/Registry.h

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,13 @@ namespace llvm {
5353
Registry() = delete;
5454

5555
friend class node;
56-
static node *Head, *Tail;
56+
// These must be must two separate declarations to workaround a 20 year
57+
// old MSVC bug with dllexport and multiple static fields in the same
58+
// declaration causing error C2487 "member of dll interface class may not
59+
// be declared with dll interface".
60+
// https://developercommunity.visualstudio.com/t/c2487-in-dllexport-class-with-static-members/69878
61+
static node *Head;
62+
static node *Tail;
5763

5864
public:
5965
/// Node in linked list of entries.
@@ -76,7 +82,13 @@ namespace llvm {
7682
/// add a node to the executable's registry. Therefore it's not defined here
7783
/// to avoid it being instantiated in the plugin and is instead defined in
7884
/// the executable (see LLVM_INSTANTIATE_REGISTRY below).
79-
static void add_node(node *N);
85+
static void add_node(node *N) {
86+
if (Tail)
87+
Tail->Next = N;
88+
else
89+
Head = N;
90+
Tail = N;
91+
}
8092

8193
/// Iterators for registry entries.
8294
///
@@ -95,7 +107,7 @@ namespace llvm {
95107

96108
// begin is not defined here in order to avoid usage of an undefined static
97109
// data member, instead it's instantiated by LLVM_INSTANTIATE_REGISTRY.
98-
static iterator begin();
110+
static iterator begin() { return iterator(Head); }
99111
static iterator end() { return iterator(nullptr); }
100112

101113
static iterator_range<iterator> entries() {
@@ -124,36 +136,28 @@ namespace llvm {
124136
}
125137
};
126138
};
139+
127140
} // end namespace llvm
128141

142+
#ifdef _WIN32
129143
/// Instantiate a registry class.
130-
///
131-
/// This provides template definitions of add_node, begin, and the Head and Tail
132-
/// pointers, then explicitly instantiates them. We could explicitly specialize
133-
/// them, instead of the two-step process of define then instantiate, but
134-
/// strictly speaking that's not allowed by the C++ standard (we would need to
135-
/// have explicit specialization declarations in all translation units where the
136-
/// specialization is used) so we don't.
137-
#define LLVM_INSTANTIATE_REGISTRY(REGISTRY_CLASS) \
138-
namespace llvm { \
139-
template<typename T> typename Registry<T>::node *Registry<T>::Head = nullptr;\
140-
template<typename T> typename Registry<T>::node *Registry<T>::Tail = nullptr;\
141-
template<typename T> \
142-
void Registry<T>::add_node(typename Registry<T>::node *N) { \
143-
if (Tail) \
144-
Tail->Next = N; \
145-
else \
146-
Head = N; \
147-
Tail = N; \
148-
} \
149-
template<typename T> typename Registry<T>::iterator Registry<T>::begin() { \
150-
return iterator(Head); \
151-
} \
152-
template REGISTRY_CLASS::node *Registry<REGISTRY_CLASS::type>::Head; \
153-
template REGISTRY_CLASS::node *Registry<REGISTRY_CLASS::type>::Tail; \
154-
template \
155-
void Registry<REGISTRY_CLASS::type>::add_node(REGISTRY_CLASS::node*); \
156-
template REGISTRY_CLASS::iterator Registry<REGISTRY_CLASS::type>::begin(); \
144+
#define LLVM_INSTANTIATE_REGISTRY(REGISTRY_CLASS) \
145+
namespace llvm { \
146+
template <typename T> \
147+
typename Registry<T>::node *Registry<T>::Head = nullptr; \
148+
template <typename T> \
149+
typename Registry<T>::node *Registry<T>::Tail = nullptr; \
150+
template class LLVM_ABI_EXPORT Registry<REGISTRY_CLASS::type>; \
151+
}
152+
#else
153+
#define LLVM_INSTANTIATE_REGISTRY(REGISTRY_CLASS) \
154+
namespace llvm { \
155+
template <typename T> \
156+
typename Registry<T>::node *Registry<T>::Head = nullptr; \
157+
template <typename T> \
158+
typename Registry<T>::node *Registry<T>::Tail = nullptr; \
159+
template class Registry<REGISTRY_CLASS::type>; \
157160
}
161+
#endif
158162

159163
#endif // LLVM_SUPPORT_REGISTRY_H

0 commit comments

Comments
 (0)