xref: /freebsd/contrib/llvm-project/llvm/include/llvm/XRay/FDRRecords.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- FDRRecords.h - XRay Flight Data Recorder Mode Records --------------===//
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 // Define types and operations on these types that represent the different kinds
10 // of records we encounter in XRay flight data recorder mode traces.
11 //
12 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_XRAY_FDRRECORDS_H
14 #define LLVM_XRAY_FDRRECORDS_H
15 
16 #include "llvm/Support/Compiler.h"
17 #include <cstdint>
18 #include <string>
19 
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/Support/Casting.h"
22 #include "llvm/Support/DataExtractor.h"
23 #include "llvm/Support/Error.h"
24 #include "llvm/XRay/XRayRecord.h"
25 
26 namespace llvm {
27 namespace xray {
28 
29 class RecordVisitor;
30 class RecordInitializer;
31 
32 class Record {
33 public:
34   enum class RecordKind {
35     RK_Metadata,
36     RK_Metadata_BufferExtents,
37     RK_Metadata_WallClockTime,
38     RK_Metadata_NewCPUId,
39     RK_Metadata_TSCWrap,
40     RK_Metadata_CustomEvent,
41     RK_Metadata_CustomEventV5,
42     RK_Metadata_CallArg,
43     RK_Metadata_PIDEntry,
44     RK_Metadata_NewBuffer,
45     RK_Metadata_EndOfBuffer,
46     RK_Metadata_TypedEvent,
47     RK_Metadata_LastMetadata,
48     RK_Function,
49   };
50 
51   LLVM_ABI static StringRef kindToString(RecordKind K);
52 
53 private:
54   const RecordKind T;
55 
56 public:
57   Record(const Record &) = delete;
58   Record(Record &&) = delete;
59   Record &operator=(const Record &) = delete;
60   Record &operator=(Record &&) = delete;
Record(RecordKind T)61   explicit Record(RecordKind T) : T(T) {}
62 
getRecordType()63   RecordKind getRecordType() const { return T; }
64 
65   // Each Record should be able to apply an abstract visitor, and choose the
66   // appropriate function in the visitor to invoke, given its own type.
67   virtual Error apply(RecordVisitor &V) = 0;
68 
69   virtual ~Record() = default;
70 };
71 
72 class MetadataRecord : public Record {
73 public:
74   enum class MetadataType : unsigned {
75     Unknown,
76     BufferExtents,
77     WallClockTime,
78     NewCPUId,
79     TSCWrap,
80     CustomEvent,
81     CallArg,
82     PIDEntry,
83     NewBuffer,
84     EndOfBuffer,
85     TypedEvent,
86   };
87 
88 protected:
89   static constexpr int kMetadataBodySize = 15;
90   friend class RecordInitializer;
91 
92 private:
93   const MetadataType MT;
94 
95 public:
MetadataRecord(RecordKind T,MetadataType M)96   explicit MetadataRecord(RecordKind T, MetadataType M) : Record(T), MT(M) {}
97 
classof(const Record * R)98   static bool classof(const Record *R) {
99     return R->getRecordType() >= RecordKind::RK_Metadata &&
100            R->getRecordType() <= RecordKind::RK_Metadata_LastMetadata;
101   }
102 
metadataType()103   MetadataType metadataType() const { return MT; }
104 
105   virtual ~MetadataRecord() = default;
106 };
107 
108 // What follows are specific Metadata record types which encapsulate the
109 // information associated with specific metadata record types in an FDR mode
110 // log.
111 class LLVM_ABI BufferExtents : public MetadataRecord {
112   uint64_t Size = 0;
113   friend class RecordInitializer;
114 
115 public:
BufferExtents()116   BufferExtents()
117       : MetadataRecord(RecordKind::RK_Metadata_BufferExtents,
118                        MetadataType::BufferExtents) {}
119 
BufferExtents(uint64_t S)120   explicit BufferExtents(uint64_t S)
121       : MetadataRecord(RecordKind::RK_Metadata_BufferExtents,
122                        MetadataType::BufferExtents),
123         Size(S) {}
124 
size()125   uint64_t size() const { return Size; }
126 
127   Error apply(RecordVisitor &V) override;
128 
classof(const Record * R)129   static bool classof(const Record *R) {
130     return R->getRecordType() == RecordKind::RK_Metadata_BufferExtents;
131   }
132 };
133 
134 class LLVM_ABI WallclockRecord : public MetadataRecord {
135   uint64_t Seconds = 0;
136   uint32_t Nanos = 0;
137   friend class RecordInitializer;
138 
139 public:
WallclockRecord()140   WallclockRecord()
141       : MetadataRecord(RecordKind::RK_Metadata_WallClockTime,
142                        MetadataType::WallClockTime) {}
143 
WallclockRecord(uint64_t S,uint32_t N)144   explicit WallclockRecord(uint64_t S, uint32_t N)
145       : MetadataRecord(RecordKind::RK_Metadata_WallClockTime,
146                        MetadataType::WallClockTime),
147         Seconds(S), Nanos(N) {}
148 
seconds()149   uint64_t seconds() const { return Seconds; }
nanos()150   uint32_t nanos() const { return Nanos; }
151 
152   Error apply(RecordVisitor &V) override;
153 
classof(const Record * R)154   static bool classof(const Record *R) {
155     return R->getRecordType() == RecordKind::RK_Metadata_WallClockTime;
156   }
157 };
158 
159 class LLVM_ABI NewCPUIDRecord : public MetadataRecord {
160   uint16_t CPUId = 0;
161   uint64_t TSC = 0;
162   friend class RecordInitializer;
163 
164 public:
NewCPUIDRecord()165   NewCPUIDRecord()
166       : MetadataRecord(RecordKind::RK_Metadata_NewCPUId,
167                        MetadataType::NewCPUId) {}
168 
NewCPUIDRecord(uint16_t C,uint64_t T)169   NewCPUIDRecord(uint16_t C, uint64_t T)
170       : MetadataRecord(RecordKind::RK_Metadata_NewCPUId,
171                        MetadataType::NewCPUId),
172         CPUId(C), TSC(T) {}
173 
cpuid()174   uint16_t cpuid() const { return CPUId; }
175 
tsc()176   uint64_t tsc() const { return TSC; }
177 
178   Error apply(RecordVisitor &V) override;
179 
classof(const Record * R)180   static bool classof(const Record *R) {
181     return R->getRecordType() == RecordKind::RK_Metadata_NewCPUId;
182   }
183 };
184 
185 class LLVM_ABI TSCWrapRecord : public MetadataRecord {
186   uint64_t BaseTSC = 0;
187   friend class RecordInitializer;
188 
189 public:
TSCWrapRecord()190   TSCWrapRecord()
191       : MetadataRecord(RecordKind::RK_Metadata_TSCWrap, MetadataType::TSCWrap) {
192   }
193 
TSCWrapRecord(uint64_t B)194   explicit TSCWrapRecord(uint64_t B)
195       : MetadataRecord(RecordKind::RK_Metadata_TSCWrap, MetadataType::TSCWrap),
196         BaseTSC(B) {}
197 
tsc()198   uint64_t tsc() const { return BaseTSC; }
199 
200   Error apply(RecordVisitor &V) override;
201 
classof(const Record * R)202   static bool classof(const Record *R) {
203     return R->getRecordType() == RecordKind::RK_Metadata_TSCWrap;
204   }
205 };
206 
207 class LLVM_ABI CustomEventRecord : public MetadataRecord {
208   int32_t Size = 0;
209   uint64_t TSC = 0;
210   uint16_t CPU = 0;
211   std::string Data{};
212   friend class RecordInitializer;
213 
214 public:
CustomEventRecord()215   CustomEventRecord()
216       : MetadataRecord(RecordKind::RK_Metadata_CustomEvent,
217                        MetadataType::CustomEvent) {}
218 
CustomEventRecord(uint64_t S,uint64_t T,uint16_t C,std::string D)219   explicit CustomEventRecord(uint64_t S, uint64_t T, uint16_t C, std::string D)
220       : MetadataRecord(RecordKind::RK_Metadata_CustomEvent,
221                        MetadataType::CustomEvent),
222         Size(S), TSC(T), CPU(C), Data(std::move(D)) {}
223 
size()224   int32_t size() const { return Size; }
tsc()225   uint64_t tsc() const { return TSC; }
cpu()226   uint16_t cpu() const { return CPU; }
data()227   StringRef data() const { return Data; }
228 
229   Error apply(RecordVisitor &V) override;
230 
classof(const Record * R)231   static bool classof(const Record *R) {
232     return R->getRecordType() == RecordKind::RK_Metadata_CustomEvent;
233   }
234 };
235 
236 class LLVM_ABI CustomEventRecordV5 : public MetadataRecord {
237   int32_t Size = 0;
238   int32_t Delta = 0;
239   std::string Data{};
240   friend class RecordInitializer;
241 
242 public:
CustomEventRecordV5()243   CustomEventRecordV5()
244       : MetadataRecord(RecordKind::RK_Metadata_CustomEventV5,
245                        MetadataType::CustomEvent) {}
246 
CustomEventRecordV5(int32_t S,int32_t D,std::string P)247   explicit CustomEventRecordV5(int32_t S, int32_t D, std::string P)
248       : MetadataRecord(RecordKind::RK_Metadata_CustomEventV5,
249                        MetadataType::CustomEvent),
250         Size(S), Delta(D), Data(std::move(P)) {}
251 
size()252   int32_t size() const { return Size; }
delta()253   int32_t delta() const { return Delta; }
data()254   StringRef data() const { return Data; }
255 
256   Error apply(RecordVisitor &V) override;
257 
classof(const Record * R)258   static bool classof(const Record *R) {
259     return R->getRecordType() == RecordKind::RK_Metadata_CustomEventV5;
260   }
261 };
262 
263 class LLVM_ABI TypedEventRecord : public MetadataRecord {
264   int32_t Size = 0;
265   int32_t Delta = 0;
266   uint16_t EventType = 0;
267   std::string Data{};
268   friend class RecordInitializer;
269 
270 public:
TypedEventRecord()271   TypedEventRecord()
272       : MetadataRecord(RecordKind::RK_Metadata_TypedEvent,
273                        MetadataType::TypedEvent) {}
274 
TypedEventRecord(int32_t S,int32_t D,uint16_t E,std::string P)275   explicit TypedEventRecord(int32_t S, int32_t D, uint16_t E, std::string P)
276       : MetadataRecord(RecordKind::RK_Metadata_TypedEvent,
277                        MetadataType::TypedEvent),
278         Size(S), Delta(D), Data(std::move(P)) {}
279 
size()280   int32_t size() const { return Size; }
delta()281   int32_t delta() const { return Delta; }
eventType()282   uint16_t eventType() const { return EventType; }
data()283   StringRef data() const { return Data; }
284 
285   Error apply(RecordVisitor &V) override;
286 
classof(const Record * R)287   static bool classof(const Record *R) {
288     return R->getRecordType() == RecordKind::RK_Metadata_TypedEvent;
289   }
290 };
291 
292 class LLVM_ABI CallArgRecord : public MetadataRecord {
293   uint64_t Arg = 0;
294   friend class RecordInitializer;
295 
296 public:
CallArgRecord()297   CallArgRecord()
298       : MetadataRecord(RecordKind::RK_Metadata_CallArg, MetadataType::CallArg) {
299   }
300 
CallArgRecord(uint64_t A)301   explicit CallArgRecord(uint64_t A)
302       : MetadataRecord(RecordKind::RK_Metadata_CallArg, MetadataType::CallArg),
303         Arg(A) {}
304 
arg()305   uint64_t arg() const { return Arg; }
306 
307   Error apply(RecordVisitor &V) override;
308 
classof(const Record * R)309   static bool classof(const Record *R) {
310     return R->getRecordType() == RecordKind::RK_Metadata_CallArg;
311   }
312 };
313 
314 class LLVM_ABI PIDRecord : public MetadataRecord {
315   int32_t PID = 0;
316   friend class RecordInitializer;
317 
318 public:
PIDRecord()319   PIDRecord()
320       : MetadataRecord(RecordKind::RK_Metadata_PIDEntry,
321                        MetadataType::PIDEntry) {}
322 
PIDRecord(int32_t P)323   explicit PIDRecord(int32_t P)
324       : MetadataRecord(RecordKind::RK_Metadata_PIDEntry,
325                        MetadataType::PIDEntry),
326         PID(P) {}
327 
pid()328   int32_t pid() const { return PID; }
329 
330   Error apply(RecordVisitor &V) override;
331 
classof(const Record * R)332   static bool classof(const Record *R) {
333     return R->getRecordType() == RecordKind::RK_Metadata_PIDEntry;
334   }
335 };
336 
337 class LLVM_ABI NewBufferRecord : public MetadataRecord {
338   int32_t TID = 0;
339   friend class RecordInitializer;
340 
341 public:
NewBufferRecord()342   NewBufferRecord()
343       : MetadataRecord(RecordKind::RK_Metadata_NewBuffer,
344                        MetadataType::NewBuffer) {}
345 
NewBufferRecord(int32_t T)346   explicit NewBufferRecord(int32_t T)
347       : MetadataRecord(RecordKind::RK_Metadata_NewBuffer,
348                        MetadataType::NewBuffer),
349         TID(T) {}
350 
tid()351   int32_t tid() const { return TID; }
352 
353   Error apply(RecordVisitor &V) override;
354 
classof(const Record * R)355   static bool classof(const Record *R) {
356     return R->getRecordType() == RecordKind::RK_Metadata_NewBuffer;
357   }
358 };
359 
360 class LLVM_ABI EndBufferRecord : public MetadataRecord {
361 public:
EndBufferRecord()362   EndBufferRecord()
363       : MetadataRecord(RecordKind::RK_Metadata_EndOfBuffer,
364                        MetadataType::EndOfBuffer) {}
365 
366   Error apply(RecordVisitor &V) override;
367 
classof(const Record * R)368   static bool classof(const Record *R) {
369     return R->getRecordType() == RecordKind::RK_Metadata_EndOfBuffer;
370   }
371 };
372 
373 class LLVM_ABI FunctionRecord : public Record {
374   RecordTypes Kind;
375   int32_t FuncId = 0;
376   uint32_t Delta = 0;
377   friend class RecordInitializer;
378 
379   static constexpr unsigned kFunctionRecordSize = 8;
380 
381 public:
FunctionRecord()382   FunctionRecord() : Record(RecordKind::RK_Function) {}
383 
FunctionRecord(RecordTypes K,int32_t F,uint32_t D)384   explicit FunctionRecord(RecordTypes K, int32_t F, uint32_t D)
385       : Record(RecordKind::RK_Function), Kind(K), FuncId(F), Delta(D) {}
386 
387   // A function record is a concrete record type which has a number of common
388   // properties.
recordType()389   RecordTypes recordType() const { return Kind; }
functionId()390   int32_t functionId() const { return FuncId; }
delta()391   uint32_t delta() const { return Delta; }
392 
393   Error apply(RecordVisitor &V) override;
394 
classof(const Record * R)395   static bool classof(const Record *R) {
396     return R->getRecordType() == RecordKind::RK_Function;
397   }
398 };
399 
400 class RecordVisitor {
401 public:
402   virtual ~RecordVisitor() = default;
403 
404   // Support all specific kinds of records:
405   virtual Error visit(BufferExtents &) = 0;
406   virtual Error visit(WallclockRecord &) = 0;
407   virtual Error visit(NewCPUIDRecord &) = 0;
408   virtual Error visit(TSCWrapRecord &) = 0;
409   virtual Error visit(CustomEventRecord &) = 0;
410   virtual Error visit(CallArgRecord &) = 0;
411   virtual Error visit(PIDRecord &) = 0;
412   virtual Error visit(NewBufferRecord &) = 0;
413   virtual Error visit(EndBufferRecord &) = 0;
414   virtual Error visit(FunctionRecord &) = 0;
415   virtual Error visit(CustomEventRecordV5 &) = 0;
416   virtual Error visit(TypedEventRecord &) = 0;
417 };
418 
419 class LLVM_ABI RecordInitializer : public RecordVisitor {
420   DataExtractor &E;
421   uint64_t &OffsetPtr;
422   uint16_t Version;
423 
424 public:
425   static constexpr uint16_t DefaultVersion = 5u;
426 
RecordInitializer(DataExtractor & DE,uint64_t & OP,uint16_t V)427   explicit RecordInitializer(DataExtractor &DE, uint64_t &OP, uint16_t V)
428       : E(DE), OffsetPtr(OP), Version(V) {}
429 
RecordInitializer(DataExtractor & DE,uint64_t & OP)430   explicit RecordInitializer(DataExtractor &DE, uint64_t &OP)
431       : RecordInitializer(DE, OP, DefaultVersion) {}
432 
433   Error visit(BufferExtents &) override;
434   Error visit(WallclockRecord &) override;
435   Error visit(NewCPUIDRecord &) override;
436   Error visit(TSCWrapRecord &) override;
437   Error visit(CustomEventRecord &) override;
438   Error visit(CallArgRecord &) override;
439   Error visit(PIDRecord &) override;
440   Error visit(NewBufferRecord &) override;
441   Error visit(EndBufferRecord &) override;
442   Error visit(FunctionRecord &) override;
443   Error visit(CustomEventRecordV5 &) override;
444   Error visit(TypedEventRecord &) override;
445 };
446 
447 } // namespace xray
448 } // namespace llvm
449 
450 #endif // LLVM_XRAY_FDRRECORDS_H
451