1 //===- Identifier.h - MLIR Identifier Class ---------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef MLIR_IR_IDENTIFIER_H
10 #define MLIR_IR_IDENTIFIER_H
11
12 #include "mlir/Support/LLVM.h"
13 #include "llvm/ADT/DenseMapInfo.h"
14 #include "llvm/ADT/StringMapEntry.h"
15 #include "llvm/Support/PointerLikeTypeTraits.h"
16
17 namespace mlir {
18 class MLIRContext;
19
20 /// This class represents a uniqued string owned by an MLIRContext. Strings
21 /// represented by this type cannot contain nul characters, and may not have a
22 /// zero length.
23 ///
24 /// This is a POD type with pointer size, so it should be passed around by
25 /// value. The underlying data is owned by MLIRContext and is thus immortal for
26 /// almost all clients.
27 class Identifier {
28 using EntryType = llvm::StringMapEntry<llvm::NoneType>;
29
30 public:
31 /// Return an identifier for the specified string.
32 static Identifier get(StringRef str, MLIRContext *context);
33 Identifier(const Identifier &) = default;
34 Identifier &operator=(const Identifier &other) = default;
35
36 /// Return a StringRef for the string.
strref()37 StringRef strref() const { return entry->first(); }
38
39 /// Identifiers implicitly convert to StringRefs.
StringRef()40 operator StringRef() const { return strref(); }
41
42 /// Return an std::string.
str()43 std::string str() const { return strref().str(); }
44
45 /// Return a null terminated C string.
c_str()46 const char *c_str() const { return entry->getKeyData(); }
47
48 /// Return a pointer to the start of the string data.
data()49 const char *data() const { return entry->getKeyData(); }
50
51 /// Return the number of bytes in this string.
size()52 unsigned size() const { return entry->getKeyLength(); }
53
begin()54 const char *begin() const { return data(); }
end()55 const char *end() const { return entry->getKeyData() + size(); }
56
57 bool operator==(Identifier other) const { return entry == other.entry; }
58 bool operator!=(Identifier rhs) const { return !(*this == rhs); }
59
60 void print(raw_ostream &os) const;
61 void dump() const;
62
getAsOpaquePointer()63 const void *getAsOpaquePointer() const {
64 return static_cast<const void *>(entry);
65 }
getFromOpaquePointer(const void * entry)66 static Identifier getFromOpaquePointer(const void *entry) {
67 return Identifier(static_cast<const EntryType *>(entry));
68 }
69
70 /// Compare the underlying StringRef.
compare(Identifier rhs)71 int compare(Identifier rhs) const { return strref().compare(rhs.strref()); }
72
73 private:
74 /// This contains the bytes of the string, which is guaranteed to be nul
75 /// terminated.
76 const EntryType *entry;
Identifier(const EntryType * entry)77 explicit Identifier(const EntryType *entry) : entry(entry) {}
78 };
79
80 inline raw_ostream &operator<<(raw_ostream &os, Identifier identifier) {
81 identifier.print(os);
82 return os;
83 }
84
85 // Identifier/Identifier equality comparisons are defined inline.
86 inline bool operator==(Identifier lhs, StringRef rhs) {
87 return lhs.strref() == rhs;
88 }
89 inline bool operator!=(Identifier lhs, StringRef rhs) { return !(lhs == rhs); }
90
91 inline bool operator==(StringRef lhs, Identifier rhs) {
92 return rhs.strref() == lhs;
93 }
94 inline bool operator!=(StringRef lhs, Identifier rhs) { return !(lhs == rhs); }
95
96 // Make identifiers hashable.
hash_value(Identifier arg)97 inline llvm::hash_code hash_value(Identifier arg) {
98 // Identifiers are uniqued, so we can just hash the pointer they contain.
99 return llvm::hash_value(arg.getAsOpaquePointer());
100 }
101 } // end namespace mlir
102
103 namespace llvm {
104 // Identifiers hash just like pointers, there is no need to hash the bytes.
105 template <>
106 struct DenseMapInfo<mlir::Identifier> {
107 static mlir::Identifier getEmptyKey() {
108 auto pointer = llvm::DenseMapInfo<const void *>::getEmptyKey();
109 return mlir::Identifier::getFromOpaquePointer(pointer);
110 }
111 static mlir::Identifier getTombstoneKey() {
112 auto pointer = llvm::DenseMapInfo<const void *>::getTombstoneKey();
113 return mlir::Identifier::getFromOpaquePointer(pointer);
114 }
115 static unsigned getHashValue(mlir::Identifier val) {
116 return mlir::hash_value(val);
117 }
118 static bool isEqual(mlir::Identifier lhs, mlir::Identifier rhs) {
119 return lhs == rhs;
120 }
121 };
122
123 /// The pointer inside of an identifier comes from a StringMap, so its alignment
124 /// is always at least 4 and probably 8 (on 64-bit machines). Allow LLVM to
125 /// steal the low bits.
126 template <>
127 struct PointerLikeTypeTraits<mlir::Identifier> {
128 public:
129 static inline void *getAsVoidPointer(mlir::Identifier i) {
130 return const_cast<void *>(i.getAsOpaquePointer());
131 }
132 static inline mlir::Identifier getFromVoidPointer(void *p) {
133 return mlir::Identifier::getFromOpaquePointer(p);
134 }
135 static constexpr int NumLowBitsAvailable = 2;
136 };
137
138 } // end namespace llvm
139 #endif
140