diff options
-rw-r--r-- | llvm/include/llvm/XRay/XRayRecord.h | 5 | ||||
-rw-r--r-- | llvm/include/llvm/XRay/YAMLXRayRecord.h | 13 | ||||
-rw-r--r-- | llvm/lib/XRay/Trace.cpp | 29 | ||||
-rw-r--r-- | llvm/test/tools/llvm-xray/X86/Inputs/fdr-log-arg1.xray | bin | 0 -> 288 bytes | |||
-rw-r--r-- | llvm/test/tools/llvm-xray/X86/convert-fdr-arg1-to-yaml.txt | 13 | ||||
-rw-r--r-- | llvm/tools/llvm-xray/xray-account.cc | 3 | ||||
-rw-r--r-- | llvm/tools/llvm-xray/xray-converter.cc | 3 | ||||
-rw-r--r-- | llvm/tools/llvm-xray/xray-graph.cc | 3 |
8 files changed, 63 insertions, 6 deletions
diff --git a/llvm/include/llvm/XRay/XRayRecord.h b/llvm/include/llvm/XRay/XRayRecord.h index eb1f26eb19d..27e90ea0bb4 100644 --- a/llvm/include/llvm/XRay/XRayRecord.h +++ b/llvm/include/llvm/XRay/XRayRecord.h @@ -53,7 +53,7 @@ struct XRayFileHeader { /// This may or may not correspond to actual record types in the raw trace (as /// the loader implementation may synthesize this information in the process of /// of loading). -enum class RecordTypes { ENTER, EXIT, TAIL_EXIT }; +enum class RecordTypes { ENTER, EXIT, TAIL_EXIT, ENTER_ARG }; struct XRayRecord { /// The type of record. @@ -73,6 +73,9 @@ struct XRayRecord { /// The thread ID for the currently running thread. uint32_t TId; + + /// The function call arguments. + std::vector<uint64_t> CallArgs; }; } // namespace xray diff --git a/llvm/include/llvm/XRay/YAMLXRayRecord.h b/llvm/include/llvm/XRay/YAMLXRayRecord.h index 792323ca555..122b88497af 100644 --- a/llvm/include/llvm/XRay/YAMLXRayRecord.h +++ b/llvm/include/llvm/XRay/YAMLXRayRecord.h @@ -37,6 +37,7 @@ struct YAMLXRayRecord { std::string Function; uint64_t TSC; uint32_t TId; + std::vector<uint64_t> CallArgs; }; struct YAMLXRayTrace { @@ -55,6 +56,7 @@ template <> struct ScalarEnumerationTraits<xray::RecordTypes> { IO.enumCase(Type, "function-enter", xray::RecordTypes::ENTER); IO.enumCase(Type, "function-exit", xray::RecordTypes::EXIT); IO.enumCase(Type, "function-tail-exit", xray::RecordTypes::TAIL_EXIT); + IO.enumCase(Type, "function-enter-arg", xray::RecordTypes::ENTER_ARG); } }; @@ -74,6 +76,7 @@ template <> struct MappingTraits<xray::YAMLXRayRecord> { IO.mapRequired("type", Record.RecordType); IO.mapRequired("func-id", Record.FuncId); IO.mapOptional("function", Record.Function); + IO.mapOptional("args", Record.CallArgs); IO.mapRequired("cpu", Record.CPU); IO.mapRequired("thread", Record.TId); IO.mapRequired("kind", Record.Type); @@ -83,6 +86,16 @@ template <> struct MappingTraits<xray::YAMLXRayRecord> { static constexpr bool flow = true; }; +template <> struct SequenceTraits<std::vector<uint64_t>> { + static constexpr bool flow = true; + static size_t size(IO &IO, std::vector<uint64_t> &V) { return V.size(); } + static uint64_t &element(IO &IO, std::vector<uint64_t> &V, size_t Index) { + if (Index >= V.size()) + V.resize(Index + 1); + return V[Index]; + } +}; + template <> struct MappingTraits<xray::YAMLXRayTrace> { static void mapping(IO &IO, xray::YAMLXRayTrace &Trace) { // A trace file contains two parts, the header and the list of all the diff --git a/llvm/lib/XRay/Trace.cpp b/llvm/lib/XRay/Trace.cpp index 131c7807b1b..7f8846cbd6f 100644 --- a/llvm/lib/XRay/Trace.cpp +++ b/llvm/lib/XRay/Trace.cpp @@ -128,6 +128,7 @@ struct FDRState { FUNCTION_SEQUENCE, SCAN_TO_END_OF_THREAD_BUF, CUSTOM_EVENT_DATA, + CALL_ARGUMENT, }; Token Expects; @@ -151,6 +152,8 @@ const char *fdrStateToTwine(const FDRState::Token &state) { return "SCAN_TO_END_OF_THREAD_BUF"; case FDRState::Token::CUSTOM_EVENT_DATA: return "CUSTOM_EVENT_DATA"; + case FDRState::Token::CALL_ARGUMENT: + return "CALL_ARGUMENT"; } return "UNKNOWN"; } @@ -238,6 +241,22 @@ Error processCustomEventMarker(FDRState &State, uint8_t RecordFirstByte, return Error::success(); } +/// State transition when a CallArgumentRecord is encountered. +Error processFDRCallArgumentRecord(FDRState &State, uint8_t RecordFirstByte, + DataExtractor &RecordExtractor, + std::vector<XRayRecord> &Records) { + uint32_t OffsetPtr = 1; // Read starting after the first byte. + auto &Enter = Records.back(); + + if (Enter.Type != RecordTypes::ENTER) + return make_error<StringError>( + "CallArgument needs to be right after a function entry", + std::make_error_code(std::errc::executable_format_error)); + Enter.Type = RecordTypes::ENTER_ARG; + Enter.CallArgs.emplace_back(RecordExtractor.getU64(&OffsetPtr)); + return Error::success(); +} + /// Advances the state machine for reading the FDR record type by reading one /// Metadata Record and updating the State appropriately based on the kind of /// record encountered. The RecordKind is encoded in the first byte of the @@ -245,7 +264,8 @@ Error processCustomEventMarker(FDRState &State, uint8_t RecordFirstByte, /// to determine that this is a metadata record as opposed to a function record. Error processFDRMetadataRecord(FDRState &State, uint8_t RecordFirstByte, DataExtractor &RecordExtractor, - size_t &RecordSize) { + size_t &RecordSize, + std::vector<XRayRecord> &Records) { // The remaining 7 bits are the RecordKind enum. uint8_t RecordKind = RecordFirstByte >> 1; switch (RecordKind) { @@ -279,6 +299,11 @@ Error processFDRMetadataRecord(FDRState &State, uint8_t RecordFirstByte, RecordExtractor, RecordSize)) return E; break; + case 6: // CallArgument + if (auto E = processFDRCallArgumentRecord(State, RecordFirstByte, + RecordExtractor, Records)) + return E; + break; default: // Widen the record type to uint16_t to prevent conversion to char. return make_error<StringError>( @@ -434,7 +459,7 @@ Error loadFDRLog(StringRef Data, XRayFileHeader &FileHeader, if (isMetadataRecord) { RecordSize = 16; if (auto E = processFDRMetadataRecord(State, BitField, RecordExtractor, - RecordSize)) + RecordSize, Records)) return E; } else { // Process Function Record RecordSize = 8; diff --git a/llvm/test/tools/llvm-xray/X86/Inputs/fdr-log-arg1.xray b/llvm/test/tools/llvm-xray/X86/Inputs/fdr-log-arg1.xray Binary files differnew file mode 100644 index 00000000000..cd311cd0eb1 --- /dev/null +++ b/llvm/test/tools/llvm-xray/X86/Inputs/fdr-log-arg1.xray diff --git a/llvm/test/tools/llvm-xray/X86/convert-fdr-arg1-to-yaml.txt b/llvm/test/tools/llvm-xray/X86/convert-fdr-arg1-to-yaml.txt new file mode 100644 index 00000000000..06b5eb8904e --- /dev/null +++ b/llvm/test/tools/llvm-xray/X86/convert-fdr-arg1-to-yaml.txt @@ -0,0 +1,13 @@ +; RUN: llvm-xray convert %S/Inputs/fdr-log-arg1.xray -f=yaml -o - | FileCheck %s + +; CHECK: --- +; CHECK-NEXT: header: +; CHECK-NEXT: version: 1 +; CHECK-NEXT: type: 1 +; CHECK-NEXT: constant-tsc: true +; CHECK-NEXT: nonstop-tsc: true +; CHECK-NEXT: cycle-frequency: 3500000000 +; CHECK-NEXT: records: +; CHECK-NEXT: - { type: 0, func-id: 1, function: '1', args: [ 1 ], cpu: 49, thread: 14648, kind: function-enter-arg, tsc: 18828908666543318 } +; CHECK-NEXT: - { type: 0, func-id: 1, function: '1', cpu: 49, thread: 14648, kind: function-exit, tsc: 18828908666595604 } +; CHECK-NEXT: ... diff --git a/llvm/tools/llvm-xray/xray-account.cc b/llvm/tools/llvm-xray/xray-account.cc index 74907044848..0ba6cad5cca 100644 --- a/llvm/tools/llvm-xray/xray-account.cc +++ b/llvm/tools/llvm-xray/xray-account.cc @@ -146,7 +146,8 @@ bool LatencyAccountant::accountRecord(const XRayRecord &Record) { auto &ThreadStack = PerThreadFunctionStack[Record.TId]; switch (Record.Type) { - case RecordTypes::ENTER: { + case RecordTypes::ENTER: + case RecordTypes::ENTER_ARG: { ThreadStack.emplace_back(Record.FuncId, Record.TSC); break; } diff --git a/llvm/tools/llvm-xray/xray-converter.cc b/llvm/tools/llvm-xray/xray-converter.cc index 4769186a19e..f1aec65bc67 100644 --- a/llvm/tools/llvm-xray/xray-converter.cc +++ b/llvm/tools/llvm-xray/xray-converter.cc @@ -86,7 +86,7 @@ void TraceConverter::exportAsYAML(const Trace &Records, raw_ostream &OS) { Trace.Records.push_back({R.RecordType, R.CPU, R.Type, R.FuncId, Symbolize ? FuncIdHelper.SymbolOrNumber(R.FuncId) : llvm::to_string(R.FuncId), - R.TSC, R.TId}); + R.TSC, R.TId, R.CallArgs}); } Output Out(OS, nullptr, 0); Out << Trace; @@ -123,6 +123,7 @@ void TraceConverter::exportAsRAWv1(const Trace &Records, raw_ostream &OS) { Writer.write(static_cast<uint8_t>(R.CPU)); switch (R.Type) { case RecordTypes::ENTER: + case RecordTypes::ENTER_ARG: Writer.write(uint8_t{0}); break; case RecordTypes::EXIT: diff --git a/llvm/tools/llvm-xray/xray-graph.cc b/llvm/tools/llvm-xray/xray-graph.cc index da2d04cf0b9..9a2f837e6a3 100644 --- a/llvm/tools/llvm-xray/xray-graph.cc +++ b/llvm/tools/llvm-xray/xray-graph.cc @@ -208,7 +208,8 @@ Error GraphRenderer::accountRecord(const XRayRecord &Record) { auto &ThreadStack = PerThreadFunctionStack[Record.TId]; switch (Record.Type) { - case RecordTypes::ENTER: { + case RecordTypes::ENTER: + case RecordTypes::ENTER_ARG: { if (Record.FuncId != 0 && G.count(Record.FuncId) == 0) G[Record.FuncId].SymbolName = FuncIdHelper.SymbolOrNumber(Record.FuncId); ThreadStack.push_back({Record.FuncId, Record.TSC}); |