1919#include " llvm/ADT/Hashing.h"
2020#include " llvm/ADT/STLExtras.h"
2121#include " llvm/Support/Allocator.h"
22+ #include " llvm/Support/Compiler.h"
2223#include " llvm/Support/PointerLikeTypeTraits.h"
2324#include " llvm/Support/TypeName.h"
2425
@@ -100,6 +101,8 @@ namespace mlir {
100101// / uses the name of the type, it may not be used for types defined in
101102// / anonymous namespaces (which is asserted when it can be detected). String
102103// / 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`.
103106// /
104107class TypeID {
105108 // / This class represents the storage of a type info object.
@@ -161,9 +164,30 @@ namespace detail {
161164class FallbackTypeIDResolver {
162165protected:
163166 // / 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);
165168};
166169
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+
167191// / This class provides a resolver for getting the ID for a given class T. This
168192// / allows for the derived type to specialize its resolution behavior. The
169193// / default implementation uses the string name of the type to resolve the ID.
@@ -178,19 +202,8 @@ class FallbackTypeIDResolver {
178202template <typename T, typename Enable = void >
179203class TypeIDResolver : public FallbackTypeIDResolver {
180204public:
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-
192205 static TypeID resolveTypeID () {
193- static_assert (is_fully_resolved<T>::value ,
206+ static_assert (is_fully_resolved<T>() ,
194207 " TypeID::get<> requires the complete definition of `T`" );
195208 static TypeID id = registerImplicitTypeID (llvm::getTypeName<T>());
196209 return id;
@@ -246,7 +259,7 @@ TypeID TypeID::get() {
246259// circumstances a hard-to-catch runtime bug when a TypeID is hidden in two
247260// different shared libraries and instances of the same class only gets the same
248261// 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 ) \
250263 namespace mlir { \
251264 namespace detail { \
252265 template <> \
@@ -260,13 +273,57 @@ TypeID TypeID::get() {
260273 } /* namespace detail */ \
261274 } /* namespace mlir */
262275
263- #define MLIR_DEFINE_EXPLICIT_TYPE_ID (CLASS_NAME ) \
276+ #define MLIR_DEFINE_EXPLICIT_SELF_OWNING_TYPE_ID (CLASS_NAME ) \
264277 namespace mlir { \
265278 namespace detail { \
266279 SelfOwningTypeID TypeIDResolver<CLASS_NAME>::id = {}; \
267280 } /* namespace detail */ \
268281 } /* namespace mlir */
269282
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+
270327// Declare/define an explicit, **internal**, specialization of TypeID for the
271328// given class. This is useful for providing an explicit specialization of
272329// TypeID for a class that is known to be internal to a specific library. It
@@ -331,7 +388,8 @@ class alignas(8) SelfOwningTypeID {
331388// ===----------------------------------------------------------------------===//
332389
333390// / 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 )
335393
336394namespace llvm {
337395template <>
0 commit comments