llvm.org GIT mirror llvm / dd24af1
[XRay] Add the `llvm-xray fdr-dump` implementation Summary: In this change, we implement a `BlockPrinter` which orders records in a Block that's been indexed by the `BlockIndexer`. This is used in the `llvm-xray fdr-dump` tool which ties together the various types and utilities we've been working on, to allow for inspection of XRay FDR mode traces both with and without verification. This change is the final step of the refactoring of D50441. Reviewers: mboerger, eizan Subscribers: mgorny, hiraditya, llvm-commits Differential Revision: https://reviews.llvm.org/D51846 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@341887 91177308-0d34-0410-b5e6-96231b3b80d8 Dean Michael Berris 1 year, 8 months ago
9 changed file(s) with 476 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
0 //===- BlockPrinter.h - FDR Block Pretty Printer -------------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // An implementation of the RecordVisitor which formats a block of records for
10 // easier human consumption.
11 //
12 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_INCLUDE_LLVM_XRAY_BLOCKPRINTER_H_
14 #define LLVM_INCLUDE_LLVM_XRAY_BLOCKPRINTER_H_
15
16 #include "llvm/Support/raw_ostream.h"
17 #include "llvm/XRay/FDRRecords.h"
18 #include "llvm/XRay/RecordPrinter.h"
19
20 namespace llvm {
21 namespace xray {
22
23 class BlockPrinter : public RecordVisitor {
24 enum class State {
25 Start,
26 Preamble,
27 Metadata,
28 Function,
29 Arg,
30 CustomEvent,
31 End,
32 };
33
34 raw_ostream &OS;
35 RecordPrinter &RP;
36 State CurrentState = State::Start;
37
38 public:
39 explicit BlockPrinter(raw_ostream &O, RecordPrinter &P)
40 : RecordVisitor(), OS(O), RP(P) {}
41
42 Error visit(BufferExtents &) override;
43 Error visit(WallclockRecord &) override;
44 Error visit(NewCPUIDRecord &) override;
45 Error visit(TSCWrapRecord &) override;
46 Error visit(CustomEventRecord &) override;
47 Error visit(CallArgRecord &) override;
48 Error visit(PIDRecord &) override;
49 Error visit(NewBufferRecord &) override;
50 Error visit(EndBufferRecord &) override;
51 Error visit(FunctionRecord &) override;
52
53 void reset() { CurrentState = State::Start; }
54 };
55
56 } // namespace xray
57 } // namespace llvm
58
59 #endif // LLVM_INCLUDE_LLVM_XRAY_BLOCKPRINTER_H_
0 //===- BlockPrinter.cpp - FDR Block Pretty Printer Implementation --------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 #include "llvm/XRay/BlockPrinter.h"
9
10 namespace llvm {
11 namespace xray {
12
13 Error BlockPrinter::visit(BufferExtents &R) {
14 OS << "\n[New Block]\n";
15 CurrentState = State::Preamble;
16 return RP.visit(R);
17 }
18
19 // Preamble printing.
20 Error BlockPrinter::visit(NewBufferRecord &R) {
21 if (CurrentState == State::Start)
22 OS << "\n[New Block]\n";
23
24 OS << "Preamble: \n";
25 CurrentState = State::Preamble;
26 return RP.visit(R);
27 }
28
29 Error BlockPrinter::visit(WallclockRecord &R) {
30 CurrentState = State::Preamble;
31 return RP.visit(R);
32 }
33
34 Error BlockPrinter::visit(PIDRecord &R) {
35 CurrentState = State::Preamble;
36 return RP.visit(R);
37 }
38
39 // Metadata printing.
40 Error BlockPrinter::visit(NewCPUIDRecord &R) {
41 if (CurrentState == State::Preamble)
42 OS << "\nBody:\n";
43 if (CurrentState == State::Function)
44 OS << "\nMetadata: ";
45 CurrentState = State::Metadata;
46 OS << " ";
47 auto E = RP.visit(R);
48 return E;
49 }
50
51 Error BlockPrinter::visit(TSCWrapRecord &R) {
52 if (CurrentState == State::Function)
53 OS << "\nMetadata:";
54 CurrentState = State::Metadata;
55 OS << " ";
56 auto E = RP.visit(R);
57 return E;
58 }
59
60 // Custom events will be rendered like "function" events.
61 Error BlockPrinter::visit(CustomEventRecord &R) {
62 if (CurrentState == State::Metadata)
63 OS << "\n";
64 CurrentState = State::CustomEvent;
65 OS << "* ";
66 auto E = RP.visit(R);
67 return E;
68 }
69
70 // Function call printing.
71 Error BlockPrinter::visit(FunctionRecord &R) {
72 if (CurrentState == State::Metadata)
73 OS << "\n";
74 CurrentState = State::Function;
75 OS << "- ";
76 auto E = RP.visit(R);
77 return E;
78 }
79
80 Error BlockPrinter::visit(CallArgRecord &R) {
81 CurrentState = State::Arg;
82 OS << " : ";
83 auto E = RP.visit(R);
84 return E;
85 }
86
87 Error BlockPrinter::visit(EndBufferRecord &R) {
88 CurrentState = State::End;
89 OS << " *** ";
90 auto E = RP.visit(R);
91 return E;
92 }
93
94 } // namespace xray
95 } // namespace llvm
0 add_llvm_library(LLVMXRay
11 BlockIndexer.cpp
2 BlockPrinter.cpp
23 BlockVerifier.cpp
34 FDRRecordProducer.cpp
45 FDRRecords.cpp
0 ; RUN: llvm-xray fdr-dump -verify %S/Inputs/fdr-log-arg1-version-3.xray \
1 ; RUN: | FileCheck %s
2
3 ; CHECK: [New Block]
4 ; CHECK-NEXT: Preamble:
5 ; CHECK-NEXT:
6 ; CHECK-NEXT:
7 ; CHECK-NEXT:
8 ; CHECK-EMPTY:
9 ; CHECK-NEXT: Body:
10 ; CHECK-NEXT:
11 ; CHECK-NEXT:
12 ; CHECK-NEXT:
13 ; CHECK-EMPTY:
14 ; CHECK-NEXT: -
15 ; CHECK-NEXT: -
16 ; CHECK-NEXT: -
17 ; CHECK-NEXT: -
18 ; CHECK-EMPTY:
19 ; CHECK-NEXT: Metadata:
20 ; CHECK-EMPTY:
21 ; CHECK-NEXT: -
22 ; CHECK-NEXT: :
23 ; CHECK-NEXT: -
24
0 ; RUN: llvm-xray fdr-dump -verify %S/Inputs/fdr-log-arg1.xray | FileCheck %s
1
2 ; CHECK: [New Block]
3 ; CHECK-NEXT: Preamble:
4 ; CHECK-NEXT:
5 ; CHECK-NEXT:
6 ; CHECK-EMPTY:
7 ; CHECK-NEXT: Body:
8 ; CHECK-NEXT:
9 ; CHECK-NEXT:
10 ; CHECK-EMPTY:
11 ; CHECK-NEXT: -
12 ; CHECK-NEXT: :
13 ; CHECK-NEXT: -
14 ; CHECK-NEXT: ***
15
1313 xray-color-helper.cpp
1414 xray-converter.cpp
1515 xray-extract.cpp
16 xray-fdr-dump.cpp
1617 xray-graph-diff.cpp
1718 xray-graph.cpp
1819 xray-registry.cpp
0 //===- xray-fdr-dump.cpp: XRay FDR Trace Dump Tool ------------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Implements the FDR trace dumping tool, using the libraries for handling FDR
10 // mode traces specifically.
11 //
12 //===----------------------------------------------------------------------===//
13 #include "xray-registry.h"
14 #include "llvm/Support/CommandLine.h"
15 #include "llvm/Support/FileSystem.h"
16 #include "llvm/XRay/BlockIndexer.h"
17 #include "llvm/XRay/BlockPrinter.h"
18 #include "llvm/XRay/BlockVerifier.h"
19 #include "llvm/XRay/FDRRecordConsumer.h"
20 #include "llvm/XRay/FDRRecordProducer.h"
21 #include "llvm/XRay/FDRRecords.h"
22 #include "llvm/XRay/FileHeaderReader.h"
23 #include "llvm/XRay/RecordPrinter.h"
24
25 using namespace llvm;
26 using namespace xray;
27
28 static cl::SubCommand Dump("fdr-dump", "FDR Trace Dump");
29 static cl::opt DumpInput(cl::Positional,
30 cl::desc(""),
31 cl::Required, cl::sub(Dump));
32 static cl::opt DumpVerify("verify",
33 cl::desc("verify structure of the log"),
34 cl::init(false), cl::sub(Dump));
35
36 static CommandRegistration Unused(&Dump, []() -> Error {
37 // Open the file provided.
38 int Fd;
39 if (auto EC = sys::fs::openFileForRead(DumpInput, Fd))
40 return createStringError(EC, "Cannot open file '%s' for read.",
41 DumpInput.c_str());
42
43 uint64_t FileSize;
44 if (auto EC = sys::fs::file_size(DumpInput, FileSize))
45 return createStringError(EC, "Failed to get file size for '%s'.",
46 DumpInput.c_str());
47
48 std::error_code EC;
49 sys::fs::mapped_file_region MappedFile(
50 Fd, sys::fs::mapped_file_region::mapmode::readonly, FileSize, 0, EC);
51
52 DataExtractor DE(StringRef(MappedFile.data(), MappedFile.size()), true, 8);
53 uint32_t OffsetPtr = 0;
54
55 auto FileHeaderOrError = readBinaryFormatHeader(DE, OffsetPtr);
56 if (!FileHeaderOrError)
57 return FileHeaderOrError.takeError();
58 auto &H = FileHeaderOrError.get();
59
60 FileBasedRecordProducer P(H, DE, OffsetPtr);
61
62 RecordPrinter RP(outs(), "\n");
63 if (!DumpVerify) {
64 PipelineConsumer C({&RP});
65 while (DE.isValidOffsetForDataOfSize(OffsetPtr, 1)) {
66 auto R = P.produce();
67 if (!R)
68 return R.takeError();
69 if (auto E = C.consume(std::move(R.get())))
70 return E;
71 }
72 return Error::success();
73 }
74
75 BlockPrinter BP(outs(), RP);
76 std::vector> Records;
77 LogBuilderConsumer C(Records);
78 while (DE.isValidOffsetForDataOfSize(OffsetPtr, 1)) {
79 auto R = P.produce();
80 if (!R) {
81 // Print records we've found so far.
82 for (auto &Ptr : Records)
83 if (auto E = Ptr->apply(RP))
84 return joinErrors(std::move(E), R.takeError());
85 return R.takeError();
86 }
87 if (auto E = C.consume(std::move(R.get())))
88 return E;
89 }
90
91 // Once we have a trace, we then index the blocks.
92 BlockIndexer::Index Index;
93 BlockIndexer BI(Index);
94 for (auto &Ptr : Records)
95 if (auto E = Ptr->apply(BI))
96 return E;
97
98 if (auto E = BI.flush())
99 return E;
100
101 // Then we validate while printing each block.
102 BlockVerifier BV;
103 for (auto ProcessThreadBlocks : Index) {
104 auto &Blocks = ProcessThreadBlocks.second;
105 for (auto &B : Blocks) {
106 for (auto *R : B.Records) {
107 if (auto E = R->apply(BV))
108 return E;
109 if (auto E = R->apply(BP))
110 return E;
111 }
112 BV.reset();
113 BP.reset();
114 }
115 }
116 outs().flush();
117 return Error::success();
118 });
44 )
55
66 add_llvm_unittest(XRayTests
7 ProfileTest.cpp
87 FDRBlockIndexerTest.cpp
98 FDRBlockVerifierTest.cpp
109 FDRProducerConsumerTest.cpp
1110 FDRRecordPrinterTest.cpp
11 FDRRecordsTest.cpp
1212 FDRTraceWriterTest.cpp
1313 GraphTest.cpp
14 ProfileTest.cpp
1415 )
1516
1617 add_dependencies(XRayTests intrinsics_gen)
0 //===- FDRRecords.cpp - Unit Tests for XRay FDR Record Loading ------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 #include "gmock/gmock.h"
9 #include "gtest/gtest.h"
10
11 #include "llvm/XRay/BlockIndexer.h"
12 #include "llvm/XRay/BlockPrinter.h"
13 #include "llvm/XRay/BlockVerifier.h"
14 #include "llvm/XRay/FDRLogBuilder.h"
15 #include "llvm/XRay/FDRRecords.h"
16 #include "llvm/XRay/RecordPrinter.h"
17
18 namespace llvm {
19 namespace xray {
20 namespace {
21
22 using ::testing::Eq;
23 using ::testing::Not;
24
25 TEST(XRayFDRTest, BuilderAndBlockIndexer) {
26 // We recreate a single block of valid records, then ensure that we find all
27 // of them belonging in the same index. We do this for three blocks, and
28 // ensure we find the same records in the blocks we deduce.
29 auto Block0 = LogBuilder()
30 .add(100)
31 .add(1)
32 .add(1, 1)
33 .add(1)
34 .add(RecordTypes::ENTER, 1, 1)
35 .add(RecordTypes::EXIT, 1, 100)
36 .consume();
37 auto Block1 = LogBuilder()
38 .add(100)
39 .add(1)
40 .add(1, 2)
41 .add(1)
42 .add(RecordTypes::ENTER, 1, 1)
43 .add(RecordTypes::EXIT, 1, 100)
44 .consume();
45 auto Block2 = LogBuilder()
46 .add(100)
47 .add(2)
48 .add(1, 3)
49 .add(1)
50 .add(RecordTypes::ENTER, 1, 1)
51 .add(RecordTypes::EXIT, 1, 100)
52 .consume();
53 BlockIndexer::Index Index;
54 BlockIndexer Indexer(Index);
55 for (auto B : {std::ref(Block0), std::ref(Block1), std::ref(Block2)}) {
56 for (auto &R : B.get())
57 ASSERT_FALSE(errorToBool(R->apply(Indexer)));
58 ASSERT_FALSE(errorToBool(Indexer.flush()));
59 }
60
61 // We have two threads worth of blocks.
62 ASSERT_THAT(Index.size(), Eq(2u));
63 auto T1Blocks = Index.find({1, 1});
64 ASSERT_THAT(T1Blocks, Not(Eq(Index.end())));
65 ASSERT_THAT(T1Blocks->second.size(), Eq(2u));
66 auto T2Blocks = Index.find({1, 2});
67 ASSERT_THAT(T2Blocks, Not(Eq(Index.end())));
68 ASSERT_THAT(T2Blocks->second.size(), Eq(1u));
69 }
70
71 TEST(XRayFDRTest, BuilderAndBlockVerifier) {
72 auto Block = LogBuilder()
73 .add(48)
74 .add(1)
75 .add(1, 1)
76 .add(1)
77 .add(1)
78 .consume();
79 BlockVerifier Verifier;
80 for (auto &R : Block)
81 ASSERT_FALSE(errorToBool(R->apply(Verifier)));
82 ASSERT_FALSE(errorToBool(Verifier.verify()));
83 }
84
85 TEST(XRayFDRTest, IndexAndVerifyBlocks) {
86 auto Block0 = LogBuilder()
87 .add(64)
88 .add(1)
89 .add(1, 1)
90 .add(1)
91 .add(1)
92 .add(RecordTypes::ENTER, 1, 1)
93 .add(RecordTypes::EXIT, 1, 100)
94 .consume();
95 auto Block1 = LogBuilder()
96 .add(64)
97 .add(1)
98 .add(1, 1)
99 .add(1)
100 .add(1)
101 .add(RecordTypes::ENTER, 1, 1)
102 .add(RecordTypes::EXIT, 1, 100)
103 .consume();
104 auto Block2 = LogBuilder()
105 .add(64)
106 .add(1)
107 .add(1, 1)
108 .add(1)
109 .add(1)
110 .add(RecordTypes::ENTER, 1, 1)
111 .add(RecordTypes::EXIT, 1, 100)
112 .consume();
113
114 // First, index the records in different blocks.
115 BlockIndexer::Index Index;
116 BlockIndexer Indexer(Index);
117 for (auto B : {std::ref(Block0), std::ref(Block1), std::ref(Block2)}) {
118 for (auto &R : B.get())
119 ASSERT_FALSE(errorToBool(R->apply(Indexer)));
120 ASSERT_FALSE(errorToBool(Indexer.flush()));
121 }
122
123 // Next, verify that each block is consistently defined.
124 BlockVerifier Verifier;
125 for (auto &ProcessThreadBlocks : Index) {
126 auto &Blocks = ProcessThreadBlocks.second;
127 for (auto &B : Blocks) {
128 for (auto *R : B.Records)
129 ASSERT_FALSE(errorToBool(R->apply(Verifier)));
130 ASSERT_FALSE(errorToBool(Verifier.verify()));
131 Verifier.reset();
132 }
133 }
134
135 // Then set up the printing mechanisms.
136 std::string Output;
137 raw_string_ostream OS(Output);
138 RecordPrinter RP(OS);
139 BlockPrinter BP(OS, RP);
140 for (auto &ProcessThreadBlocks : Index) {
141 auto &Blocks = ProcessThreadBlocks.second;
142 for (auto &B : Blocks) {
143 for (auto *R : B.Records)
144 ASSERT_FALSE(errorToBool(R->apply(BP)));
145 BP.reset();
146 }
147 }
148
149 OS.flush();
150 EXPECT_THAT(Output, Not(Eq("")));
151 }
152
153 } // namespace
154 } // namespace xray
155 } // namespace llvm