blob: 9c318805d61b423858057767ca9ed5baa2caf252 [file] [log] [blame]
//===- 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_XRAY_FDRRECORDS_H
#define LLVM_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_XRAY_FDRRECORDS_H