diff options
| author | Dean Michael Berris <dberris@google.com> | 2018-08-31 08:04:56 +0000 |
|---|---|---|
| committer | Dean Michael Berris <dberris@google.com> | 2018-08-31 08:04:56 +0000 |
| commit | 146d5791d9b8b20eaca0ca3434f81359046edfbe (patch) | |
| tree | 22faadb9b0f041131b54591dc8b71f8f6083c067 /llvm/lib/XRay | |
| parent | 24f590fca688c6abf333faa1da659826da0e3f95 (diff) | |
| download | bcm5719-llvm-146d5791d9b8b20eaca0ca3434f81359046edfbe.tar.gz bcm5719-llvm-146d5791d9b8b20eaca0ca3434f81359046edfbe.zip | |
[XRay] FDR Record Producer/Consumer Implementation
Summary:
This patch defines two new base types called `RecordProducer` and
`RecordConsumer` which have default implementations for convenience
(particularly for testing).
A `RecordProducer` implementation has one member function called
`produce()` which serves as a factory constructor for `Record`
instances. This code exercises the `RecordInitializer` code path in the
implementation for `FileBasedRecordProducer`.
A `RecordConsumer` has a single member function called `consume(...)`
which, as the name implies, consumes instances of
`std::unique_ptr<Record>`. We have two implementations, one of which is
used in the test to generate a vector of `std::unique_ptr<Record>`
similar to how the `LogBuilder` implementation works.
We introduce a test in `FDRProducerConsumerTest` which ensures that
records we write through the `FDRTraceWriter` can be loaded by the
`FileBasedRecordProducer`. The record(s) loaded this way are written
again through the `FDRTraceWriter` into a separate string, which we then
compare. This ensures that the read-in bytes to create the `Record`
instances in memory can be replicated when written out through the
`FDRTraceWriter`.
This change depends on D51210 and is part of the refactoring of D50441
into smaller, more focused changes.
Reviewers: eizan, kpw
Subscribers: mgorny, hiraditya, llvm-commits
Differential Revision: https://reviews.llvm.org/D51289
llvm-svn: 341180
Diffstat (limited to 'llvm/lib/XRay')
| -rw-r--r-- | llvm/lib/XRay/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | llvm/lib/XRay/FDRRecordProducer.cpp | 125 | ||||
| -rw-r--r-- | llvm/lib/XRay/LogBuilderConsumer.cpp | 38 |
3 files changed, 165 insertions, 0 deletions
diff --git a/llvm/lib/XRay/CMakeLists.txt b/llvm/lib/XRay/CMakeLists.txt index 5a09a24eb6d..a726db29a57 100644 --- a/llvm/lib/XRay/CMakeLists.txt +++ b/llvm/lib/XRay/CMakeLists.txt @@ -1,8 +1,10 @@ add_llvm_library(LLVMXRay + FDRRecordProducer.cpp FDRRecords.cpp FDRTraceWriter.cpp FileHeaderReader.cpp InstrumentationMap.cpp + LogBuilderConsumer.cpp Profile.cpp RecordInitializer.cpp Trace.cpp diff --git a/llvm/lib/XRay/FDRRecordProducer.cpp b/llvm/lib/XRay/FDRRecordProducer.cpp new file mode 100644 index 00000000000..84d75cc9a29 --- /dev/null +++ b/llvm/lib/XRay/FDRRecordProducer.cpp @@ -0,0 +1,125 @@ +//===- FDRRecordProducer.cpp - XRay FDR Mode Record Producer --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "llvm/XRay/FDRRecordProducer.h" +#include "llvm/Support/DataExtractor.h" + +namespace llvm { +namespace xray { + +namespace { + +// Keep this in sync with the values written in the XRay FDR mode runtime in +// compiler-rt. +enum class MetadataRecordKinds : uint8_t { + NewBuffer, + EndOfBuffer, + NewCPUId, + TSCWrap, + WalltimeMarker, + CustomEventMarker, + CallArgument, + BufferExtents, + TypedEventMarker, + Pid, + // This is an end marker, used to identify the upper bound for this enum. + EnumEndMarker, +}; + +Expected<std::unique_ptr<Record>> +metadataRecordType(const XRayFileHeader &Header, uint8_t T) { + if (T >= static_cast<uint8_t>(MetadataRecordKinds::EnumEndMarker)) + return createStringError(std::make_error_code(std::errc::invalid_argument), + "Invalid metadata record type: %d", T); + static constexpr MetadataRecordKinds Mapping[] = { + MetadataRecordKinds::NewBuffer, + MetadataRecordKinds::EndOfBuffer, + MetadataRecordKinds::NewCPUId, + MetadataRecordKinds::TSCWrap, + MetadataRecordKinds::WalltimeMarker, + MetadataRecordKinds::CustomEventMarker, + MetadataRecordKinds::CallArgument, + MetadataRecordKinds::BufferExtents, + MetadataRecordKinds::TypedEventMarker, + MetadataRecordKinds::Pid, + }; + switch (Mapping[T]) { + case MetadataRecordKinds::NewBuffer: + return make_unique<NewBufferRecord>(); + case MetadataRecordKinds::EndOfBuffer: + if (Header.Version >= 2) + return createStringError( + std::make_error_code(std::errc::executable_format_error), + "End of buffer records are no longer supported starting version " + "2 of the log."); + return make_unique<EndBufferRecord>(); + case MetadataRecordKinds::NewCPUId: + return make_unique<NewCPUIDRecord>(); + case MetadataRecordKinds::TSCWrap: + return make_unique<TSCWrapRecord>(); + case MetadataRecordKinds::WalltimeMarker: + return make_unique<WallclockRecord>(); + case MetadataRecordKinds::CustomEventMarker: + return make_unique<CustomEventRecord>(); + case MetadataRecordKinds::CallArgument: + return make_unique<CallArgRecord>(); + case MetadataRecordKinds::BufferExtents: + return make_unique<BufferExtents>(); + case MetadataRecordKinds::TypedEventMarker: + return createStringError(std::make_error_code(std::errc::invalid_argument), + "Encountered an unsupported TypedEventMarker."); + case MetadataRecordKinds::Pid: + return make_unique<PIDRecord>(); + case MetadataRecordKinds::EnumEndMarker: + llvm_unreachable("Invalid MetadataRecordKind"); + } +} + +} // namespace + +Expected<std::unique_ptr<Record>> FileBasedRecordProducer::produce() { + // At the top level, we read one byte to determine the type of the record to + // create. This byte will comprise of the following bits: + // + // - offset 0: A '1' indicates a metadata record, a '0' indicates a function + // record. + // - offsets 1-7: For metadata records, this will indicate the kind of + // metadata record should be loaded. + // + // We read first byte, then create the appropriate type of record to consume + // the rest of the bytes. + auto PreReadOffset = OffsetPtr; + uint8_t FirstByte = E.getU8(&OffsetPtr); + std::unique_ptr<Record> R; + + // For metadata records, handle especially here. + if (FirstByte & 0x01) { + auto LoadedType = FirstByte >> 1; + auto MetadataRecordOrErr = metadataRecordType(Header, LoadedType); + if (!MetadataRecordOrErr) + return joinErrors( + MetadataRecordOrErr.takeError(), + createStringError( + std::make_error_code(std::errc::executable_format_error), + "Encountered an unsupported metadata record (%d) at offset %d.", + LoadedType, PreReadOffset)); + R = std::move(MetadataRecordOrErr.get()); + } else { + R = llvm::make_unique<FunctionRecord>(); + } + RecordInitializer RI(E, OffsetPtr); + + if (auto Err = R->apply(RI)) + return std::move(Err); + + assert(R != nullptr); + return std::move(R); +} + +} // namespace xray +} // namespace llvm diff --git a/llvm/lib/XRay/LogBuilderConsumer.cpp b/llvm/lib/XRay/LogBuilderConsumer.cpp new file mode 100644 index 00000000000..88b7d2d728b --- /dev/null +++ b/llvm/lib/XRay/LogBuilderConsumer.cpp @@ -0,0 +1,38 @@ +//===- FDRRecordConsumer.h - XRay Flight Data Recorder Mode Records -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "llvm/XRay/FDRRecordConsumer.h" + +namespace llvm { +namespace xray { + +Error LogBuilderConsumer::consume(std::unique_ptr<Record> R) { + if (!R) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Must not call RecordConsumer::consume() with a null pointer."); + Records.push_back(std::move(R)); + return Error::success(); +} + +Error PipelineConsumer::consume(std::unique_ptr<Record> R) { + if (!R) + return createStringError( + std::make_error_code(std::errc::invalid_argument), + "Must not call RecordConsumer::consume() with a null pointer."); + + // We apply all of the visitors in order, and concatenate errors + // appropriately. + Error Result = Error::success(); + for (auto *V : Visitors) + Result = joinErrors(std::move(Result), R->apply(*V)); + return Result; +} + +} // namespace xray +} // namespace llvm |

