115 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			115 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
//===- 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 {
 | 
						|
 | 
						|
Expected<std::unique_ptr<Record>>
 | 
						|
metadataRecordType(const XRayFileHeader &Header, uint8_t T) {
 | 
						|
  // Keep this in sync with the values written in the XRay FDR mode runtime in
 | 
						|
  // compiler-rt.
 | 
						|
  enum MetadataRecordKinds : uint8_t {
 | 
						|
    NewBufferKind,
 | 
						|
    EndOfBufferKind,
 | 
						|
    NewCPUIdKind,
 | 
						|
    TSCWrapKind,
 | 
						|
    WalltimeMarkerKind,
 | 
						|
    CustomEventMarkerKind,
 | 
						|
    CallArgumentKind,
 | 
						|
    BufferExtentsKind,
 | 
						|
    TypedEventMarkerKind,
 | 
						|
    PidKind,
 | 
						|
    // This is an end marker, used to identify the upper bound for this enum.
 | 
						|
    EnumEndMarker,
 | 
						|
  };
 | 
						|
 | 
						|
  if (T >= static_cast<uint8_t>(MetadataRecordKinds::EnumEndMarker))
 | 
						|
    return createStringError(std::make_error_code(std::errc::invalid_argument),
 | 
						|
                             "Invalid metadata record type: %d", T);
 | 
						|
  switch (T) {
 | 
						|
  case MetadataRecordKinds::NewBufferKind:
 | 
						|
    return make_unique<NewBufferRecord>();
 | 
						|
  case MetadataRecordKinds::EndOfBufferKind:
 | 
						|
    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::NewCPUIdKind:
 | 
						|
    return make_unique<NewCPUIDRecord>();
 | 
						|
  case MetadataRecordKinds::TSCWrapKind:
 | 
						|
    return make_unique<TSCWrapRecord>();
 | 
						|
  case MetadataRecordKinds::WalltimeMarkerKind:
 | 
						|
    return make_unique<WallclockRecord>();
 | 
						|
  case MetadataRecordKinds::CustomEventMarkerKind:
 | 
						|
    return make_unique<CustomEventRecord>();
 | 
						|
  case MetadataRecordKinds::CallArgumentKind:
 | 
						|
    return make_unique<CallArgRecord>();
 | 
						|
  case MetadataRecordKinds::BufferExtentsKind:
 | 
						|
    return make_unique<BufferExtents>();
 | 
						|
  case MetadataRecordKinds::TypedEventMarkerKind:
 | 
						|
    return createStringError(std::make_error_code(std::errc::invalid_argument),
 | 
						|
                             "Encountered an unsupported TypedEventMarker.");
 | 
						|
  case MetadataRecordKinds::PidKind:
 | 
						|
    return make_unique<PIDRecord>();
 | 
						|
  case MetadataRecordKinds::EnumEndMarker:
 | 
						|
    llvm_unreachable("Invalid MetadataRecordKind");
 | 
						|
  }
 | 
						|
  llvm_unreachable("Unhandled MetadataRecordKinds enum value");
 | 
						|
}
 | 
						|
 | 
						|
} // 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
 |