1 //===- 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 16 namespace llvm { 17 namespace xray { 18 19 namespace { 20 21 struct 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 30 struct MetadataBlob { 31 uint8_t Type : 1; 32 uint8_t RecordKind : 7; 33 char Data[15]; 34 }; 35 36 struct FunctionDeltaBlob { 37 uint8_t Type : 1; 38 uint8_t RecordKind : 3; 39 int FuncId : 28; 40 uint32_t TSCDelta; 41 }; 42 43 template <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 67 template <uint8_t Kind, class... Values> 68 Error writeMetadata(raw_ostream &OS, Values&&... Ds) { 69 MetadataBlob B; 70 B.Type = 1; 71 B.RecordKind = Kind; 72 std::memset(B.Data, 0, 15); 73 auto T = std::make_tuple(std::forward<Values>(std::move(Ds))...); 74 IndexedMemcpy<0>::Copy(B.Data, T); 75 OS.write(reinterpret_cast<const char *>(&B), sizeof(MetadataBlob)); 76 return Error::success(); 77 } 78 79 } // namespace 80 81 FDRTraceWriter::FDRTraceWriter(raw_ostream &O, const XRayFileHeader &H) 82 : OS(O) { 83 // We need to re-construct a header, by writing the fields we care about for 84 // traces, in the format that the runtime would have written. 85 FileHeader Raw; 86 Raw.Version = H.Version; 87 Raw.Type = H.Type; 88 Raw.ConstantTSC = H.ConstantTSC; 89 Raw.NonstopTSC = H.NonstopTSC; 90 Raw.CycleFrequency = H.CycleFrequency; 91 memcpy(&Raw.FreeForm, H.FreeFormData, 16); 92 OS.write(reinterpret_cast<const char *>(&Raw), sizeof(XRayFileHeader)); 93 } 94 95 FDRTraceWriter::~FDRTraceWriter() {} 96 97 Error FDRTraceWriter::visit(BufferExtents &R) { 98 return writeMetadata<7u>(OS, R.size()); 99 } 100 101 Error FDRTraceWriter::visit(WallclockRecord &R) { 102 return writeMetadata<4u>(OS, R.seconds(), R.nanos()); 103 } 104 105 Error FDRTraceWriter::visit(NewCPUIDRecord &R) { 106 return writeMetadata<2u>(OS, R.cpuid()); 107 } 108 109 Error FDRTraceWriter::visit(TSCWrapRecord &R) { 110 return writeMetadata<3u>(OS, R.tsc()); 111 } 112 113 Error FDRTraceWriter::visit(CustomEventRecord &R) { 114 if (auto E = writeMetadata<5u>(OS, R.size(), R.tsc())) 115 return E; 116 OS.write(R.data().data(), R.data().size()); 117 return Error::success(); 118 } 119 120 Error FDRTraceWriter::visit(CallArgRecord &R) { 121 return writeMetadata<6u>(OS, R.arg()); 122 } 123 124 Error FDRTraceWriter::visit(PIDRecord &R) { 125 return writeMetadata<9u>(OS, R.pid()); 126 } 127 128 Error FDRTraceWriter::visit(NewBufferRecord &R) { 129 return writeMetadata<0u>(OS, R.tid()); 130 } 131 132 Error FDRTraceWriter::visit(EndBufferRecord &R) { 133 return writeMetadata<1u>(OS, 0); 134 } 135 136 Error FDRTraceWriter::visit(FunctionRecord &R) { 137 FunctionDeltaBlob B; 138 B.Type = 0; 139 B.RecordKind = static_cast<uint8_t>(R.recordType()); 140 B.FuncId = R.functionId(); 141 B.TSCDelta = R.delta(); 142 OS.write(reinterpret_cast<const char *>(&B), sizeof(FunctionDeltaBlob)); 143 return Error::success(); 144 } 145 146 } // namespace xray 147 } // namespace llvm 148