45
45
#define LLVM_MC_MCPSEUDOPROBE_H
46
46
47
47
#include " llvm/ADT/MapVector.h"
48
+ #include " llvm/ADT/StringRef.h"
49
+ #include " llvm/ADT/Twine.h"
50
+ #include " llvm/IR/PseudoProbe.h"
48
51
#include " llvm/MC/MCSection.h"
52
+ #include " llvm/Support/Errc.h"
53
+ #include " llvm/Support/Error.h"
54
+ #include " llvm/Support/ErrorOr.h"
55
+ #include " llvm/Support/WithColor.h"
56
+ #include " llvm/Support/raw_ostream.h"
57
+ #include < algorithm>
49
58
#include < functional>
59
+ #include < list>
50
60
#include < map>
61
+ #include < set>
62
+ #include < sstream>
63
+ #include < string>
64
+ #include < system_error>
65
+ #include < unordered_map>
66
+ #include < unordered_set>
51
67
#include < vector>
52
68
53
69
namespace llvm {
@@ -62,69 +78,213 @@ enum class MCPseudoProbeFlag {
62
78
AddressDelta = 0x1 ,
63
79
};
64
80
81
+ // Function descriptor decoded from .pseudo_probe_desc section
82
+ struct MCPseudoProbeFuncDesc {
83
+ uint64_t FuncGUID = 0 ;
84
+ uint64_t FuncHash = 0 ;
85
+ std::string FuncName;
86
+
87
+ MCPseudoProbeFuncDesc (uint64_t GUID, uint64_t Hash, StringRef Name)
88
+ : FuncGUID(GUID), FuncHash(Hash), FuncName(Name){};
89
+
90
+ void print (raw_ostream &OS);
91
+ };
92
+
93
+ class MCPseudoProbe ;
94
+ class MCDecodedPseudoProbe ;
95
+
96
+ // An inline frame has the form <Guid, ProbeID>
97
+ using InlineSite = std::tuple<uint64_t , uint32_t >;
98
+ using MCPseudoProbeInlineStack = SmallVector<InlineSite, 8 >;
99
+ // GUID to PseudoProbeFuncDesc map
100
+ using GUIDProbeFunctionMap =
101
+ std::unordered_map<uint64_t , MCPseudoProbeFuncDesc>;
102
+ // Address to pseudo probes map.
103
+ using AddressProbesMap =
104
+ std::unordered_map<uint64_t , std::list<MCDecodedPseudoProbe>>;
105
+
106
+ class MCPseudoProbeInlineTree ;
107
+ class MCDecodedPseudoProbeInlineTree ;
108
+
109
+ class MCPseudoProbeBase {
110
+ protected:
111
+ uint64_t Guid;
112
+ uint64_t Index;
113
+ uint8_t Attributes;
114
+ uint8_t Type;
115
+ // The value should be equal to PseudoProbeReservedId::Last + 1 which is
116
+ // defined in SampleProfileProbe.h. The header file is not included here to
117
+ // reduce the dependency from MC to IPO.
118
+ const static uint32_t PseudoProbeFirstId = 1 ;
119
+
120
+ public:
121
+ MCPseudoProbeBase (uint64_t G, uint64_t I, uint64_t At, uint8_t T)
122
+ : Guid(G), Index(I), Attributes(At), Type(T) {}
123
+
124
+ bool isEntry () const { return Index == PseudoProbeFirstId; }
125
+
126
+ bool isTailCall () const {
127
+ return Attributes & static_cast <uint8_t >(PseudoProbeAttributes::Reserved);
128
+ }
129
+
130
+ uint64_t getGuid () const { return Guid; }
131
+
132
+ uint64_t getIndex () const { return Index; }
133
+
134
+ uint8_t getAttributes () const { return Attributes; }
135
+
136
+ uint8_t getType () const { return Type; }
137
+
138
+ bool isBlock () const {
139
+ return Type == static_cast <uint8_t >(PseudoProbeType::Block);
140
+ }
141
+
142
+ bool isIndirectCall () const {
143
+ return Type == static_cast <uint8_t >(PseudoProbeType::IndirectCall);
144
+ }
145
+
146
+ bool isDirectCall () const {
147
+ return Type == static_cast <uint8_t >(PseudoProbeType::DirectCall);
148
+ }
149
+
150
+ bool isCall () const { return isIndirectCall () || isDirectCall (); }
151
+
152
+ void setAttributes (uint8_t Attr) { Attributes = Attr; }
153
+ };
154
+
65
155
// / Instances of this class represent a pseudo probe instance for a pseudo probe
66
156
// / table entry, which is created during a machine instruction is assembled and
67
157
// / uses an address from a temporary label created at the current address in the
68
158
// / current section.
69
- class MCPseudoProbe {
159
+ class MCPseudoProbe : public MCPseudoProbeBase {
70
160
MCSymbol *Label;
71
- uint64_t Guid;
72
- uint64_t Index;
73
- uint8_t Type;
74
- uint8_t Attributes;
75
161
76
162
public:
77
163
MCPseudoProbe (MCSymbol *Label, uint64_t Guid, uint64_t Index, uint64_t Type,
78
164
uint64_t Attributes)
79
- : Label(Label), Guid(Guid), Index(Index), Type(Type),
80
- Attributes (Attributes) {
165
+ : MCPseudoProbeBase(Guid, Index, Attributes, Type), Label(Label) {
81
166
assert (Type <= 0xFF && " Probe type too big to encode, exceeding 2^8" );
82
167
assert (Attributes <= 0xFF &&
83
168
" Probe attributes too big to encode, exceeding 2^16" );
84
169
}
85
170
86
171
MCSymbol *getLabel () const { return Label; }
172
+ void emit (MCObjectStreamer *MCOS, const MCPseudoProbe *LastProbe) const ;
173
+ };
87
174
88
- uint64_t getGuid () const { return Guid; }
175
+ class MCDecodedPseudoProbe : public MCPseudoProbeBase {
176
+ uint64_t Address;
177
+ MCDecodedPseudoProbeInlineTree *InlineTree;
89
178
90
- uint64_t getIndex () const { return Index; }
179
+ public:
180
+ MCDecodedPseudoProbe (uint64_t Ad, uint64_t G, uint32_t I, PseudoProbeType K,
181
+ uint8_t At, MCDecodedPseudoProbeInlineTree *Tree)
182
+ : MCPseudoProbeBase(G, I, At, static_cast <uint8_t >(K)), Address(Ad),
183
+ InlineTree (Tree){};
91
184
92
- uint8_t getType () const { return Type ; }
185
+ uint64_t getAddress () const { return Address ; }
93
186
94
- uint8_t getAttributes () const { return Attributes ; }
187
+ void setAddress ( uint64_t Addr) { Address = Addr ; }
95
188
96
- void emit (MCObjectStreamer *MCOS, const MCPseudoProbe *LastProbe) const ;
189
+ MCDecodedPseudoProbeInlineTree *getInlineTreeNode () const {
190
+ return InlineTree;
191
+ }
192
+
193
+ // Get the inlined context by traversing current inline tree backwards,
194
+ // each tree node has its InlineSite which is taken as the context.
195
+ // \p ContextStack is populated in root to leaf order
196
+ void getInlineContext (SmallVectorImpl<std::string> &ContextStack,
197
+ const GUIDProbeFunctionMap &GUID2FuncMAP,
198
+ bool ShowName) const ;
199
+
200
+ // Helper function to get the string from context stack
201
+ std::string getInlineContextStr (const GUIDProbeFunctionMap &GUID2FuncMAP,
202
+ bool ShowName) const ;
203
+
204
+ // Print pseudo probe while disassembling
205
+ void print (raw_ostream &OS, const GUIDProbeFunctionMap &GUID2FuncMAP,
206
+ bool ShowName) const ;
97
207
};
98
208
99
- // An inline frame has the form <Guid, ProbeID>
100
- using InlineSite = std::tuple<uint64_t , uint32_t >;
101
- using MCPseudoProbeInlineStack = SmallVector<InlineSite, 8 >;
209
+ template <typename ProbeType, typename DerivedProbeInlineTreeType>
210
+ class MCPseudoProbeInlineTreeBase {
211
+ struct InlineSiteHash {
212
+ uint64_t operator ()(const InlineSite &Site) const {
213
+ return std::get<0 >(Site) ^ std::get<1 >(Site);
214
+ }
215
+ };
216
+
217
+ protected:
218
+ // Track children (e.g. inlinees) of current context
219
+ using InlinedProbeTreeMap = std::unordered_map<
220
+ InlineSite, std::unique_ptr<DerivedProbeInlineTreeType>, InlineSiteHash>;
221
+ InlinedProbeTreeMap Children;
222
+ // Set of probes that come with the function.
223
+ std::vector<ProbeType> Probes;
224
+ MCPseudoProbeInlineTreeBase () {
225
+ static_assert (std::is_base_of<MCPseudoProbeInlineTreeBase,
226
+ DerivedProbeInlineTreeType>::value,
227
+ " DerivedProbeInlineTreeType must be subclass of "
228
+ " MCPseudoProbeInlineTreeBase" );
229
+ }
230
+
231
+ public:
232
+ uint64_t Guid = 0 ;
233
+
234
+ // Root node has a GUID 0.
235
+ bool isRoot () const { return Guid == 0 ; }
236
+ InlinedProbeTreeMap &getChildren () { return Children; }
237
+ const InlinedProbeTreeMap &getChildren () const { return Children; }
238
+ std::vector<ProbeType> &getProbes () { return Probes; }
239
+ void addProbes (ProbeType Probe) { Probes.push_back (Probe); }
240
+ // Caller node of the inline site
241
+ MCPseudoProbeInlineTreeBase<ProbeType, DerivedProbeInlineTreeType> *Parent;
242
+ DerivedProbeInlineTreeType *getOrAddNode (const InlineSite &Site) {
243
+ auto Ret = Children.emplace (
244
+ Site, std::make_unique<DerivedProbeInlineTreeType>(Site));
245
+ Ret.first ->second ->Parent = this ;
246
+ return Ret.first ->second .get ();
247
+ };
248
+ };
102
249
103
250
// A Tri-tree based data structure to group probes by inline stack.
104
251
// A tree is allocated for a standalone .text section. A fake
105
252
// instance is created as the root of a tree.
106
253
// A real instance of this class is created for each function, either an
107
254
// unlined function that has code in .text section or an inlined function.
108
- class MCPseudoProbeInlineTree {
109
- uint64_t Guid;
110
- // Set of probes that come with the function.
111
- std::vector<MCPseudoProbe> Probes;
112
- // Use std::map for a deterministic output.
113
- std::map<InlineSite, MCPseudoProbeInlineTree *> Inlinees;
114
-
115
- // Root node has a GUID 0.
116
- bool isRoot () { return Guid == 0 ; }
117
- MCPseudoProbeInlineTree *getOrAddNode (InlineSite Site);
118
255
256
+ class MCPseudoProbeInlineTree
257
+ : public MCPseudoProbeInlineTreeBase<MCPseudoProbe,
258
+ MCPseudoProbeInlineTree> {
119
259
public:
120
260
MCPseudoProbeInlineTree () = default ;
121
- MCPseudoProbeInlineTree (uint64_t Guid) : Guid(Guid) {}
122
- ~MCPseudoProbeInlineTree ();
261
+ MCPseudoProbeInlineTree (uint64_t Guid) { this ->Guid = Guid; }
262
+ MCPseudoProbeInlineTree (const InlineSite &Site) {
263
+ this ->Guid = std::get<0 >(Site);
264
+ }
265
+
266
+ // MCPseudoProbeInlineTree method based on Inlinees
123
267
void addPseudoProbe (const MCPseudoProbe &Probe,
124
268
const MCPseudoProbeInlineStack &InlineStack);
125
269
void emit (MCObjectStreamer *MCOS, const MCPseudoProbe *&LastProbe);
126
270
};
127
271
272
+ // inline tree node for the decoded pseudo probe
273
+ class MCDecodedPseudoProbeInlineTree
274
+ : public MCPseudoProbeInlineTreeBase<MCDecodedPseudoProbe *,
275
+ MCDecodedPseudoProbeInlineTree> {
276
+ public:
277
+ InlineSite ISite;
278
+ // Used for decoding
279
+ uint32_t ChildrenToProcess = 0 ;
280
+
281
+ MCDecodedPseudoProbeInlineTree (){};
282
+ MCDecodedPseudoProbeInlineTree (const InlineSite &Site) : ISite(Site){};
283
+
284
+ // Return false if it's a dummy inline site
285
+ bool hasInlineSite () const { return std::get<0 >(ISite) != 0 ; }
286
+ };
287
+
128
288
// / Instances of this class represent the pseudo probes inserted into a compile
129
289
// / unit.
130
290
class MCPseudoProbeSection {
@@ -172,6 +332,83 @@ class MCPseudoProbeTable {
172
332
static int DdgPrintIndent;
173
333
#endif
174
334
};
335
+
336
+ class MCPseudoProbeDecoder {
337
+ // GUID to PseudoProbeFuncDesc map.
338
+ GUIDProbeFunctionMap GUID2FuncDescMap;
339
+
340
+ // Address to probes map.
341
+ AddressProbesMap Address2ProbesMap;
342
+
343
+ // The dummy root of the inline trie, all the outlined function will directly
344
+ // be the children of the dummy root, all the inlined function will be the
345
+ // children of its inlineer. So the relation would be like:
346
+ // DummyRoot --> OutlinedFunc --> InlinedFunc1 --> InlinedFunc2
347
+ MCDecodedPseudoProbeInlineTree DummyInlineRoot;
348
+
349
+ // / Points to the current location in the buffer.
350
+ const uint8_t *Data = nullptr ;
351
+
352
+ // / Points to the end of the buffer.
353
+ const uint8_t *End = nullptr ;
354
+
355
+ // Decoding helper function
356
+ template <typename T> ErrorOr<T> readUnencodedNumber ();
357
+ template <typename T> ErrorOr<T> readUnsignedNumber ();
358
+ template <typename T> ErrorOr<T> readSignedNumber ();
359
+ ErrorOr<StringRef> readString (uint32_t Size);
360
+
361
+ public:
362
+ // Decode pseudo_probe_desc section to build GUID to PseudoProbeFuncDesc map.
363
+ bool buildGUID2FuncDescMap (const uint8_t *Start, std::size_t Size);
364
+
365
+ // Decode pseudo_probe section to build address to probes map.
366
+ bool buildAddress2ProbeMap (const uint8_t *Start, std::size_t Size);
367
+
368
+ // Print pseudo_probe_desc section info
369
+ void printGUID2FuncDescMap (raw_ostream &OS);
370
+
371
+ // Print pseudo_probe section info, used along with show-disassembly
372
+ void printProbeForAddress (raw_ostream &OS, uint64_t Address);
373
+
374
+ // do printProbeForAddress for all addresses
375
+ void printProbesForAllAddresses (raw_ostream &OS);
376
+
377
+ // Look up the probe of a call for the input address
378
+ const MCDecodedPseudoProbe *getCallProbeForAddr (uint64_t Address) const ;
379
+
380
+ const MCPseudoProbeFuncDesc *getFuncDescForGUID (uint64_t GUID) const ;
381
+
382
+ // Helper function to populate one probe's inline stack into
383
+ // \p InlineContextStack.
384
+ // Current leaf location info will be added if IncludeLeaf is true
385
+ // Example:
386
+ // Current probe(bar:3) inlined at foo:2 then inlined at main:1
387
+ // IncludeLeaf = true, Output: [main:1, foo:2, bar:3]
388
+ // IncludeLeaf = false, Output: [main:1, foo:2]
389
+ void
390
+ getInlineContextForProbe (const MCDecodedPseudoProbe *Probe,
391
+ SmallVectorImpl<std::string> &InlineContextStack,
392
+ bool IncludeLeaf) const ;
393
+
394
+ const AddressProbesMap &getAddress2ProbesMap () const {
395
+ return Address2ProbesMap;
396
+ }
397
+
398
+ AddressProbesMap &getAddress2ProbesMap () { return Address2ProbesMap; }
399
+
400
+ const GUIDProbeFunctionMap &getGUID2FuncDescMap () const {
401
+ return GUID2FuncDescMap;
402
+ }
403
+
404
+ const MCPseudoProbeFuncDesc *
405
+ getInlinerDescForProbe (const MCDecodedPseudoProbe *Probe) const ;
406
+
407
+ const MCDecodedPseudoProbeInlineTree &getDummyInlineRoot () const {
408
+ return DummyInlineRoot;
409
+ }
410
+ };
411
+
175
412
} // end namespace llvm
176
413
177
414
#endif // LLVM_MC_MCPSEUDOPROBE_H
0 commit comments