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