19
19
#include " llvm/ADT/Hashing.h"
20
20
#include " llvm/ADT/STLExtras.h"
21
21
#include " llvm/Support/Allocator.h"
22
+ #include " llvm/Support/Compiler.h"
22
23
#include " llvm/Support/PointerLikeTypeTraits.h"
23
24
#include " llvm/Support/TypeName.h"
24
25
@@ -100,6 +101,8 @@ namespace mlir {
100
101
// / uses the name of the type, it may not be used for types defined in
101
102
// / anonymous namespaces (which is asserted when it can be detected). String
102
103
// / names do not provide any guarantees on uniqueness in these contexts.
104
+ // / - This behavior may be forced even in the presence of explicit declarations
105
+ // / by specifying `MLIR_USE_FALLBACK_TYPE_IDS`.
103
106
// /
104
107
class TypeID {
105
108
// / This class represents the storage of a type info object.
@@ -161,9 +164,30 @@ namespace detail {
161
164
class FallbackTypeIDResolver {
162
165
protected:
163
166
// / Register an implicit type ID for the given type name.
164
- static TypeID registerImplicitTypeID (StringRef name);
167
+ LLVM_ALWAYS_EXPORT static TypeID registerImplicitTypeID (StringRef name);
165
168
};
166
169
170
+ template <typename T>
171
+ struct is_fully_resolved_t {
172
+ // / Trait to check if `U` is fully resolved. We use this to verify that `T` is
173
+ // / fully resolved when trying to resolve a TypeID. We don't technically need
174
+ // / to have the full definition of `T` for the fallback, but it does help
175
+ // / prevent situations where a forward declared type uses this fallback even
176
+ // / though there is a strong definition for the TypeID in the location where
177
+ // / `T` is defined.
178
+ template <typename U>
179
+ using is_fully_resolved_trait = decltype (sizeof (U));
180
+ template <typename U>
181
+ using is_fully_resolved = llvm::is_detected<is_fully_resolved_trait, U>;
182
+ static constexpr bool value = is_fully_resolved<T>::value;
183
+ };
184
+
185
+ template <typename T>
186
+ constexpr bool is_fully_resolved () {
187
+ // / Helper function for is_fully_resolved_t.
188
+ return is_fully_resolved_t <T>::value;
189
+ }
190
+
167
191
// / This class provides a resolver for getting the ID for a given class T. This
168
192
// / allows for the derived type to specialize its resolution behavior. The
169
193
// / default implementation uses the string name of the type to resolve the ID.
@@ -178,19 +202,8 @@ class FallbackTypeIDResolver {
178
202
template <typename T, typename Enable = void >
179
203
class TypeIDResolver : public FallbackTypeIDResolver {
180
204
public:
181
- // / Trait to check if `U` is fully resolved. We use this to verify that `T` is
182
- // / fully resolved when trying to resolve a TypeID. We don't technically need
183
- // / to have the full definition of `T` for the fallback, but it does help
184
- // / prevent situations where a forward declared type uses this fallback even
185
- // / though there is a strong definition for the TypeID in the location where
186
- // / `T` is defined.
187
- template <typename U>
188
- using is_fully_resolved_trait = decltype (sizeof (U));
189
- template <typename U>
190
- using is_fully_resolved = llvm::is_detected<is_fully_resolved_trait, U>;
191
-
192
205
static TypeID resolveTypeID () {
193
- static_assert (is_fully_resolved<T>::value ,
206
+ static_assert (is_fully_resolved<T>() ,
194
207
" TypeID::get<> requires the complete definition of `T`" );
195
208
static TypeID id = registerImplicitTypeID (llvm::getTypeName<T>());
196
209
return id;
@@ -246,7 +259,7 @@ TypeID TypeID::get() {
246
259
// circumstances a hard-to-catch runtime bug when a TypeID is hidden in two
247
260
// different shared libraries and instances of the same class only gets the same
248
261
// TypeID inside a given DSO.
249
- #define MLIR_DECLARE_EXPLICIT_TYPE_ID (CLASS_NAME ) \
262
+ #define MLIR_DECLARE_EXPLICIT_SELF_OWNING_TYPE_ID (CLASS_NAME ) \
250
263
namespace mlir { \
251
264
namespace detail { \
252
265
template <> \
@@ -260,13 +273,57 @@ TypeID TypeID::get() {
260
273
} /* namespace detail */ \
261
274
} /* namespace mlir */
262
275
263
- #define MLIR_DEFINE_EXPLICIT_TYPE_ID (CLASS_NAME ) \
276
+ #define MLIR_DEFINE_EXPLICIT_SELF_OWNING_TYPE_ID (CLASS_NAME ) \
264
277
namespace mlir { \
265
278
namespace detail { \
266
279
SelfOwningTypeID TypeIDResolver<CLASS_NAME>::id = {}; \
267
280
} /* namespace detail */ \
268
281
} /* namespace mlir */
269
282
283
+
284
+ // / Declare/define an explicit specialization for TypeID using the string
285
+ // / comparison fallback. This is useful for complex shared library setups
286
+ // / where it may be difficult to agree on a source of truth for specific
287
+ // / type ID resolution. As long as there is a single resolution for
288
+ // / registerImplicitTypeID, all type IDs can be reference a shared
289
+ // / registration. This way types which are logically shared across multiple
290
+ // / DSOs can have the same type ID, even if their definitions are duplicated.
291
+ #define MLIR_DECLARE_EXPLICIT_FALLBACK_TYPE_ID (CLASS_NAME ) \
292
+ namespace mlir { \
293
+ namespace detail { \
294
+ template <> \
295
+ class TypeIDResolver <CLASS_NAME> : public FallbackTypeIDResolver { \
296
+ public: \
297
+ static TypeID resolveTypeID () { \
298
+ static_assert (is_fully_resolved<CLASS_NAME>(), \
299
+ " TypeID::get<> requires the complete definition of `T`" ); \
300
+ static TypeID id = \
301
+ registerImplicitTypeID (llvm::getTypeName<CLASS_NAME>()); \
302
+ return id; \
303
+ } \
304
+ }; \
305
+ } /* namespace detail */ \
306
+ } /* namespace mlir */
307
+
308
+ #define MLIR_DEFINE_EXPLICIT_FALLBACK_TYPE_ID (CLASS_NAME )
309
+
310
+
311
+ #ifndef MLIR_USE_FALLBACK_TYPE_IDS
312
+ #define MLIR_USE_FALLBACK_TYPE_IDS false
313
+ #endif
314
+
315
+ #if MLIR_USE_FALLBACK_TYPE_IDS
316
+ #define MLIR_DECLARE_EXPLICIT_TYPE_ID (CLASS_NAME ) \
317
+ MLIR_DECLARE_EXPLICIT_FALLBACK_TYPE_ID (CLASS_NAME)
318
+ #define MLIR_DEFINE_EXPLICIT_TYPE_ID (CLASS_NAME ) \
319
+ MLIR_DEFINE_EXPLICIT_FALLBACK_TYPE_ID (CLASS_NAME)
320
+ #else
321
+ #define MLIR_DECLARE_EXPLICIT_TYPE_ID (CLASS_NAME ) \
322
+ MLIR_DECLARE_EXPLICIT_SELF_OWNING_TYPE_ID (CLASS_NAME)
323
+ #define MLIR_DEFINE_EXPLICIT_TYPE_ID (CLASS_NAME ) \
324
+ MLIR_DEFINE_EXPLICIT_SELF_OWNING_TYPE_ID (CLASS_NAME)
325
+ #endif /* MLIR_USE_FALLBACK_TYPE_IDS */
326
+
270
327
// Declare/define an explicit, **internal**, specialization of TypeID for the
271
328
// given class. This is useful for providing an explicit specialization of
272
329
// TypeID for a class that is known to be internal to a specific library. It
@@ -331,7 +388,8 @@ class alignas(8) SelfOwningTypeID {
331
388
// ===----------------------------------------------------------------------===//
332
389
333
390
// / Explicitly register a set of "builtin" types.
334
- MLIR_DECLARE_EXPLICIT_TYPE_ID (void )
391
+ // / `void` must be self-owning, it can't be fully resolved.
392
+ MLIR_DECLARE_EXPLICIT_SELF_OWNING_TYPE_ID (void )
335
393
336
394
namespace llvm {
337
395
template <>
0 commit comments