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

source code of llvm/include/llvm/XRay/FDRRecords.h