xref: /aosp_15_r20/external/pytorch/aten/src/ATen/core/dispatch/CppSignature.h (revision da0073e96a02ea20f0ac840b70461e3646d07c45)
1 #pragma once
2 
3 #include <typeindex>
4 #include <c10/core/DispatchKeySet.h>
5 #include <c10/macros/Macros.h>
6 #include <c10/util/Metaprogramming.h>
7 #include <c10/util/Type.h>
8 
9 namespace c10 {
10 namespace impl {
11 
12 // A CppSignature object holds RTTI information about a C++ function signature at runtime
13 // and can compare them or get a debug-printable name.
14 class TORCH_API CppSignature final {
15 public:
16     CppSignature(const CppSignature&) = default;
17     CppSignature(CppSignature&&) noexcept = default;
18     CppSignature& operator=(const CppSignature&) = default;
19     CppSignature& operator=(CppSignature&&) noexcept = default;
20 
21     template<class FuncType>
make()22     static CppSignature make() {
23         // Normalize functors, lambdas, function pointers, etc. into the plain function type
24         // The first argument of the schema might be of type DispatchKeySet, in which case we remove it.
25         // We do this to guarantee that all CppSignature's for an operator will match, even if they're registered
26         // with different calling conventions.
27         // See Note [Plumbing Keys Through The Dispatcher]
28         using decayed_function_type = typename c10::remove_DispatchKeySet_arg_from_func<std::decay_t<FuncType>>::func_type;
29 
30         return CppSignature(std::type_index(typeid(decayed_function_type)));
31     }
32 
name()33     std::string name() const {
34         return c10::demangle(signature_.name());
35     }
36 
37     friend bool operator==(const CppSignature& lhs, const CppSignature& rhs) {
38         if (lhs.signature_ == rhs.signature_) {
39             return true;
40         }
41         // Without RTLD_GLOBAL, the type_index comparison could yield false because
42         // they point to different instances of the RTTI data, but the types would
43         // still be the same. Let's check for that case too.
44         // Note that there still is a case where this might not work, i.e. when
45         // linking libraries of different compilers together, they might have
46         // different ways to serialize a type name. That, together with a missing
47         // RTLD_GLOBAL, would still fail this.
48         if (0 == strcmp(lhs.signature_.name(), rhs.signature_.name())) {
49             return true;
50         }
51 
52         return false;
53     }
54 
55 private:
CppSignature(std::type_index signature)56     explicit CppSignature(std::type_index signature): signature_(std::move(signature)) {}
57     std::type_index signature_;
58 };
59 
60 inline bool operator!=(const CppSignature& lhs, const CppSignature& rhs) {
61     return !(lhs == rhs );
62 }
63 
64 }
65 }
66