| //===- FDRRecords.h - XRay Flight Data Recorder Mode Records --------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // Define types and operations on these types that represent the different kinds |
| // of records we encounter in XRay flight data recorder mode traces. |
| // |
| //===----------------------------------------------------------------------===// |
| #ifndef LLVM_LIB_XRAY_FDRRECORDS_H_ |
| #define LLVM_LIB_XRAY_FDRRECORDS_H_ |
| |
| #include <cstdint> |
| #include <string> |
| |
| #include "llvm/ADT/StringRef.h" |
| #include "llvm/Support/Casting.h" |
| #include "llvm/Support/DataExtractor.h" |
| #include "llvm/Support/Error.h" |
| #include "llvm/XRay/XRayRecord.h" |
| |
| namespace llvm { |
| namespace xray { |
| |
| class RecordVisitor; |
| class RecordInitializer; |
| |
| class Record { |
| public: |
| enum class RecordKind { |
| RK_Metadata, |
| RK_Metadata_BufferExtents, |
| RK_Metadata_WallClockTime, |
| RK_Metadata_NewCPUId, |
| RK_Metadata_TSCWrap, |
| RK_Metadata_CustomEvent, |
| RK_Metadata_CustomEventV5, |
| RK_Metadata_CallArg, |
| RK_Metadata_PIDEntry, |
| RK_Metadata_NewBuffer, |
| RK_Metadata_EndOfBuffer, |
| RK_Metadata_TypedEvent, |
| RK_Metadata_LastMetadata, |
| RK_Function, |
| }; |
| |
| static StringRef kindToString(RecordKind K); |
| |
| private: |
| const RecordKind T; |
| |
| public: |
| Record(const Record &) = delete; |
| Record(Record &&) = delete; |
| Record &operator=(const Record &) = delete; |
| Record &operator=(Record &&) = delete; |
| explicit Record(RecordKind T) : T(T) {} |
| |
| RecordKind getRecordType() const { return T; } |
| |
| // Each Record should be able to apply an abstract visitor, and choose the |
| // appropriate function in the visitor to invoke, given its own type. |
| virtual Error apply(RecordVisitor &V) = 0; |
| |
| virtual ~Record() = default; |
| }; |
| |
| class MetadataRecord : public Record { |
| public: |
| enum class MetadataType : unsigned { |
| Unknown, |
| BufferExtents, |
| WallClockTime, |
| NewCPUId, |
| TSCWrap, |
| CustomEvent, |
| CallArg, |
| PIDEntry, |
| NewBuffer, |
| EndOfBuffer, |
| TypedEvent, |
| }; |
| |
| protected: |
| static constexpr int kMetadataBodySize = 15; |
| friend class RecordInitializer; |
| |
| private: |
| const MetadataType MT; |
| |
| public: |
| explicit MetadataRecord(RecordKind T, MetadataType M) : Record(T), MT(M) {} |
| |
| static bool classof(const Record *R) { |
| return R->getRecordType() >= RecordKind::RK_Metadata && |
| R->getRecordType() <= RecordKind::RK_Metadata_LastMetadata; |
| } |
| |
| MetadataType metadataType() const { return MT; } |
| |
| virtual ~MetadataRecord() = default; |
| }; |
| |
| // What follows are specific Metadata record types which encapsulate the |
| // information associated with specific metadata record types in an FDR mode |
| // log. |
| class BufferExtents : public MetadataRecord { |
| uint64_t Size = 0; |
| friend class RecordInitializer; |
| |
| public: |
| BufferExtents() |
| : MetadataRecord(RecordKind::RK_Metadata_BufferExtents, |
| MetadataType::BufferExtents) {} |
| |
| explicit BufferExtents(uint64_t S) |
| : MetadataRecord(RecordKind::RK_Metadata_BufferExtents, |
| MetadataType::BufferExtents), |
| Size(S) {} |
| |
| uint64_t size() const { return Size; } |
| |
| Error apply(RecordVisitor &V) override; |
| |
| static bool classof(const Record *R) { |
| return R->getRecordType() == RecordKind::RK_Metadata_BufferExtents; |
| } |
| }; |
| |
| class WallclockRecord : public MetadataRecord { |
| uint64_t Seconds = 0; |
| uint32_t Nanos = 0; |
| friend class RecordInitializer; |
| |
| public: |
| WallclockRecord() |
| : MetadataRecord(RecordKind::RK_Metadata_WallClockTime, |
| MetadataType::WallClockTime) {} |
| |
| explicit WallclockRecord(uint64_t S, uint32_t N) |
| : MetadataRecord(RecordKind::RK_Metadata_WallClockTime, |
| MetadataType::WallClockTime), |
| Seconds(S), Nanos(N) {} |
| |
| uint64_t seconds() const { return Seconds; } |
| uint32_t nanos() const { return Nanos; } |
| |
| Error apply(RecordVisitor &V) override; |
| |
| static bool classof(const Record *R) { |
| return R->getRecordType() == RecordKind::RK_Metadata_WallClockTime; |
| } |
| }; |
| |
| class NewCPUIDRecord : public MetadataRecord { |
| uint16_t CPUId = 0; |
| uint64_t TSC = 0; |
| friend class RecordInitializer; |
| |
| public: |
| NewCPUIDRecord() |
| : MetadataRecord(RecordKind::RK_Metadata_NewCPUId, |
| MetadataType::NewCPUId) {} |
| |
| NewCPUIDRecord(uint16_t C, uint64_t T) |
| : MetadataRecord(RecordKind::RK_Metadata_NewCPUId, |
| MetadataType::NewCPUId), |
| CPUId(C), TSC(T) {} |
| |
| uint16_t cpuid() const { return CPUId; } |
| |
| uint64_t tsc() const { return TSC; } |
| |
| Error apply(RecordVisitor &V) override; |
| |
| static bool classof(const Record *R) { |
| return R->getRecordType() == RecordKind::RK_Metadata_NewCPUId; |
| } |
| }; |
| |
| class TSCWrapRecord : public MetadataRecord { |
| uint64_t BaseTSC = 0; |
| friend class RecordInitializer; |
| |
| public: |
| TSCWrapRecord() |
| : MetadataRecord(RecordKind::RK_Metadata_TSCWrap, MetadataType::TSCWrap) { |
| } |
| |
| explicit TSCWrapRecord(uint64_t B) |
| : MetadataRecord(RecordKind::RK_Metadata_TSCWrap, MetadataType::TSCWrap), |
| BaseTSC(B) {} |
| |
| uint64_t tsc() const { return BaseTSC; } |
| |
| Error apply(RecordVisitor &V) override; |
| |
| static bool classof(const Record *R) { |
| return R->getRecordType() == RecordKind::RK_Metadata_TSCWrap; |
| } |
| }; |
| |
| class CustomEventRecord : public MetadataRecord { |
| int32_t Size = 0; |
| uint64_t TSC = 0; |
| uint16_t CPU = 0; |
| std::string Data{}; |
| friend class RecordInitializer; |
| |
| public: |
| CustomEventRecord() |
| : MetadataRecord(RecordKind::RK_Metadata_CustomEvent, |
| MetadataType::CustomEvent) {} |
| |
| explicit CustomEventRecord(uint64_t S, uint64_t T, uint16_t C, std::string D) |
| : MetadataRecord(RecordKind::RK_Metadata_CustomEvent, |
| MetadataType::CustomEvent), |
| Size(S), TSC(T), CPU(C), Data(std::move(D)) {} |
| |
| int32_t size() const { return Size; } |
| uint64_t tsc() const { return TSC; } |
| uint16_t cpu() const { return CPU; } |
| StringRef data() const { return Data; } |
| |
| Error apply(RecordVisitor &V) override; |
| |
| static bool classof(const Record *R) { |
| return R->getRecordType() == RecordKind::RK_Metadata_CustomEvent; |
| } |
| }; |
| |
| class CustomEventRecordV5 : public MetadataRecord { |
| int32_t Size = 0; |
| int32_t Delta = 0; |
| std::string Data{}; |
| friend class RecordInitializer; |
| |
| public: |
| CustomEventRecordV5() |
| : MetadataRecord(RecordKind::RK_Metadata_CustomEventV5, |
| MetadataType::CustomEvent) {} |
| |
| explicit CustomEventRecordV5(int32_t S, int32_t D, std::string P) |
| : MetadataRecord(RecordKind::RK_Metadata_CustomEventV5, |
| MetadataType::CustomEvent), |
| Size(S), Delta(D), Data(std::move(P)) {} |
| |
| int32_t size() const { return Size; } |
| int32_t delta() const { return Delta; } |
| StringRef data() const { return Data; } |
| |
| Error apply(RecordVisitor &V) override; |
| |
| static bool classof(const Record *R) { |
| return R->getRecordType() == RecordKind::RK_Metadata_CustomEventV5; |
| } |
| }; |
| |
| class TypedEventRecord : public MetadataRecord { |
| int32_t Size = 0; |
| int32_t Delta = 0; |
| uint16_t EventType = 0; |
| std::string Data{}; |
| friend class RecordInitializer; |
| |
| public: |
| TypedEventRecord() |
| : MetadataRecord(RecordKind::RK_Metadata_TypedEvent, |
| MetadataType::TypedEvent) {} |
| |
| explicit TypedEventRecord(int32_t S, int32_t D, uint16_t E, std::string P) |
| : MetadataRecord(RecordKind::RK_Metadata_TypedEvent, |
| MetadataType::TypedEvent), |
| Size(S), Delta(D), Data(std::move(P)) {} |
| |
| int32_t size() const { return Size; } |
| int32_t delta() const { return Delta; } |
| uint16_t eventType() const { return EventType; } |
| StringRef data() const { return Data; } |
| |
| Error apply(RecordVisitor &V) override; |
| |
| static bool classof(const Record *R) { |
| return R->getRecordType() == RecordKind::RK_Metadata_TypedEvent; |
| } |
| }; |
| |
| class CallArgRecord : public MetadataRecord { |
| uint64_t Arg = 0; |
| friend class RecordInitializer; |
| |
| public: |
| CallArgRecord() |
| : MetadataRecord(RecordKind::RK_Metadata_CallArg, MetadataType::CallArg) { |
| } |
| |
| explicit CallArgRecord(uint64_t A) |
| : MetadataRecord(RecordKind::RK_Metadata_CallArg, MetadataType::CallArg), |
| Arg(A) {} |
| |
| uint64_t arg() const { return Arg; } |
| |
| Error apply(RecordVisitor &V) override; |
| |
| static bool classof(const Record *R) { |
| return R->getRecordType() == RecordKind::RK_Metadata_CallArg; |
| } |
| }; |
| |
| class PIDRecord : public MetadataRecord { |
| int32_t PID = 0; |
| friend class RecordInitializer; |
| |
| public: |
| PIDRecord() |
| : MetadataRecord(RecordKind::RK_Metadata_PIDEntry, |
| MetadataType::PIDEntry) {} |
| |
| explicit PIDRecord(int32_t P) |
| : MetadataRecord(RecordKind::RK_Metadata_PIDEntry, |
| MetadataType::PIDEntry), |
| PID(P) {} |
| |
| int32_t pid() const { return PID; } |
| |
| Error apply(RecordVisitor &V) override; |
| |
| static bool classof(const Record *R) { |
| return R->getRecordType() == RecordKind::RK_Metadata_PIDEntry; |
| } |
| }; |
| |
| class NewBufferRecord : public MetadataRecord { |
| int32_t TID = 0; |
| friend class RecordInitializer; |
| |
| public: |
| NewBufferRecord() |
| : MetadataRecord(RecordKind::RK_Metadata_NewBuffer, |
| MetadataType::NewBuffer) {} |
| |
| explicit NewBufferRecord(int32_t T) |
| : MetadataRecord(RecordKind::RK_Metadata_NewBuffer, |
| MetadataType::NewBuffer), |
| TID(T) {} |
| |
| int32_t tid() const { return TID; } |
| |
| Error apply(RecordVisitor &V) override; |
| |
| static bool classof(const Record *R) { |
| return R->getRecordType() == RecordKind::RK_Metadata_NewBuffer; |
| } |
| }; |
| |
| class EndBufferRecord : public MetadataRecord { |
| public: |
| EndBufferRecord() |
| : MetadataRecord(RecordKind::RK_Metadata_EndOfBuffer, |
| MetadataType::EndOfBuffer) {} |
| |
| Error apply(RecordVisitor &V) override; |
| |
| static bool classof(const Record *R) { |
| return R->getRecordType() == RecordKind::RK_Metadata_EndOfBuffer; |
| } |
| }; |
| |
| class FunctionRecord : public Record { |
| RecordTypes Kind; |
| int32_t FuncId = 0; |
| uint32_t Delta = 0; |
| friend class RecordInitializer; |
| |
| static constexpr unsigned kFunctionRecordSize = 8; |
| |
| public: |
| FunctionRecord() : Record(RecordKind::RK_Function) {} |
| |
| explicit FunctionRecord(RecordTypes K, int32_t F, uint32_t D) |
| : Record(RecordKind::RK_Function), Kind(K), FuncId(F), Delta(D) {} |
| |
| // A function record is a concrete record type which has a number of common |
| // properties. |
| RecordTypes recordType() const { return Kind; } |
| int32_t functionId() const { return FuncId; } |
| uint32_t delta() const { return Delta; } |
| |
| Error apply(RecordVisitor &V) override; |
| |
| static bool classof(const Record *R) { |
| return R->getRecordType() == RecordKind::RK_Function; |
| } |
| }; |
| |
| class RecordVisitor { |
| public: |
| virtual ~RecordVisitor() = default; |
| |
| // Support all specific kinds of records: |
| virtual Error visit(BufferExtents &) = 0; |
| virtual Error visit(WallclockRecord &) = 0; |
| virtual Error visit(NewCPUIDRecord &) = 0; |
| virtual Error visit(TSCWrapRecord &) = 0; |
| virtual Error visit(CustomEventRecord &) = 0; |
| virtual Error visit(CallArgRecord &) = 0; |
| virtual Error visit(PIDRecord &) = 0; |
| virtual Error visit(NewBufferRecord &) = 0; |
| virtual Error visit(EndBufferRecord &) = 0; |
| virtual Error visit(FunctionRecord &) = 0; |
| virtual Error visit(CustomEventRecordV5 &) = 0; |
| virtual Error visit(TypedEventRecord &) = 0; |
| }; |
| |
| class RecordInitializer : public RecordVisitor { |
| DataExtractor &E; |
| uint64_t &OffsetPtr; |
| uint16_t Version; |
| |
| public: |
| static constexpr uint16_t DefaultVersion = 5u; |
| |
| explicit RecordInitializer(DataExtractor &DE, uint64_t &OP, uint16_t V) |
| : RecordVisitor(), E(DE), OffsetPtr(OP), Version(V) {} |
| |
| explicit RecordInitializer(DataExtractor &DE, uint64_t &OP) |
| : RecordInitializer(DE, OP, DefaultVersion) {} |
| |
| Error visit(BufferExtents &) override; |
| Error visit(WallclockRecord &) override; |
| Error visit(NewCPUIDRecord &) override; |
| Error visit(TSCWrapRecord &) override; |
| Error visit(CustomEventRecord &) override; |
| Error visit(CallArgRecord &) override; |
| Error visit(PIDRecord &) override; |
| Error visit(NewBufferRecord &) override; |
| Error visit(EndBufferRecord &) override; |
| Error visit(FunctionRecord &) override; |
| Error visit(CustomEventRecordV5 &) override; |
| Error visit(TypedEventRecord &) override; |
| }; |
| |
| } // namespace xray |
| } // namespace llvm |
| |
| #endif // LLVM_LIB_XRAY_FDRRECORDS_H_ |