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