Index: docs/XRayFDRFormat.rst =================================================================== --- docs/XRayFDRFormat.rst +++ docs/XRayFDRFormat.rst @@ -165,7 +165,7 @@ +---------------+--------------+-----------------------------------------------+ | Exit | ``1`` | Typical function exit. | +---------------+--------------+-----------------------------------------------+ -| Tail_Exit | ``2`` | An exit from a function due to Tail call | +| Tail_Exit | ``2`` | An exit from a function due to tail call | | | | optimization. | +---------------+--------------+-----------------------------------------------+ | Entry_Args | ``3`` | A function entry that records arguments. | Index: include/llvm/XRay/XRayRecord.h =================================================================== --- include/llvm/XRay/XRayRecord.h +++ include/llvm/XRay/XRayRecord.h @@ -53,7 +53,7 @@ /// 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 }; +enum class RecordTypes { ENTER, EXIT, TAIL_EXIT }; struct XRayRecord { /// The type of record. Index: include/llvm/XRay/YAMLXRayRecord.h =================================================================== --- include/llvm/XRay/YAMLXRayRecord.h +++ include/llvm/XRay/YAMLXRayRecord.h @@ -54,6 +54,7 @@ static void enumeration(IO &IO, xray::RecordTypes &Type) { 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); } }; Index: lib/XRay/Trace.cpp =================================================================== --- lib/XRay/Trace.cpp +++ lib/XRay/Trace.cpp @@ -48,7 +48,7 @@ FileHeader.NonstopTSC = Bitfield & 1uL << 1; FileHeader.CycleFrequency = HeaderExtractor.getU64(&OffsetPtr); std::memcpy(&FileHeader.FreeFormData, Data.bytes_begin() + OffsetPtr, 16); - if (FileHeader.Version != 1) + if (FileHeader.Version != 1 && FileHeader.Version != 2) return make_error( Twine("Unsupported XRay file version: ") + Twine(FileHeader.Version), std::make_error_code(std::errc::invalid_argument)); @@ -94,6 +94,9 @@ case 1: Record.Type = RecordTypes::EXIT; break; + case 2: + Record.Type = RecordTypes::TAIL_EXIT; + break; default: return make_error( Twine("Unknown record type '") + Twine(int{Type}) + "'", @@ -320,9 +323,11 @@ Record.Type = RecordTypes::ENTER; break; case static_cast(RecordTypes::EXIT): - case 2: // TAIL_EXIT is not yet defined in RecordTypes. Record.Type = RecordTypes::EXIT; break; + case static_cast(RecordTypes::TAIL_EXIT): + Record.Type = RecordTypes::TAIL_EXIT; + break; default: // Cast to an unsigned integer to not interpret the record type as a char. return make_error( @@ -443,7 +448,7 @@ // Having iterated over everything we've been given, we've either consumed // everything and ended up in the end state, or were told to skip the rest. bool Finished = State.Expects == FDRState::Token::SCAN_TO_END_OF_THREAD_BUF && - State.CurrentBufferSize == State.CurrentBufferConsumed; + State.CurrentBufferSize == State.CurrentBufferConsumed; if (State.Expects != FDRState::Token::NEW_BUFFER_RECORD_OR_EOF && !Finished) return make_error( Twine("Encountered EOF with unexpected state expectation ") + @@ -534,9 +539,8 @@ enum BinaryFormatType { NAIVE_FORMAT = 0, FLIGHT_DATA_RECORDER_FORMAT = 1 }; Trace T; - if (Version == 1 && Type == NAIVE_FORMAT) { - if (auto E = - loadNaiveFormatLog(Data, T.FileHeader, T.Records)) + if (Type == NAIVE_FORMAT && (Version == 1 || Version == 2)) { + if (auto E = loadNaiveFormatLog(Data, T.FileHeader, T.Records)) return std::move(E); } else if (Version == 1 && Type == FLIGHT_DATA_RECORDER_FORMAT) { if (auto E = loadFDRLog(Data, T.FileHeader, T.Records)) Index: test/tools/llvm-xray/X86/convert-fdr-to-yaml.txt =================================================================== --- test/tools/llvm-xray/X86/convert-fdr-to-yaml.txt +++ test/tools/llvm-xray/X86/convert-fdr-to-yaml.txt @@ -16,7 +16,7 @@ ; CHECK-NEXT: - { type: 0, func-id: 2, function: '2', cpu: 5, thread: 5, kind: function-exit, tsc: 7238225556407467 } ; CHECK-NEXT: - { type: 0, func-id: 4, function: '4', cpu: 5, thread: 5, kind: function-enter, tsc: 7238225556407492 } ; CHECK-NEXT: - { type: 0, func-id: 5, function: '5', cpu: 5, thread: 5, kind: function-enter, tsc: 7238225556407517 } -; CHECK-NEXT: - { type: 0, func-id: 5, function: '5', cpu: 5, thread: 5, kind: function-exit, tsc: 7238225556407542 } +; CHECK-NEXT: - { type: 0, func-id: 5, function: '5', cpu: 5, thread: 5, kind: function-tail-exit, tsc: 7238225556407542 } ; CHECK-NEXT: - { type: 0, func-id: 268435455, function: '268435455', cpu: 5, thread: 5, kind: function-enter, tsc: 7238225556407552 } ; CHECK-NEXT: - { type: 0, func-id: 268435455, function: '268435455', cpu: 5, thread: 5, kind: function-exit, tsc: 7238225556407562 } ; CHECK-NEXT: - { type: 0, func-id: 6, function: '6', cpu: 6, thread: 5, kind: function-enter, tsc: 7238225556407682 } Index: tools/llvm-xray/xray-account.cc =================================================================== --- tools/llvm-xray/xray-account.cc +++ tools/llvm-xray/xray-account.cc @@ -150,7 +150,8 @@ ThreadStack.emplace_back(Record.FuncId, Record.TSC); break; } - case RecordTypes::EXIT: { + case RecordTypes::EXIT: + case RecordTypes::TAIL_EXIT: { if (ThreadStack.empty()) return false; @@ -419,6 +420,9 @@ case RecordTypes::EXIT: Stream << "exit"; break; + case RecordTypes::TAIL_EXIT: + Stream << "tail-exit"; + break; } } }; Index: tools/llvm-xray/xray-converter.cc =================================================================== --- tools/llvm-xray/xray-converter.cc +++ tools/llvm-xray/xray-converter.cc @@ -128,6 +128,9 @@ case RecordTypes::EXIT: Writer.write(uint8_t{1}); break; + case RecordTypes::TAIL_EXIT: + Writer.write(uint8_t{2}); + break; } Writer.write(R.FuncId); Writer.write(R.TSC); Index: tools/llvm-xray/xray-graph.cc =================================================================== --- tools/llvm-xray/xray-graph.cc +++ tools/llvm-xray/xray-graph.cc @@ -214,7 +214,8 @@ ThreadStack.push_back({Record.FuncId, Record.TSC}); break; } - case RecordTypes::EXIT: { + case RecordTypes::EXIT: + case RecordTypes::TAIL_EXIT: { // FIXME: Refactor this and the account subcommand to reduce code // duplication if (ThreadStack.size() == 0 || ThreadStack.back().FuncId != Record.FuncId) { Index: tools/llvm-xray/xray-stacks.cc =================================================================== --- tools/llvm-xray/xray-stacks.cc +++ tools/llvm-xray/xray-stacks.cc @@ -352,7 +352,8 @@ } return AccountRecordStatus::OK; } - case RecordTypes::EXIT: { + case RecordTypes::EXIT: + case RecordTypes::TAIL_EXIT: { bool wasLastRecordExit = state->wasLastRecordExit; state->wasLastRecordExit = true; // The exit case is more interesting, since we want to be able to deduce