LLVM: lib/ProfileData/ItaniumManglingCanonicalizer.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

15

16using namespace llvm;

17using llvm::itanium_demangle::ForwardTemplateReference;

18using llvm::itanium_demangle::Node;

19using llvm::itanium_demangle::NodeKind;

20

21namespace {

22struct FoldingSetNodeIDBuilder {

23 llvm::FoldingSetNodeID &ID;

24 void operator()(const Node *P) { ID.AddPointer(P); }

25 void operator()(std::string_view Str) {

26 if (Str.empty())

27 ID.AddString({});

28 else

29 ID.AddString(llvm::StringRef(&*Str.begin(), Str.size()));

30 }

31 template

32 std::enable_if_t<std::is_integral_v || std::is_enum_v> operator()(T V) {

33 ID.AddInteger((unsigned long long)V);

34 }

35 void operator()(itanium_demangle::NodeArray A) {

36 ID.AddInteger(A.size());

37 for (const Node *N : A)

38 (*this)(N);

39 }

40};

41

42template<typename ...T>

44 FoldingSetNodeIDBuilder Builder = {ID};

45 Builder(K);

46 int VisitInOrder[] = {

47 (Builder(V), 0) ...,

48 0

49 };

50 (void)VisitInOrder;

51}

52

53

54template struct ProfileSpecificNode {

55 FoldingSetNodeID &ID;

56 template<typename ...T> void operator()(T ...V) {

57 profileCtor(ID, NodeKind::Kind, V...);

58 }

59};

60

61struct ProfileNode {

62 FoldingSetNodeID &ID;

63 template void operator()(const NodeT *N) {

64 N->match(ProfileSpecificNode{ID});

65 }

66};

67

69 llvm_unreachable("should never canonicalize a ForwardTemplateReference");

70}

71

72void profileNode(llvm::FoldingSetNodeID &ID, const Node *N) {

73 N->visit(ProfileNode{ID});

74}

75

76class FoldingNodeAllocator {

78 public:

79

80 itanium_demangle::Node *getNode() {

81 return reinterpret_cast<itanium_demangle::Node *>(this + 1);

82 }

83 void Profile(llvm::FoldingSetNodeID &ID) { profileNode(ID, getNode()); }

84 };

85

87 llvm::FoldingSet Nodes;

88

89public:

90 void reset() {}

91

92 template <typename T, typename... Args>

93 std::pair<Node *, bool> getOrCreateNode(bool CreateNewNodes, Args &&... As) {

94

95

96

97 if (std::is_same<T, ForwardTemplateReference>::value) {

98

99

100 return {new (RawAlloc.Allocate(sizeof(T), alignof(T)))

101 T(std::forward(As)...),

102 true};

103 }

104

105 llvm::FoldingSetNodeID ID;

106 profileCtor(ID, NodeKind::Kind, As...);

107

108 void *InsertPos;

110 return {static_cast<T*>(Existing->getNode()), false};

111

112 if (!CreateNewNodes)

113 return {nullptr, true};

114

115 static_assert(alignof(T) <= alignof(NodeHeader),

116 "underaligned node header for specific node kind");

117 void *Storage =

118 RawAlloc.Allocate(sizeof(NodeHeader) + sizeof(T), alignof(NodeHeader));

119 NodeHeader *New = new (Storage) NodeHeader;

120 T *Result = new (New->getNode()) T(std::forward(As)...);

122 return {Result, true};

123 }

124

125 template<typename T, typename... Args>

126 Node *makeNode(Args &&...As) {

127 return getOrCreateNode(true, std::forward(As)...).first;

128 }

129

130 void *allocateNodeArray(size_t sz) {

131 return RawAlloc.Allocate(sizeof(Node *) * sz, alignof(Node *));

132 }

133};

134

135class CanonicalizerAllocator : public FoldingNodeAllocator {

136 Node *MostRecentlyCreated = nullptr;

137 Node *TrackedNode = nullptr;

138 bool TrackedNodeIsUsed = false;

139 bool CreateNewNodes = true;

140 llvm::SmallDenseMap<Node*, Node*, 32> Remappings;

141

142 template<typename T, typename ...Args> Node *makeNodeSimple(Args &&...As) {

143 std::pair<Node *, bool> Result =

144 getOrCreateNode(CreateNewNodes, std::forward(As)...);

146

147 MostRecentlyCreated = Result.first;

148 } else if (Result.first) {

149

153 "should never need multiple remap steps");

154 }

155 if (Result.first == TrackedNode)

156 TrackedNodeIsUsed = true;

157 }

159 }

160

161

162 template struct MakeNodeImpl {

163 CanonicalizerAllocator &Self;

164 template<typename ...Args> Node *make(Args &&...As) {

165 return Self.makeNodeSimple<T>(std::forward(As)...);

166 }

167 };

168

169public:

170 template<typename T, typename ...Args> Node *makeNode(Args &&...As) {

171 return MakeNodeImpl{*this}.make(std::forward(As)...);

172 }

173

174 void reset() { MostRecentlyCreated = nullptr; }

175

176 void setCreateNewNodes(bool CNN) { CreateNewNodes = CNN; }

177

178 void addRemapping(Node *A, Node *B) {

179

180

181 Remappings.insert(std::make_pair(A, B));

182 }

183

184 bool isMostRecentlyCreated(Node *N) const { return MostRecentlyCreated == N; }

185

