blob: 4b010f1fa624b7fbc619f29eca6feadea8c2bef3 [file] [log] [blame]
Dean Michael Berris146d57912018-08-31 08:04:56 +00001//===- FDRRecordProducer.cpp - XRay FDR Mode Record Producer --------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9#include "llvm/XRay/FDRRecordProducer.h"
10#include "llvm/Support/DataExtractor.h"
11
12namespace llvm {
13namespace xray {
14
15namespace {
16
Dean Michael Berris146d57912018-08-31 08:04:56 +000017Expected<std::unique_ptr<Record>>
18metadataRecordType(const XRayFileHeader &Header, uint8_t T) {
Dean Michael Berrisfc774e22018-08-31 11:41:08 +000019 // Keep this in sync with the values written in the XRay FDR mode runtime in
20 // compiler-rt.
21 enum MetadataRecordKinds : uint8_t {
22 NewBufferKind,
23 EndOfBufferKind,
24 NewCPUIdKind,
25 TSCWrapKind,
26 WalltimeMarkerKind,
27 CustomEventMarkerKind,
28 CallArgumentKind,
29 BufferExtentsKind,
30 TypedEventMarkerKind,
31 PidKind,
32 // This is an end marker, used to identify the upper bound for this enum.
33 EnumEndMarker,
34 };
35
Dean Michael Berris146d57912018-08-31 08:04:56 +000036 if (T >= static_cast<uint8_t>(MetadataRecordKinds::EnumEndMarker))
37 return createStringError(std::make_error_code(std::errc::invalid_argument),
38 "Invalid metadata record type: %d", T);
Dean Michael Berrisfc774e22018-08-31 11:41:08 +000039 switch (T) {
40 case MetadataRecordKinds::NewBufferKind:
Dean Michael Berris146d57912018-08-31 08:04:56 +000041 return make_unique<NewBufferRecord>();
Dean Michael Berrisfc774e22018-08-31 11:41:08 +000042 case MetadataRecordKinds::EndOfBufferKind:
Dean Michael Berris146d57912018-08-31 08:04:56 +000043 if (Header.Version >= 2)
44 return createStringError(
45 std::make_error_code(std::errc::executable_format_error),
46 "End of buffer records are no longer supported starting version "
47 "2 of the log.");
48 return make_unique<EndBufferRecord>();
Dean Michael Berrisfc774e22018-08-31 11:41:08 +000049 case MetadataRecordKinds::NewCPUIdKind:
Dean Michael Berris146d57912018-08-31 08:04:56 +000050 return make_unique<NewCPUIDRecord>();
Dean Michael Berrisfc774e22018-08-31 11:41:08 +000051 case MetadataRecordKinds::TSCWrapKind:
Dean Michael Berris146d57912018-08-31 08:04:56 +000052 return make_unique<TSCWrapRecord>();
Dean Michael Berrisfc774e22018-08-31 11:41:08 +000053 case MetadataRecordKinds::WalltimeMarkerKind:
Dean Michael Berris146d57912018-08-31 08:04:56 +000054 return make_unique<WallclockRecord>();
Dean Michael Berrisfc774e22018-08-31 11:41:08 +000055 case MetadataRecordKinds::CustomEventMarkerKind:
Dean Michael Berris146d57912018-08-31 08:04:56 +000056 return make_unique<CustomEventRecord>();
Dean Michael Berrisfc774e22018-08-31 11:41:08 +000057 case MetadataRecordKinds::CallArgumentKind:
Dean Michael Berris146d57912018-08-31 08:04:56 +000058 return make_unique<CallArgRecord>();
Dean Michael Berrisfc774e22018-08-31 11:41:08 +000059 case MetadataRecordKinds::BufferExtentsKind:
Dean Michael Berris146d57912018-08-31 08:04:56 +000060 return make_unique<BufferExtents>();
Dean Michael Berrisfc774e22018-08-31 11:41:08 +000061 case MetadataRecordKinds::TypedEventMarkerKind:
Dean Michael Berris146d57912018-08-31 08:04:56 +000062 return createStringError(std::make_error_code(std::errc::invalid_argument),
63 "Encountered an unsupported TypedEventMarker.");
Dean Michael Berrisfc774e22018-08-31 11:41:08 +000064 case MetadataRecordKinds::PidKind:
Dean Michael Berris146d57912018-08-31 08:04:56 +000065 return make_unique<PIDRecord>();
66 case MetadataRecordKinds::EnumEndMarker:
67 llvm_unreachable("Invalid MetadataRecordKind");
68 }
Simon Pilgrim95f41202018-08-31 09:24:09 +000069 llvm_unreachable("Unhandled MetadataRecordKinds enum value");
Dean Michael Berris146d57912018-08-31 08:04:56 +000070}
71
72} // namespace
73
74Expected<std::unique_ptr<Record>> FileBasedRecordProducer::produce() {
75 // At the top level, we read one byte to determine the type of the record to
76 // create. This byte will comprise of the following bits:
77 //
78 // - offset 0: A '1' indicates a metadata record, a '0' indicates a function
79 // record.
80 // - offsets 1-7: For metadata records, this will indicate the kind of
81 // metadata record should be loaded.
82 //
83 // We read first byte, then create the appropriate type of record to consume
84 // the rest of the bytes.
85 auto PreReadOffset = OffsetPtr;
86 uint8_t FirstByte = E.getU8(&OffsetPtr);
87 std::unique_ptr<Record> R;
88
89 // For metadata records, handle especially here.
90 if (FirstByte & 0x01) {
91 auto LoadedType = FirstByte >> 1;
92 auto MetadataRecordOrErr = metadataRecordType(Header, LoadedType);
93 if (!MetadataRecordOrErr)
94 return joinErrors(
95 MetadataRecordOrErr.takeError(),
96 createStringError(
97 std::make_error_code(std::errc::executable_format_error),
98 "Encountered an unsupported metadata record (%d) at offset %d.",
99 LoadedType, PreReadOffset));
100 R = std::move(MetadataRecordOrErr.get());
101 } else {
102 R = llvm::make_unique<FunctionRecord>();
103 }
104 RecordInitializer RI(E, OffsetPtr);
105
106 if (auto Err = R->apply(RI))
107 return std::move(Err);
108
109 assert(R != nullptr);
110 return std::move(R);
111}
112
113} // namespace xray
114} // namespace llvm