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 uint32_t BitField; 25 uint64_t CycleFrequency; 26 char FreeForm[16]; 27 }; 28 29 struct MetadataBlob { 30 uint8_t Type : 1; 31 uint8_t RecordKind : 7; 32 char Data[15]; 33 }; 34 35 struct FunctionDeltaBlob { 36 uint8_t Type : 1; 37 uint8_t RecordKind : 3; 38 int FuncId : 28; 39 uint32_t TSCDelta; 40 }; 41 42 template <size_t Index> struct IndexedMemcpy { 43 template < 44 class Tuple, 45 typename std::enable_if< 46 (Index < 47 std::tuple_size<typename std::remove_reference<Tuple>::type>::value), 48 int>::type = 0> 49 static void Copy(char *Dest, Tuple &&T) { 50 auto Next = static_cast<char *>(std::memcpy( 51 Dest, reinterpret_cast<const char *>(&std::get<Index>(T)), 52 sizeof(std::get<Index>(T)))) + 53 sizeof(std::get<Index>(T)); 54 IndexedMemcpy<Index + 1>::Copy(Next, T); 55 } 56 57 template < 58 class Tuple, 59 typename std::enable_if< 60 (Index >= 61 std::tuple_size<typename std::remove_reference<Tuple>::type>::value), 62 int>::type = 0> 63 static void Copy(char *, Tuple &&) {} 64 }; 65 66 template <uint8_t Kind, class... Values> 67 Error writeMetadata(raw_ostream &OS, Values &&... Ds) { 68 MetadataBlob B; 69 B.Type = 1; 70 B.RecordKind = Kind; 71 std::memset(B.Data, 0, 15); 72 auto T = std::make_tuple(std::forward<Values>(std::move(Ds))...); 73 IndexedMemcpy<0>::Copy(B.Data, T); 74 OS.write(reinterpret_cast<const char *>(&B), sizeof(MetadataBlob)); 75 return Error::success(); 76 } 77 78 } // namespace 79 80 FDRTraceWriter::FDRTraceWriter(raw_ostream &O, const XRayFileHeader &H) 81 : OS(O) { 82 // We need to re-construct a header, by writing the fields we care about for 83 // traces, in the format that the runtime would have written. 84 FileHeader Raw; 85 Raw.Version = H.Version; 86 Raw.Type = H.Type; 87 Raw.BitField = (H.ConstantTSC ? 0x01 : 0x0) | (H.NonstopTSC ? 0x02 : 0x0); 88 Raw.CycleFrequency = H.CycleFrequency; 89 memcpy(&Raw.FreeForm, H.FreeFormData, 16); 90 OS.write(reinterpret_cast<const char *>(&Raw), sizeof(XRayFileHeader)); 91 } 92 93 FDRTraceWriter::~FDRTraceWriter() {} 94 95 Error FDRTraceWriter::visit(BufferExtents &R) { 96 return writeMetadata<7u>(OS, R.size()); 97 } 98 99 Error FDRTraceWriter::visit(WallclockRecord &R) { 100 return writeMetadata<4u>(OS, R.seconds(), R.nanos()); 101 } 102 103 Error FDRTraceWriter::visit(NewCPUIDRecord &R) { 104 return writeMetadata<2u>(OS, R.cpuid()); 105 } 106 107 Error FDRTraceWriter::visit(TSCWrapRecord &R) { 108 return writeMetadata<3u>(OS, R.tsc()); 109 } 110 111 Error 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 118 Error FDRTraceWriter::visit(CallArgRecord &R) { 119 return writeMetadata<6u>(OS, R.arg()); 120 } 121 122 Error FDRTraceWriter::visit(PIDRecord &R) { 123 return writeMetadata<9u>(OS, R.pid()); 124 } 125 126 Error FDRTraceWriter::visit(NewBufferRecord &R) { 127 return writeMetadata<0u>(OS, R.tid()); 128 } 129 130 Error FDRTraceWriter::visit(EndBufferRecord &R) { 131 return writeMetadata<1u>(OS, 0); 132 } 133 134 Error 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 146