Index: test/tools/llvm-xray/X86/convert-roundtrip.yaml =================================================================== --- /dev/null +++ test/tools/llvm-xray/X86/convert-roundtrip.yaml @@ -0,0 +1,28 @@ +#RUN: llvm-xray convert %s -i=yaml -f=raw -o %t && llvm-xray convert %t -f=yaml -o - | FileCheck %s +--- +header: + version: 1 + type: 0 + constant-tsc: true + nonstop-tsc: true + cycle-frequency: 2601000000 +records: + - { type: 0, func-id: 1, cpu: 1, thread: 111, kind: function-enter, + tsc: 10001 } + - { type: 0, func-id: 1, cpu: 1, thread: 111, kind: function-exit, + tsc: 10100 } +... + +#CHECK: --- +#CHECK-NEXT: header: +#CHECK-NEXT: version: 1 +#CHECK-NEXT: type: 0 +#CHECK-NEXT: constant-tsc: true +#CHECK-NEXT: nonstop-tsc: true +#CHECK-NEXT: cycle-frequency: 2601000000 +#CHECK-NEXT: records: +#CHECK-NEXT: - { type: 0, func-id: 1, function: '1', cpu: 1, thread: 111, kind: function-enter, +#CHECK-NEXT: tsc: 10001 } +#CHECK-NEXT: - { type: 0, func-id: 1, function: '1', cpu: 1, thread: 111, kind: function-exit, +#CHECK-NEXT: tsc: 10100 } +#CHECK-NEXT: ... Index: tools/llvm-xray/CMakeLists.txt =================================================================== --- tools/llvm-xray/CMakeLists.txt +++ tools/llvm-xray/CMakeLists.txt @@ -1,10 +1,16 @@ set(LLVM_LINK_COMPONENTS ${LLVM_TARGETS_TO_BUILD} + DebugInfoDWARF + Object Support - Object) + Symbolize) set(LLVM_XRAY_TOOLS + func-id-helper.cc + xray-converter.cc xray-extract.cc + xray-extract.cc + xray-log-reader.cc xray-registry.cc) add_llvm_tool(llvm-xray llvm-xray.cc ${LLVM_XRAY_TOOLS}) Index: tools/llvm-xray/func-id-helper.h =================================================================== --- /dev/null +++ tools/llvm-xray/func-id-helper.h @@ -0,0 +1,51 @@ +//===- func-id-helper.h - XRay Function ID Conversion Helpers -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines helper tools dealing with XRay-generated function ids. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_TOOLS_LLVM_XRAY_FUNC_ID_HELPER_H +#define LLVM_TOOLS_LLVM_XRAY_FUNC_ID_HELPER_H + +#include "llvm/DebugInfo/Symbolize/Symbolize.h" +#include + +namespace llvm { +namespace xray { + +// This class consolidates common operations related to Function IDs. +class FuncIdConversionHelper { +public: + using FunctionAddressMap = std::unordered_map; + +private: + std::string BinaryInstrMap; + symbolize::LLVMSymbolizer &Symbolizer; + const FunctionAddressMap &FunctionAddresses; + +public: + FuncIdConversionHelper(std::string BinaryInstrMap, + symbolize::LLVMSymbolizer &Symbolizer, + const FunctionAddressMap &FunctionAddresses) + : BinaryInstrMap(std::move(BinaryInstrMap)), Symbolizer(Symbolizer), + FunctionAddresses(FunctionAddresses) {} + + FuncIdConversionHelper(const FuncIdConversionHelper &) = default; + + // Returns the symbol or a string representation of the function id. + std::string SymbolOrNumber(int32_t FuncId) const; + + // Returns the file and column from debug info for the given function id. + std::string FileLineAndColumn(int32_t FuncId) const; +}; + +} // namespace xray +} // namespace llvm + +#endif // LLVM_TOOLS_LLVM_XRAY_FUNC_ID_HELPER_H Index: tools/llvm-xray/func-id-helper.cc =================================================================== --- /dev/null +++ tools/llvm-xray/func-id-helper.cc @@ -0,0 +1,56 @@ +//===- xray-fc-account.cc - XRay Function Call Accounting Tool ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implementation of the helper tools dealing with XRay-generated function ids. +// +//===----------------------------------------------------------------------===// + +#include +#include "func-id-helper.h" + +using namespace llvm; +using namespace xray; + +std::string FuncIdConversionHelper::SymbolOrNumber(int32_t FuncId) const { + std::ostringstream F; + auto It = FunctionAddresses.find(FuncId); + if (It == FunctionAddresses.end()) { + F << "#" << FuncId; + return F.str(); + } + + auto ResOrErr = Symbolizer.symbolizeCode(BinaryInstrMap, It->second); + if (!ResOrErr || ResOrErr.get().FunctionName == "") { + F << "@(" << std::hex << It->second << ")"; + } else { + auto &DI = ResOrErr.get(); + F << DI.FunctionName; + } + return F.str(); +} + +std::string FuncIdConversionHelper::FileLineAndColumn(int32_t FuncId) const { + auto It = FunctionAddresses.find(FuncId); + if (It == FunctionAddresses.end()) { + return "(unknown)"; + } + std::ostringstream F; + auto ResOrErr = Symbolizer.symbolizeCode(BinaryInstrMap, It->second); + if (!ResOrErr || ResOrErr.get().FileName == "") + return "(unknown)"; + auto &DI = ResOrErr.get(); + auto LastSlash = DI.FileName.find_last_of('/'); + if (LastSlash != std::string::npos) { + F << DI.FileName.substr(LastSlash + 1); + } else { + F << DI.FileName; + } + F << ":" << DI.Line << ":" << DI.Column; + return F.str(); +} Index: tools/llvm-xray/llvm-xray.cc =================================================================== --- tools/llvm-xray/llvm-xray.cc +++ tools/llvm-xray/llvm-xray.cc @@ -18,8 +18,6 @@ // #include "xray-registry.h" #include "llvm/Support/CommandLine.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/raw_ostream.h" #include using namespace llvm; Index: tools/llvm-xray/xray-converter.h =================================================================== --- /dev/null +++ tools/llvm-xray/xray-converter.h @@ -0,0 +1,39 @@ +//===- xray-converter.h - XRay Trace Conversion ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines the TraceConverter class for turning binary traces into +// human-readable text and vice versa. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_TOOLS_LLVM_XRAY_XRAY_CONVERTER_H +#define LLVM_TOOLS_LLVM_XRAY_XRAY_CONVERTER_H + +#include "func-id-helper.h" +#include "xray-log-reader.h" +#include "xray-record.h" + +namespace llvm { +namespace xray { + +class TraceConverter { + FuncIdConversionHelper &FuncIdHelper; + bool Symbolize; + +public: + TraceConverter(FuncIdConversionHelper &FuncIdHelper, bool Symbolize = false) + : FuncIdHelper(FuncIdHelper), Symbolize(Symbolize) {} + + void exportAsYAML(const NaiveLogReader &Records, raw_ostream &OS); + void exportAsRAW(const YAMLLogReader &Records, int Fd); +}; + +} // namespace xray +} // namespace llvm + +#endif // LLVM_TOOLS_LLVM_XRAY_XRAY_CONVERTER_H Index: tools/llvm-xray/xray-converter.cc =================================================================== --- /dev/null +++ tools/llvm-xray/xray-converter.cc @@ -0,0 +1,241 @@ +//===- xray-converter.cc - XRay Trace Conversion --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implements the trace conversion functions. +// +//===----------------------------------------------------------------------===// +#include "xray-converter.h" + +#include "xray-extract.h" +#include "xray-record-yaml.h" +#include "xray-registry.h" +#include "llvm/DebugInfo/Symbolize/Symbolize.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/YAMLTraits.h" +#include "llvm/Support/raw_ostream.h" +#include + +using namespace llvm; +using namespace xray; + +// llvm-xray convert +// ---------------------------------------------------------------------------- +static cl::SubCommand Convert("convert", "Trace Format Conversion"); +static cl::opt ConvertInput(cl::Positional, + cl::desc(""), + cl::Required, cl::sub(Convert)); +enum class ConvertFormats { BINARY, YAML }; +static cl::opt ConvertInputFormat( + "input-format", cl::desc("input format"), + cl::values(clEnumValN(ConvertFormats::BINARY, "raw", + "input is in raw binary"), + clEnumValN(ConvertFormats::YAML, "yaml", "input is in yaml")), + cl::sub(Convert)); +static cl::alias ConvertInputFormat2("i", cl::aliasopt(ConvertInputFormat), + cl::desc("Alias for -input-format"), + cl::sub(Convert)); +static cl::opt ConvertOutputFormat( + "output-format", cl::desc("output format"), + cl::values(clEnumValN(ConvertFormats::BINARY, "raw", "output in binary"), + clEnumValN(ConvertFormats::YAML, "yaml", "output in yaml")), + cl::sub(Convert)); +static cl::alias ConvertOutputFormat2("f", cl::aliasopt(ConvertOutputFormat), + cl::desc("Alias for -output-format"), + cl::sub(Convert)); +static cl::opt + ConvertOutput("output", cl::value_desc("output file"), cl::init("-"), + cl::desc("output file; use '-' for stdout"), + cl::sub(Convert)); +static cl::alias ConvertOutput2("o", cl::aliasopt(ConvertOutput), + cl::desc("Alias for -output"), + cl::sub(Convert)); + +static cl::opt + ConvertSymbolize("symbolize", + cl::desc("symbolize function ids from the input log"), + cl::init(false), cl::sub(Convert)); + +static cl::opt + ConvertInstrMap("instr_map", + cl::desc("binary with the instrumentation map, or " + "a separate instrumentation map"), + cl::value_desc("binary with xray_instr_map"), + cl::sub(Convert), cl::init("")); +static cl::alias ConvertInstrMap2("m", cl::aliasopt(ConvertInstrMap), + cl::desc("Alias for -instr_map"), + cl::sub(Convert)); +static cl::opt ConvertSortInput( + "sort", + cl::desc("determines whether to sort input log records by timestamp"), + cl::sub(Convert), cl::init(true)); +static cl::alias ConvertSortInput2("s", cl::aliasopt(ConvertSortInput), + cl::desc("Alias for -sort"), + cl::sub(Convert)); +static cl::opt InstrMapFormat( + "instr-map-format", cl::desc("format of instrumentation map"), + cl::values(clEnumValN(InstrumentationMapExtractor::InputFormats::ELF, "elf", + "instrumentation map in an ELF header"), + clEnumValN(InstrumentationMapExtractor::InputFormats::YAML, + "yaml", "instrumentation map in YAML")), + cl::sub(Convert), cl::init(InstrumentationMapExtractor::InputFormats::ELF)); +static cl::alias InstrMapFormat2("t", cl::aliasopt(InstrMapFormat), + cl::desc("Alias for -instr-map-format"), + cl::sub(Convert)); + +using llvm::yaml::MappingTraits; +using llvm::yaml::ScalarEnumerationTraits; +using llvm::yaml::IO; +using llvm::yaml::Output; + +void TraceConverter::exportAsYAML(const NaiveLogReader &Records, + raw_ostream &OS) { + YAMLXRayTrace Trace; + const auto &FH = Records.getFileHeader(); + Trace.Header = {FH.Version, FH.Type, FH.ConstantTSC, FH.NonstopTSC, + FH.CycleFrequency}; + Trace.Records.reserve(Records.size()); + for (const auto &R : Records) { + Trace.Records.push_back( + {R.RecordType, R.CPU, + R.Type == 0 ? RecordTypes::ENTER : RecordTypes::EXIT, R.FuncId, + Symbolize ? FuncIdHelper.SymbolOrNumber(R.FuncId) + : std::to_string(R.FuncId), + R.TSC, R.TId}); + } + Output Out(OS); + Out << Trace; +} + +namespace { + +void retryingWriteAll(int Fd, const char *Begin, const char *End) { + if (Begin == End) + return; + auto TotalBytes = std::distance(Begin, End); + while (auto Written = write(Fd, Begin, TotalBytes)) { + if (Written < 0) { + if (errno == EINTR) + continue; + return; + } + TotalBytes -= Written; + if (TotalBytes == 0) + break; + Begin += Written; + } + return; +} + +} // namespace + +void TraceConverter::exportAsRAW(const YAMLLogReader &Records, int Fd) { + retryingWriteAll(Fd, reinterpret_cast(&Records.getFileHeader()), + reinterpret_cast(&Records.getFileHeader()) + + sizeof(XRayFileHeader)); + + // Now we write each record as binary. + std::aligned_storage::type Buffer; + for (const auto &Y : Records) { + std::ignore = toXRayRecord(Y, Buffer); + retryingWriteAll(Fd, reinterpret_cast(&Buffer), + reinterpret_cast(&Buffer) + + sizeof(XRayRecord)); + } +} + +namespace llvm { +namespace xray { + +static CommandRegistration Unused(&Convert, [] { + if (ConvertInputFormat == ConvertOutputFormat) { + errs() << "-input-format and -output-format are the same, bailing out.\n"; + return 1; + } + int Fd; + auto EC = sys::fs::openFileForRead(ConvertInput, Fd); + if (EC) { + errs() << "Cannot open file '" << ConvertInput << "' for reading.\n"; + return 1; + } + xray::InstrumentationMapExtractor Extractor(ConvertInstrMap, InstrMapFormat, + EC); + const auto &FunctionAddresses = Extractor.getFunctionAddresses(); + symbolize::LLVMSymbolizer::Options Opts( + symbolize::FunctionNameKind::LinkageName, true, true, false, ""); + symbolize::LLVMSymbolizer Symbolizer(Opts); + llvm::xray::FuncIdConversionHelper FuncIdHelper(ConvertInstrMap, Symbolizer, + FunctionAddresses); + llvm::xray::TraceConverter TC(FuncIdHelper, ConvertSymbolize); + switch (ConvertInputFormat) { + case ConvertFormats::BINARY: { + xray::NaiveLogReader LogReader(Fd, EC, ConvertSortInput); + if (EC) { + errs() << "Failed loading input file '" << ConvertInput << "'\n"; + return 1; + } + if (LogReader.getFileHeader().Version != 1) { + errs() << "Unsupported XRay file version: " + << LogReader.getFileHeader().Version << '\n'; + return 1; + } + raw_fd_ostream OS(ConvertOutput, EC, + ConvertOutputFormat == ConvertFormats::BINARY + ? sys::fs::OpenFlags::F_None + : sys::fs::OpenFlags::F_Text); + if (EC) { + errs() << "Cannot open file '" << ConvertOutput << "' for writing.\n"; + return 1; + } + switch (ConvertOutputFormat) { + case ConvertFormats::YAML: + TC.exportAsYAML(LogReader, OS); + return 0; + default: + errs() << "input-output conversion for provided formats not supported " + "yet.\n"; + return 1; + } + break; + } + case ConvertFormats::YAML: { + xray::YAMLLogReader LogReader(Fd, EC, ConvertSortInput); + if (EC) { + errs() << "Failed loading input file '" << ConvertInput << "'\n"; + return 1; + } + if (LogReader.getFileHeader().Version != 1) { + errs() << "Unsupported XRay file version: " + << LogReader.getFileHeader().Version << '\n'; + return 1; + } + int Fd; + sys::fs::openFileForWrite(ConvertOutput, Fd, sys::fs::OpenFlags::F_None); + if (EC) { + errs() << "Cannot open file '" << ConvertOutput << "' for writing.\n"; + return 1; + } + switch (ConvertOutputFormat) { + case ConvertFormats::BINARY: + TC.exportAsRAW(LogReader, Fd); + close(Fd); + return 0; + default: + errs() << "input-output conversion for provided formats not supported " + "yet.\n"; + close(Fd); + return 1; + } + break; + } + } + return 0; +}); + +} // namespace xray +} // namespace llvm Index: tools/llvm-xray/xray-log-reader.h =================================================================== --- /dev/null +++ tools/llvm-xray/xray-log-reader.h @@ -0,0 +1,79 @@ +//===- xray-log-reader.h - XRay Log Reader Interface ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Define the interface for an XRay log reader. Currently we only support one +// version of the log (naive log) with fixed-sized records. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_TOOLS_LLVM_XRAY_XRAY_LOG_READER_H +#define LLVM_TOOLS_LLVM_XRAY_XRAY_LOG_READER_H + +#include +#include +#include + +#include "xray-record-yaml.h" +#include "xray-record.h" + +namespace llvm { +namespace xray { + +class NaiveLogReader { + XRayFileHeader FileHeader; + typedef std::deque RecordsDeque; + RecordsDeque Records; + using iterator = RecordsDeque::iterator; + using citerator = RecordsDeque::const_iterator; + +public: + // Loads the contents of the file into memory, then sorts the events by TSC if + // |Sort| is true. + explicit NaiveLogReader(int Fd, std::error_code &EC, bool Sort = true); + + const XRayFileHeader &getFileHeader() const { return FileHeader; } + + iterator begin() { return Records.begin(); } + iterator end() { return Records.end(); } + citerator cbegin() { return Records.cbegin(); } + citerator cend() { return Records.cend(); } + citerator begin() const { return Records.begin(); } + citerator end() const { return Records.end(); } + citerator cbegin() const { return Records.begin(); } + citerator cend() const { return Records.end(); } + size_t size() const { return Records.size(); } +}; + +class YAMLLogReader { + XRayFileHeader FileHeader; + typedef std::vector RecordsVector; + RecordsVector Records; + using iterator = RecordsVector::iterator; + using citerator = RecordsVector::const_iterator; + +public: + // Loads the contents of the file from |Fd|, parses the YAML and turns those + // into XRayRecord entries. Sorts the events by TSC if |Sort| is true. + explicit YAMLLogReader(int Fd, std::error_code &EC, bool Sort = true); + + const XRayFileHeader &getFileHeader() const { return FileHeader; }; + iterator begin() { return Records.begin(); } + iterator end() { return Records.end(); } + citerator cbegin() { return Records.cbegin(); } + citerator cend() { return Records.cend(); } + citerator begin() const { return Records.begin(); } + citerator end() const { return Records.end(); } + citerator cbegin() const { return Records.begin(); } + citerator cend() const { return Records.end(); } + size_t size() const { return Records.size(); } +}; + +} // namespace xray +} // namespace llvm + +#endif // LLVM_TOOLS_LLVM_XRAY_XRAY_LOG_READER_H Index: tools/llvm-xray/xray-log-reader.cc =================================================================== --- /dev/null +++ tools/llvm-xray/xray-log-reader.cc @@ -0,0 +1,86 @@ +//===- xray-log-reader.cc - XRay Log Reader Implementation ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// XRay log reader implementation. +// +//===----------------------------------------------------------------------===// +#include +#include + +#include "xray-log-reader.h" +#include "xray-record-yaml.h" +#include "llvm/Support/FileSystem.h" + +using namespace llvm; +using namespace llvm::xray; +using llvm::yaml::Input; + +NaiveLogReader::NaiveLogReader(int Fd, std::error_code &EC, bool Sort) { + off_t FileSize; + while ((FileSize = lseek(Fd, 0, SEEK_END)) == -1) { + if (errno == EINTR) + continue; + } + assert(FileSize != -1 && "Error seeking to the end of file"); + sys::fs::mapped_file_region MappedFile( + Fd, sys::fs::mapped_file_region::mapmode::readonly, FileSize, 0, EC); + if (EC) + return; + + // Set up the FileHeader. + memcpy(&FileHeader, MappedFile.data(), sizeof(XRayFileHeader)); + + // Start copying the data from the MappedFile into the Records data structure. + auto I = MappedFile.data() + sizeof(XRayFileHeader); + auto E = MappedFile.data() + MappedFile.size(); + while (I + sizeof(XRayRecord) <= E) { + Records.push_back({}); + memcpy(&Records.back(), I, sizeof(XRayRecord)); + I += sizeof(XRayRecord); + } + + if (Sort) + std::sort( + Records.begin(), Records.end(), + [](const XRayRecord &L, const XRayRecord &R) { return L.TSC < R.TSC; }); +} + +YAMLLogReader::YAMLLogReader(int Fd, std::error_code &EC, bool Sort) { + off_t FileSize; + while ((FileSize = lseek(Fd, 0, SEEK_END)) == -1) { + if (errno == EINTR) + continue; + } + assert(FileSize != -1 && "Error seeking to the end of the file"); + sys::fs::mapped_file_region MappedFile( + Fd, sys::fs::mapped_file_region::mapmode::readonly, FileSize, 0, EC); + if (EC) + return; + + // Load the documents from the MappedFile. + YAMLXRayTrace Trace; + Input In(StringRef(MappedFile.data(), FileSize)); + In >> Trace; + if (In.error()) { + EC = std::make_error_code(std::errc::io_error); + return; + } + // Only read the first trace in the document. + FileHeader.Version = Trace.Header.Version; + FileHeader.Type = Trace.Header.Type; + FileHeader.ConstantTSC = Trace.Header.ConstantTSC; + FileHeader.NonstopTSC = Trace.Header.NonstopTSC; + FileHeader.CycleFrequency = Trace.Header.CycleFrequency; + Records.swap(Trace.Records); + if (Sort) + std::sort(Records.begin(), Records.end(), + [](const YAMLXRayRecord &L, const YAMLXRayRecord &R) { + return L.TSC < R.TSC; + }); +} Index: tools/llvm-xray/xray-record-yaml.h =================================================================== --- /dev/null +++ tools/llvm-xray/xray-record-yaml.h @@ -0,0 +1,126 @@ +//===- xray-record-yaml.h - XRay Record YAML Support Definitions ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Types and traits specialisations for YAML I/O of XRay log entries. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_TOOLS_LLVM_XRAY_XRAY_RECORD_YAML_H +#define LLVM_TOOLS_LLVM_XRAY_XRAY_RECORD_YAML_H + +#include + +#include "xray-record.h" +#include "llvm/Support/YAMLTraits.h" + +namespace llvm { +namespace xray { + +struct YAMLXRayFileHeader { + uint16_t Version; + uint16_t Type; + bool ConstantTSC; + bool NonstopTSC; + uint64_t CycleFrequency; +}; + +enum class RecordTypes { ENTER, EXIT }; + +struct YAMLXRayRecord { + uint16_t RecordType; + uint8_t CPU; + RecordTypes Type; + int32_t FuncId; + std::string Function; + uint64_t TSC; + uint32_t TId; +}; + +struct YAMLXRayTrace { + YAMLXRayFileHeader Header; + std::vector Records; +}; + +using XRayRecordStorage = + std::aligned_storage::type; + +/// Converts a YAMLXRayRecord into an XRayRecord stored in an aligned storage +/// buffer |Buf| then returns a reference to that object. +inline XRayRecord &toXRayRecord(const YAMLXRayRecord &Y, + XRayRecordStorage &Buf) { + XRayRecord &R = *reinterpret_cast(&Buf); + R.RecordType = Y.RecordType; + R.CPU = Y.CPU; + switch (Y.Type) { + case RecordTypes::ENTER: + R.Type = 0; + break; + case RecordTypes::EXIT: + R.Type = 1; + break; + } + R.FuncId = Y.FuncId; + R.TSC = Y.TSC; + R.TId = Y.TId; + memset(R.Buffer, 0, sizeof(R.Buffer)); + return R; +} + +} // namespace xray + +namespace yaml { + +// YAML Traits +// ----------- +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, xray::RecordTypes &Type) { + IO.enumCase(Type, "function-enter", xray::RecordTypes::ENTER); + IO.enumCase(Type, "function-exit", xray::RecordTypes::EXIT); + } +}; + +template <> struct MappingTraits { + static void mapping(IO &IO, xray::YAMLXRayFileHeader &Header) { + IO.mapRequired("version", Header.Version); + IO.mapRequired("type", Header.Type); + IO.mapRequired("constant-tsc", Header.ConstantTSC); + IO.mapRequired("nonstop-tsc", Header.NonstopTSC); + IO.mapRequired("cycle-frequency", Header.CycleFrequency); + } +}; + +template <> struct MappingTraits { + static void mapping(IO &IO, xray::YAMLXRayRecord &Record) { + // FIXME: Make this type actually be descriptive + IO.mapRequired("type", Record.RecordType); + IO.mapRequired("func-id", Record.FuncId); + IO.mapOptional("function", Record.Function); + IO.mapRequired("cpu", Record.CPU); + IO.mapRequired("thread", Record.TId); + IO.mapRequired("kind", Record.Type); + IO.mapRequired("tsc", Record.TSC); + } + + static constexpr bool flow = true; +}; + +template <> struct MappingTraits { + static void mapping(IO &IO, xray::YAMLXRayTrace &Trace) { + // A trace file contains two parts, the header and the list of all the + // trace records. + IO.mapRequired("header", Trace.Header); + IO.mapRequired("records", Trace.Records); + } +}; + +} // namespace yaml +} // namespace llvm + +LLVM_YAML_IS_SEQUENCE_VECTOR(xray::YAMLXRayRecord); + +#endif // LLVM_TOOLS_LLVM_XRAY_XRAY_RECORD_YAML_H Index: tools/llvm-xray/xray-record.h =================================================================== --- /dev/null +++ tools/llvm-xray/xray-record.h @@ -0,0 +1,60 @@ +//===- xray-record.h - XRay Trace Record ----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file replicates the record definition for XRay log entries. This should +// follow the evolution of the log record versions supported in the compiler-rt +// xray project. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_TOOLS_LLVM_XRAY_XRAY_RECORD_H +#define LLVM_TOOLS_LLVM_XRAY_XRAY_RECORD_H + +#include + +namespace llvm { +namespace xray { + +struct alignas(32) XRayFileHeader { + uint16_t Version = 0; + uint16_t Type = 0; + bool ConstantTSC : 1; + bool NonstopTSC : 1; + alignas(8) uint64_t CycleFrequency = 0; +} __attribute__((packed)); + +static_assert(sizeof(XRayFileHeader) == 32, "XRayFileHeader != 32 bytes"); + +struct alignas(32) XRayRecord { + uint16_t RecordType = 0; + + // The CPU where the thread is running. We assume number of CPUs <= 256. + uint8_t CPU = 0; + + // The type of the event. Usually either ENTER = 0 or EXIT = 1. + uint8_t Type = 0; + + // The function ID for the record. + int32_t FuncId = 0; + + // Get the full 8 bytes of the TSC when we get the log record. + uint64_t TSC = 0; + + // The thread ID for the currently running thread. + uint32_t TId = 0; + + // Use some bytes in the end of the record for buffers. + char Buffer[4] = {}; +} __attribute__((packed)); + +static_assert(sizeof(XRayRecord) == 32, "XRayRecord != 32 bytes"); + +} // namespace xray +} // namespace llvm + +#endif // LLVM_TOOLS_LLVM_XRAY_XRAY_RECORD_H