186 void trackUsesOf(Node *N) {

187 TrackedNode = N;

188 TrackedNodeIsUsed = false;

189 }

190 bool trackedNodeIsUsed() const { return TrackedNodeIsUsed; }

191};

192

193

194

195using CanonicalizingDemangler =

196 itanium_demangle::ManglingParser;

197}

198

200 CanonicalizingDemangler Demangler = {nullptr, nullptr};

201};

202

205

209 auto &Alloc = P->Demangler.ASTAllocator;

210 Alloc.setCreateNewNodes(true);

211

212 auto Parse = [&](StringRef Str) {

213 P->Demangler.reset(Str.begin(), Str.end());

214 Node *N = nullptr;

215 switch (Kind) {

216

217

219

220

221

222 if (Str.size() == 2 && P->Demangler.consumeIf("St"))

223 N = P->Demangler.make<itanium_demangle::NameType>("std");

224

225

226

227

228 else if (Str.starts_with("S"))

229

230 N = P->Demangler.parseType();

231 else

232 N = P->Demangler.parseName();

233 break;

234

235

237 N = P->Demangler.parseType();

238 break;

239

240

242 N = P->Demangler.parseEncoding();

243 break;

244 }

245

246

247 if (P->Demangler.numLeft() != 0)

248 N = nullptr;

249

250

251

252 return std::make_pair(N, Alloc.isMostRecentlyCreated(N));

253 };

254

255 Node *FirstNode, *SecondNode;

256 bool FirstIsNew, SecondIsNew;

257

258 std::tie(FirstNode, FirstIsNew) = Parse(First);

259 if (!FirstNode)

261

262 Alloc.trackUsesOf(FirstNode);

263 std::tie(SecondNode, SecondIsNew) = Parse(Second);

264 if (!SecondNode)

266

267

268 if (FirstNode == SecondNode)

270

271 if (FirstIsNew && Alloc.trackedNodeIsUsed())

272 Alloc.addRemapping(FirstNode, SecondNode);

273 else if (SecondIsNew)

274 Alloc.addRemapping(SecondNode, FirstNode);

275 else

277

279}

280

283 bool CreateNewNodes) {

284 Demangler.ASTAllocator.setCreateNewNodes(CreateNewNodes);

285 Demangler.reset(Mangling.begin(), Mangling.end());

286

287

288

289

290

294 N = Demangler.parse();

295 else

296 N = Demangler.make<itanium_demangle::NameType>(

297 std::string_view(Mangling.data(), Mangling.size()));

299}

300

305

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)

This file defines the BumpPtrAllocator interface.

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

This file defines the DenseMap class.

This file defines a hash set that can be used to remove duplication of nodes in a graph.

static ItaniumManglingCanonicalizer::Key parseMaybeMangledName(CanonicalizingDemangler &Demangler, StringRef Mangling, bool CreateNewNodes)

Definition ItaniumManglingCanonicalizer.cpp:282

ValueT lookup(const_arg_type_t< KeyT > Val) const

lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...

bool contains(const_arg_type_t< KeyT > Val) const

Return true if the specified key is in the map, false otherwise.

std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)

void InsertNode(T *N, void *InsertPos)

InsertNode - Insert the specified node into the folding set, knowing that it is not already in the fo...

T * FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos)

FindNodeOrInsertPos - Look up the node specified by ID.

FoldingSetNodeID - This class is used to gather all the unique data bits of a node.

@ Encoding

The mangling fragment is an .

@ Name

The mangling fragment is a (or a predefined ).

@ Type

The mangling fragment is a .

LLVM_ABI Key lookup(StringRef Mangling)

Find a canonical key for the specified mangling, if one has already been formed.

Definition ItaniumManglingCanonicalizer.cpp:307

LLVM_ABI Key canonicalize(StringRef Mangling)

Form a canonical key for the specified mangling.

Definition ItaniumManglingCanonicalizer.cpp:302

LLVM_ABI ItaniumManglingCanonicalizer()

Definition ItaniumManglingCanonicalizer.cpp:203

@ InvalidFirstMangling

The first equivalent mangling is invalid.

@ InvalidSecondMangling

The second equivalent mangling is invalid.

@ ManglingAlreadyUsed

Both the equivalent manglings have already been used as components of some other mangling we've looke...

LLVM_ABI EquivalenceError addEquivalence(FragmentKind Kind, StringRef First, StringRef Second)

Add an equivalence between First and Second.

Definition ItaniumManglingCanonicalizer.cpp:207

LLVM_ABI ~ItaniumManglingCanonicalizer()

Definition ItaniumManglingCanonicalizer.cpp:204

StringRef - Represent a constant reference to a string, i.e.

bool starts_with(StringRef Prefix) const

Check if this string starts with the given Prefix.

constexpr size_t size() const

size - Get the string size.

constexpr const char * data() const

data - Get a pointer to the start of the string (which may not be null terminated).

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

constexpr char Args[]

Key for Kernel::Metadata::mArgs.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

NodeAddr< NodeBase * > Node

This is an optimization pass for GlobalISel generic memory operations.

FoldingSetBase::Node FoldingSetNode

@ First

Helpers to iterate all locations in the MemoryEffectsBase class.

BumpPtrAllocatorImpl<> BumpPtrAllocator

The standard BumpPtrAllocator which just uses the default template parameters.

A forward-reference to a template argument that was not known at the point where the template paramet...

CanonicalizingDemangler Demangler

Definition ItaniumManglingCanonicalizer.cpp:200