blob: 6214a6b80c1be5e8759f0a3e0d2a32f09e1a0053 [file] [log] [blame]
Dean Michael Berrisa6c63432018-08-30 07:22:21 +00001//===- FDRTraceWriter.cpp - XRay FDR Trace Writer ---------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Test a utility that can write out XRay FDR Mode formatted trace files.
11//
12//===----------------------------------------------------------------------===//
13#include "llvm/XRay/FDRTraceWriter.h"
14#include <tuple>
15
16namespace llvm {
17namespace xray {
18
19namespace {
20
21struct alignas(32) FileHeader {
22 uint16_t Version;
23 uint16_t Type;
24 bool ConstantTSC : 1;
25 bool NonstopTSC : 1;
26 alignas(8) uint64_t CycleFrequency;
27 char FreeForm[16];
28};
29
30struct MetadataBlob {
31 uint8_t Type : 1;
32 uint8_t RecordKind : 7;
33 char Data[15];
34} __attribute__((packed));
35
36struct FunctionDeltaBlob {
37 uint8_t Type : 1;
38 uint8_t RecordKind : 3;
39 int FuncId : 28;
40 uint32_t TSCDelta;
41} __attribute__((packed));
42
43template <size_t Index> struct IndexedMemcpy {
44 template <
45 class Tuple,
46 typename std::enable_if<
47 (Index <
48 std::tuple_size<typename std::remove_reference<Tuple>::type>::value),
49 int>::type = 0>
50 static void Copy(char *Dest, Tuple &&T) {
51 auto Next = static_cast<char *>(std::memcpy(
52 Dest, reinterpret_cast<const char *>(&std::get<Index>(T)),
53 sizeof(std::get<Index>(T)))) +
54 sizeof(std::get<Index>(T));
55 IndexedMemcpy<Index + 1>::Copy(Next, T);
56 }
57
58 template <
59 class Tuple,
60 typename std::enable_if<
61 (Index >=
62 std::tuple_size<typename std::remove_reference<Tuple>::type>::value),
63 int>::type = 0>
64 static void Copy(char *, Tuple &&) {}
65};
66
67template <uint8_t Kind, class... Data>
68Error writeMetadata(raw_ostream &OS, Data... Ds) {
69 MetadataBlob B;
70 B.Type = 1;
71 B.RecordKind = Kind;
72 IndexedMemcpy<0>::Copy(B.Data, std::make_tuple(Ds...));
73 OS.write(reinterpret_cast<const char *>(&B), sizeof(MetadataBlob));
74 return Error::success();
75}
76
77} // namespace
78
79FDRTraceWriter::FDRTraceWriter(raw_ostream &O, const XRayFileHeader &H)
80 : OS(O) {
81 // We need to re-construct a header, by writing the fields we care about for
82 // traces, in the format that the runtime would have written.
83 FileHeader Raw;
84 Raw.Version = H.Version;
85 Raw.Type = H.Type;
86 Raw.ConstantTSC = H.ConstantTSC;
87 Raw.NonstopTSC = H.NonstopTSC;
88 Raw.CycleFrequency = H.CycleFrequency;
89 memcpy(&Raw.FreeForm, H.FreeFormData, 16);
90 OS.write(reinterpret_cast<const char *>(&Raw), sizeof(XRayFileHeader));
91}
92
93FDRTraceWriter::~FDRTraceWriter() {}
94
95Error FDRTraceWriter::visit(BufferExtents &R) {
96 return writeMetadata<7u>(OS, R.size());
97}
98
99Error FDRTraceWriter::visit(WallclockRecord &R) {
100 return writeMetadata<4u>(OS, R.seconds(), R.nanos());
101}
102
103Error FDRTraceWriter::visit(NewCPUIDRecord &R) {
104 return writeMetadata<2u>(OS, R.cpuid());
105}
106
107Error FDRTraceWriter::visit(TSCWrapRecord &R) {
108 return writeMetadata<3u>(OS, R.tsc());
109}
110
111Error FDRTraceWriter::visit(CustomEventRecord &R) {
112 if (auto E = writeMetadata<5u>(OS, R.size(), R.tsc()))
113 return E;
114 OS.write(R.data().data(), R.data().size());
115 return Error::success();
116}
117
118Error FDRTraceWriter::visit(CallArgRecord &R) {
119 return writeMetadata<6u>(OS, R.arg());
120}
121
122Error FDRTraceWriter::visit(PIDRecord &R) {
123 return writeMetadata<9u>(OS, R.pid());
124}
125
126Error FDRTraceWriter::visit(NewBufferRecord &R) {
127 return writeMetadata<0u>(OS, R.tid());
128}
129
130Error FDRTraceWriter::visit(EndBufferRecord &R) {
131 return writeMetadata<1u>(OS, 0);
132}
133
134Error FDRTraceWriter::visit(FunctionRecord &R) {
135 FunctionDeltaBlob B;
136 B.Type = 0;
137 B.RecordKind = static_cast<uint8_t>(R.recordType());
138 B.FuncId = R.functionId();
139 B.TSCDelta = R.delta();
140 OS.write(reinterpret_cast<const char *>(&B), sizeof(FunctionDeltaBlob));
141 return Error::success();
142}
143
144} // namespace xray
145} // namespace llvm