Index: compiler-rt/lib/xray/xray_fdr_controller.h =================================================================== --- compiler-rt/lib/xray/xray_fdr_controller.h +++ compiler-rt/lib/xray/xray_fdr_controller.h @@ -327,7 +327,7 @@ LatestTSC = 0; UndoableFunctionEnters = 0; UndoableTailExits = 0; - return W.writeCustomEvent(TSC, Event, EventSize); + return W.writeCustomEvent(TSC, CPU, Event, EventSize); } bool typedEvent(uint64_t TSC, uint16_t CPU, uint16_t EventType, Index: compiler-rt/lib/xray/xray_fdr_log_writer.h =================================================================== --- compiler-rt/lib/xray/xray_fdr_log_writer.h +++ compiler-rt/lib/xray/xray_fdr_log_writer.h @@ -110,9 +110,10 @@ return true; } - bool writeCustomEvent(uint64_t TSC, const void *Event, int32_t EventSize) { + bool writeCustomEvent(uint64_t TSC, uint16_t CPU, const void *Event, + int32_t EventSize) { writeMetadata(EventSize, - TSC); + TSC, CPU); internal_memcpy(NextRecord, Event, EventSize); NextRecord += EventSize; atomic_fetch_add(&Buffer.Extents, EventSize, memory_order_acq_rel); Index: compiler-rt/lib/xray/xray_fdr_logging.cc =================================================================== --- compiler-rt/lib/xray/xray_fdr_logging.cc +++ compiler-rt/lib/xray/xray_fdr_logging.cc @@ -148,7 +148,8 @@ // Version 2 of the log writes the extents of the buffer, instead of // relying on an end-of-buffer record. // Version 3 includes PID metadata record - H.Version = 3; + // Version 4 includes CPU data in the custom event records + H.Version = 4; H.Type = FileTypes::FDR_LOG; // Test for required CPU features and cache the cycle frequency Index: llvm/include/llvm/XRay/FDRRecords.h =================================================================== --- llvm/include/llvm/XRay/FDRRecords.h +++ llvm/include/llvm/XRay/FDRRecords.h @@ -153,13 +153,14 @@ class CustomEventRecord : public MetadataRecord { int32_t Size = 0; uint64_t TSC = 0; + uint16_t CPU = 0; std::string Data{}; friend class RecordInitializer; public: CustomEventRecord() = default; - explicit CustomEventRecord(uint64_t S, uint64_t T, std::string D) - : MetadataRecord(), Size(S), TSC(T), Data(std::move(D)) {} + explicit CustomEventRecord(uint64_t S, uint64_t T, uint16_t C, std::string D) + : MetadataRecord(), Size(S), TSC(T), CPU(C), Data(std::move(D)) {} MetadataType metadataType() const override { return MetadataType::CustomEvent; @@ -167,6 +168,7 @@ int32_t size() const { return Size; } uint64_t tsc() const { return TSC; } + uint16_t cpu() const { return CPU; } StringRef data() const { return Data; } Error apply(RecordVisitor &V) override; @@ -272,10 +274,16 @@ class RecordInitializer : public RecordVisitor { DataExtractor &E; uint32_t &OffsetPtr; + uint16_t Version; public: + static constexpr uint16_t DefaultVersion = 4u; + + explicit RecordInitializer(DataExtractor &DE, uint32_t &OP, uint16_t V) + : RecordVisitor(), E(DE), OffsetPtr(OP), Version(V) {} + explicit RecordInitializer(DataExtractor &DE, uint32_t &OP) - : RecordVisitor(), E(DE), OffsetPtr(OP) {} + : RecordInitializer(DE, OP, DefaultVersion) {} Error visit(BufferExtents &) override; Error visit(WallclockRecord &) override; Index: llvm/lib/XRay/FDRTraceWriter.cpp =================================================================== --- llvm/lib/XRay/FDRTraceWriter.cpp +++ llvm/lib/XRay/FDRTraceWriter.cpp @@ -94,9 +94,10 @@ } Error FDRTraceWriter::visit(CustomEventRecord &R) { - if (auto E = writeMetadata<5u>(OS, R.size(), R.tsc())) + if (auto E = writeMetadata<5u>(OS, R.size(), R.tsc(), R.cpu())) return E; - ArrayRef Bytes(R.data().data(), R.data().size()); + auto D = R.data(); + ArrayRef Bytes(D.data(), D.size()); OS.write(Bytes); return Error::success(); } @@ -127,7 +128,7 @@ OS.write(TypeRecordFuncId); OS.write(R.delta()); return Error::success(); -} // namespace xray +} } // namespace xray } // namespace llvm Index: llvm/lib/XRay/FileHeaderReader.cpp =================================================================== --- llvm/lib/XRay/FileHeaderReader.cpp +++ llvm/lib/XRay/FileHeaderReader.cpp @@ -63,8 +63,7 @@ // Manually advance the offset pointer 16 bytes, after getting a raw memcpy // from the underlying data. OffsetPtr += 16; - if (FileHeader.Version != 1 && FileHeader.Version != 2 && - FileHeader.Version != 3) + if (FileHeader.Version < 1 || FileHeader.Version > 4) return createStringError(std::make_error_code(std::errc::invalid_argument), "Unsupported XRay file version: %d at offset %d", FileHeader.Version, OffsetPtr); Index: llvm/lib/XRay/RecordInitializer.cpp =================================================================== --- llvm/lib/XRay/RecordInitializer.cpp +++ llvm/lib/XRay/RecordInitializer.cpp @@ -118,6 +118,19 @@ std::make_error_code(std::errc::invalid_argument), "Cannot read a custom event TSC field at offset %d.", OffsetPtr); + // For version 4 onwards, of the FDR log, we want to also capture the CPU ID + // of the custom event. + if (Version >= 4) { + PreReadOffset = OffsetPtr; + R.CPU = E.getU16(&OffsetPtr); + if (PreReadOffset == OffsetPtr) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Missing CPU field at offset %d", OffsetPtr); + } + + assert(OffsetPtr > BeginOffset && + OffsetPtr - BeginOffset <= MetadataRecord::kMetadataBodySize); OffsetPtr += MetadataRecord::kMetadataBodySize - (OffsetPtr - BeginOffset); // Next we read in a fixed chunk of data from the given offset. Index: llvm/lib/XRay/RecordPrinter.cpp =================================================================== --- llvm/lib/XRay/RecordPrinter.cpp +++ llvm/lib/XRay/RecordPrinter.cpp @@ -35,8 +35,9 @@ } Error RecordPrinter::visit(CustomEventRecord &R) { - OS << formatv("", R.tsc(), - R.size(), R.data()) + OS << formatv( + "", + R.tsc(), R.cpu(), R.size(), R.data()) << Delim; return Error::success(); } Index: llvm/lib/XRay/Trace.cpp =================================================================== --- llvm/lib/XRay/Trace.cpp +++ llvm/lib/XRay/Trace.cpp @@ -310,12 +310,11 @@ { for (auto &PTB : Index) { auto &Blocks = PTB.second; - llvm::sort( - Blocks, - [](const BlockIndexer::Block &L, const BlockIndexer::Block &R) { - return (L.WallclockTime->seconds() < R.WallclockTime->seconds() && - L.WallclockTime->nanos() < R.WallclockTime->nanos()); - }); + llvm::sort(Blocks, [](const BlockIndexer::Block &L, + const BlockIndexer::Block &R) { + return (L.WallclockTime->seconds() < R.WallclockTime->seconds() && + L.WallclockTime->nanos() < R.WallclockTime->nanos()); + }); auto Adder = [&](const XRayRecord &R) { Records.push_back(R); }; TraceExpander Expander(Adder, FileHeader.Version); for (auto &B : Blocks) { @@ -435,7 +434,7 @@ } break; case FLIGHT_DATA_RECORDER_FORMAT: - if (Version == 1 || Version == 2 || Version == 3) { + if (Version >= 1 && Version <= 4) { if (auto E = loadFDRLog(DE.getData(), DE.isLittleEndian(), T.FileHeader, T.Records)) return std::move(E); Index: llvm/unittests/XRay/FDRProducerConsumerTest.cpp =================================================================== --- llvm/unittests/XRay/FDRProducerConsumerTest.cpp +++ llvm/unittests/XRay/FDRProducerConsumerTest.cpp @@ -54,7 +54,7 @@ } template <> std::unique_ptr MakeRecord() { - return make_unique(4, 1, "data"); + return make_unique(4, 1, 2, "data"); } template <> std::unique_ptr MakeRecord() { Index: llvm/unittests/XRay/FDRRecordPrinterTest.cpp =================================================================== --- llvm/unittests/XRay/FDRRecordPrinterTest.cpp +++ llvm/unittests/XRay/FDRRecordPrinterTest.cpp @@ -55,11 +55,11 @@ template <> struct Helper { static std::unique_ptr construct() { - return make_unique(4, 1, "data"); + return make_unique(4, 1, 2, "data"); } static const char *expected() { - return ""; + return ""; } };