FDRRecords.h revision 343210
1//===- FDRRecords.h - XRay Flight Data Recorder Mode Records --------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Define types and operations on these types that represent the different kinds
11// of records we encounter in XRay flight data recorder mode traces.
12//
13//===----------------------------------------------------------------------===//
14#ifndef LLVM_LIB_XRAY_FDRRECORDS_H_
15#define LLVM_LIB_XRAY_FDRRECORDS_H_
16
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
26namespace llvm {
27namespace xray {
28
29class RecordVisitor;
30class RecordInitializer;
31
32class Record {
33public:
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  static StringRef kindToString(RecordKind K);
52
53private:
54  const RecordKind T;
55
56public:
57  Record(const Record &) = delete;
58  Record(Record &&) = delete;
59  Record &operator=(const Record &) = delete;
60  Record &operator=(Record &&) = delete;
61  explicit Record(RecordKind T) : T(T) {}
62
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
72class MetadataRecord : public Record {
73public:
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
88protected:
89  static constexpr int kMetadataBodySize = 15;
90  friend class RecordInitializer;
91
92private:
93  const MetadataType MT;
94
95public:
96  explicit MetadataRecord(RecordKind T, MetadataType M) : Record(T), MT(M) {}
97
98  static bool classof(const Record *R) {
99    return R->getRecordType() >= RecordKind::RK_Metadata &&
100           R->getRecordType() <= RecordKind::RK_Metadata_LastMetadata;
101  }
102
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.
111class BufferExtents : public MetadataRecord {
112  uint64_t Size = 0;
113  friend class RecordInitializer;
114
115public:
116  BufferExtents()
117      : MetadataRecord(RecordKind::RK_Metadata_BufferExtents,
118                       MetadataType::BufferExtents) {}
119
120  explicit BufferExtents(uint64_t S)
121      : MetadataRecord(RecordKind::RK_Metadata_BufferExtents,
122                       MetadataType::BufferExtents),
123        Size(S) {}
124
125  uint64_t size() const { return Size; }
126
127  Error apply(RecordVisitor &V) override;
128
129  static bool classof(const Record *R) {
130    return R->getRecordType() == RecordKind::RK_Metadata_BufferExtents;
131  }
132};
133
134class WallclockRecord : public MetadataRecord {
135  uint64_t Seconds = 0;
136  uint32_t Nanos = 0;
137  friend class RecordInitializer;
138
139public:
140  WallclockRecord()
141      : MetadataRecord(RecordKind::RK_Metadata_WallClockTime,
142                       MetadataType::WallClockTime) {}
143
144  explicit WallclockRecord(uint64_t S, uint32_t N)
145      : MetadataRecord(RecordKind::RK_Metadata_WallClockTime,
146                       MetadataType::WallClockTime),
147        Seconds(S), Nanos(N) {}
148
149  uint64_t seconds() const { return Seconds; }
150  uint32_t nanos() const { return Nanos; }
151
152  Error apply(RecordVisitor &V) override;
153
154  static bool classof(const Record *R) {
155    return R->getRecordType() == RecordKind::RK_Metadata_WallClockTime;
156  }
157};
158
159class NewCPUIDRecord : public MetadataRecord {
160  uint16_t CPUId = 0;
161  uint64_t TSC = 0;
162  friend class RecordInitializer;
163
164public:
165  NewCPUIDRecord()
166      : MetadataRecord(RecordKind::RK_Metadata_NewCPUId,
167                       MetadataType::NewCPUId) {}
168
169  NewCPUIDRecord(uint16_t C, uint64_t T)
170      : MetadataRecord(RecordKind::RK_Metadata_NewCPUId,
171                       MetadataType::NewCPUId),
172        CPUId(C), TSC(T) {}
173
174  uint16_t cpuid() const { return CPUId; }
175
176  uint64_t tsc() const { return TSC; }
177
178  Error apply(RecordVisitor &V) override;
179
180  static bool classof(const Record *R) {
181    return R->getRecordType() == RecordKind::RK_Metadata_NewCPUId;
182  }
183};
184
185class TSCWrapRecord : public MetadataRecord {
186  uint64_t BaseTSC = 0;
187  friend class RecordInitializer;
188
189public:
190  TSCWrapRecord()
191      : MetadataRecord(RecordKind::RK_Metadata_TSCWrap, MetadataType::TSCWrap) {
192  }
193
194  explicit TSCWrapRecord(uint64_t B)
195      : MetadataRecord(RecordKind::RK_Metadata_TSCWrap, MetadataType::TSCWrap),
196        BaseTSC(B) {}
197
198  uint64_t tsc() const { return BaseTSC; }
199
200  Error apply(RecordVisitor &V) override;
201
202  static bool classof(const Record *R) {
203    return R->getRecordType() == RecordKind::RK_Metadata_TSCWrap;
204  }
205};
206
207class 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
214public:
215  CustomEventRecord()
216      : MetadataRecord(RecordKind::RK_Metadata_CustomEvent,
217                       MetadataType::CustomEvent) {}
218
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
224  int32_t size() const { return Size; }
225  uint64_t tsc() const { return TSC; }
226  uint16_t cpu() const { return CPU; }
227  StringRef data() const { return Data; }
228
229  Error apply(RecordVisitor &V) override;
230
231  static bool classof(const Record *R) {
232    return R->getRecordType() == RecordKind::RK_Metadata_CustomEvent;
233  }
234};
235
236class CustomEventRecordV5 : public MetadataRecord {
237  int32_t Size = 0;
238  int32_t Delta = 0;
239  std::string Data{};
240  friend class RecordInitializer;
241
242public:
243  CustomEventRecordV5()
244      : MetadataRecord(RecordKind::RK_Metadata_CustomEventV5,
245                       MetadataType::CustomEvent) {}
246
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
252  int32_t size() const { return Size; }
253  int32_t delta() const { return Delta; }
254  StringRef data() const { return Data; }
255
256  Error apply(RecordVisitor &V) override;
257
258  static bool classof(const Record *R) {
259    return R->getRecordType() == RecordKind::RK_Metadata_CustomEventV5;
260  }
261};
262
263class 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
270public:
271  TypedEventRecord()
272      : MetadataRecord(RecordKind::RK_Metadata_TypedEvent,
273                       MetadataType::TypedEvent) {}
274
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
280  int32_t size() const { return Size; }
281  int32_t delta() const { return Delta; }
282  uint16_t eventType() const { return EventType; }
283  StringRef data() const { return Data; }
284
285  Error apply(RecordVisitor &V) override;
286
287  static bool classof(const Record *R) {
288    return R->getRecordType() == RecordKind::RK_Metadata_TypedEvent;
289  }
290};
291
292class CallArgRecord : public MetadataRecord {
293  uint64_t Arg;
294  friend class RecordInitializer;
295
296public:
297  CallArgRecord()
298      : MetadataRecord(RecordKind::RK_Metadata_CallArg, MetadataType::CallArg) {
299  }
300
301  explicit CallArgRecord(uint64_t A)
302      : MetadataRecord(RecordKind::RK_Metadata_CallArg, MetadataType::CallArg),
303        Arg(A) {}
304
305  uint64_t arg() const { return Arg; }
306
307  Error apply(RecordVisitor &V) override;
308
309  static bool classof(const Record *R) {
310    return R->getRecordType() == RecordKind::RK_Metadata_CallArg;
311  }
312};
313
314class PIDRecord : public MetadataRecord {
315  int32_t PID = 0;
316  friend class RecordInitializer;
317
318public:
319  PIDRecord()
320      : MetadataRecord(RecordKind::RK_Metadata_PIDEntry,
321                       MetadataType::PIDEntry) {}
322
323  explicit PIDRecord(int32_t P)
324      : MetadataRecord(RecordKind::RK_Metadata_PIDEntry,
325                       MetadataType::PIDEntry),
326        PID(P) {}
327
328  int32_t pid() const { return PID; }
329
330  Error apply(RecordVisitor &V) override;
331
332  static bool classof(const Record *R) {
333    return R->getRecordType() == RecordKind::RK_Metadata_PIDEntry;
334  }
335};
336
337class NewBufferRecord : public MetadataRecord {
338  int32_t TID = 0;
339  friend class RecordInitializer;
340
341public:
342  NewBufferRecord()
343      : MetadataRecord(RecordKind::RK_Metadata_NewBuffer,
344                       MetadataType::NewBuffer) {}
345
346  explicit NewBufferRecord(int32_t T)
347      : MetadataRecord(RecordKind::RK_Metadata_NewBuffer,
348                       MetadataType::NewBuffer),
349        TID(T) {}
350
351  int32_t tid() const { return TID; }
352
353  Error apply(RecordVisitor &V) override;
354
355  static bool classof(const Record *R) {
356    return R->getRecordType() == RecordKind::RK_Metadata_NewBuffer;
357  }
358};
359
360class EndBufferRecord : public MetadataRecord {
361public:
362  EndBufferRecord()
363      : MetadataRecord(RecordKind::RK_Metadata_EndOfBuffer,
364                       MetadataType::EndOfBuffer) {}
365
366  Error apply(RecordVisitor &V) override;
367
368  static bool classof(const Record *R) {
369    return R->getRecordType() == RecordKind::RK_Metadata_EndOfBuffer;
370  }
371};
372
373class FunctionRecord : public Record {
374  RecordTypes Kind;
375  int32_t FuncId;
376  uint32_t Delta;
377  friend class RecordInitializer;
378
379  static constexpr unsigned kFunctionRecordSize = 8;
380
381public:
382  FunctionRecord() : Record(RecordKind::RK_Function) {}
383
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.
389  RecordTypes recordType() const { return Kind; }
390  int32_t functionId() const { return FuncId; }
391  uint32_t delta() const { return Delta; }
392
393  Error apply(RecordVisitor &V) override;
394
395  static bool classof(const Record *R) {
396    return R->getRecordType() == RecordKind::RK_Function;
397  }
398};
399
400class RecordVisitor {
401public:
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
419class RecordInitializer : public RecordVisitor {
420  DataExtractor &E;
421  uint32_t &OffsetPtr;
422  uint16_t Version;
423
424public:
425  static constexpr uint16_t DefaultVersion = 5u;
426
427  explicit RecordInitializer(DataExtractor &DE, uint32_t &OP, uint16_t V)
428      : RecordVisitor(), E(DE), OffsetPtr(OP), Version(V) {}
429
430  explicit RecordInitializer(DataExtractor &DE, uint32_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_LIB_XRAY_FDRRECORDS_H_
451