Skip to content

Commit 5866032

Browse files
authored
[mlir] Add MLIR_USE_FALLBACK_TYPE_IDS macro support for TypeID (#126999)
Adds a macro definition `MLIR_USE_FALLBACK_TYPE_IDS`. When this is defined, the `MLIR_{DECLARE,DEFINE}_EXPLICIT_TYPE_ID` functions explicitly fall back to string comparison. This is useful for complex shared library setups where it may be difficult to agree on a source of truth for specific type ID resolution. As long as there is a single resolution for `registerImplicitTypeID`, all type IDs can be reference a shared registration. This way types which are logically shared across multiple DSOs can have the same type ID, even if their definitions are duplicated.
1 parent e9fb239 commit 5866032

File tree

2 files changed

+77
-18
lines changed

2 files changed

+77
-18
lines changed

mlir/include/mlir/Support/TypeID.h

Lines changed: 74 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
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
///
104107
class TypeID {
105108
/// This class represents the storage of a type info object.
@@ -161,9 +164,30 @@ namespace detail {
161164
class FallbackTypeIDResolver {
162165
protected:
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 {
178202
template <typename T, typename Enable = void>
179203
class TypeIDResolver : public FallbackTypeIDResolver {
180204
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-
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

336394
namespace llvm {
337395
template <>

mlir/lib/Support/TypeID.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ struct ImplicitTypeIDRegistry {
8080
};
8181
} // end namespace
8282

83-
TypeID detail::FallbackTypeIDResolver::registerImplicitTypeID(StringRef name) {
83+
LLVM_ALWAYS_EXPORT TypeID
84+
detail::FallbackTypeIDResolver::registerImplicitTypeID(StringRef name) {
8485
static ImplicitTypeIDRegistry registry;
8586
return registry.lookupOrInsert(name);
8687
}
@@ -89,4 +90,4 @@ TypeID detail::FallbackTypeIDResolver::registerImplicitTypeID(StringRef name) {
8990
// Builtin TypeIDs
9091
//===----------------------------------------------------------------------===//
9192

92-
MLIR_DEFINE_EXPLICIT_TYPE_ID(void)
93+
MLIR_DEFINE_EXPLICIT_SELF_OWNING_TYPE_ID(void)

0 commit comments

Comments
 (0)