]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/llvm-mca/CodeRegionGenerator.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / llvm-mca / CodeRegionGenerator.cpp
1 //===----------------------- CodeRegionGenerator.cpp ------------*- C++ -*-===//
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 /// \file
10 ///
11 /// This file defines classes responsible for generating llvm-mca
12 /// CodeRegions from various types of input. llvm-mca only analyzes CodeRegions,
13 /// so the classes here provide the input-to-CodeRegions translation.
14 //
15 //===----------------------------------------------------------------------===//
16
17 #include "CodeRegionGenerator.h"
18 #include "llvm/ADT/ArrayRef.h"
19 #include "llvm/ADT/StringRef.h"
20 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
21 #include "llvm/MC/MCStreamer.h"
22 #include "llvm/MC/MCTargetOptions.h"
23 #include "llvm/Support/Error.h"
24 #include "llvm/Support/SMLoc.h"
25 #include <memory>
26
27 namespace llvm {
28 namespace mca {
29
30 // This virtual dtor serves as the anchor for the CodeRegionGenerator class.
31 CodeRegionGenerator::~CodeRegionGenerator() {}
32
33 // A comment consumer that parses strings.  The only valid tokens are strings.
34 class MCACommentConsumer : public AsmCommentConsumer {
35 public:
36   CodeRegions &Regions;
37
38   MCACommentConsumer(CodeRegions &R) : Regions(R) {}
39   void HandleComment(SMLoc Loc, StringRef CommentText) override;
40 };
41
42 // This class provides the callbacks that occur when parsing input assembly.
43 class MCStreamerWrapper final : public MCStreamer {
44   CodeRegions &Regions;
45
46 public:
47   MCStreamerWrapper(MCContext &Context, mca::CodeRegions &R)
48       : MCStreamer(Context), Regions(R) {}
49
50   // We only want to intercept the emission of new instructions.
51   virtual void EmitInstruction(const MCInst &Inst,
52                                const MCSubtargetInfo & /* unused */,
53                                bool /* unused */) override {
54     Regions.addInstruction(Inst);
55   }
56
57   bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {
58     return true;
59   }
60
61   void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
62                         unsigned ByteAlignment) override {}
63   void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
64                     uint64_t Size = 0, unsigned ByteAlignment = 0,
65                     SMLoc Loc = SMLoc()) override {}
66   void EmitGPRel32Value(const MCExpr *Value) override {}
67   void BeginCOFFSymbolDef(const MCSymbol *Symbol) override {}
68   void EmitCOFFSymbolStorageClass(int StorageClass) override {}
69   void EmitCOFFSymbolType(int Type) override {}
70   void EndCOFFSymbolDef() override {}
71
72   ArrayRef<MCInst> GetInstructionSequence(unsigned Index) const {
73     return Regions.getInstructionSequence(Index);
74   }
75 };
76
77 void MCACommentConsumer::HandleComment(SMLoc Loc, StringRef CommentText) {
78   // Skip empty comments.
79   StringRef Comment(CommentText);
80   if (Comment.empty())
81     return;
82
83   // Skip spaces and tabs.
84   unsigned Position = Comment.find_first_not_of(" \t");
85   if (Position >= Comment.size())
86     // We reached the end of the comment. Bail out.
87     return;
88
89   Comment = Comment.drop_front(Position);
90   if (Comment.consume_front("LLVM-MCA-END")) {
91     Regions.endRegion(Loc);
92     return;
93   }
94
95   // Try to parse the LLVM-MCA-BEGIN comment.
96   if (!Comment.consume_front("LLVM-MCA-BEGIN"))
97     return;
98
99   // Skip spaces and tabs.
100   Position = Comment.find_first_not_of(" \t");
101   if (Position < Comment.size())
102     Comment = Comment.drop_front(Position);
103   // Use the rest of the string as a descriptor for this code snippet.
104   Regions.beginRegion(Comment, Loc);
105 }
106
107 Expected<const CodeRegions &> AsmCodeRegionGenerator::parseCodeRegions() {
108   MCTargetOptions Opts;
109   Opts.PreserveAsmComments = false;
110   MCStreamerWrapper Str(Ctx, Regions);
111
112   // Create a MCAsmParser and setup the lexer to recognize llvm-mca ASM
113   // comments.
114   std::unique_ptr<MCAsmParser> Parser(
115       createMCAsmParser(Regions.getSourceMgr(), Ctx, Str, MAI));
116   MCAsmLexer &Lexer = Parser->getLexer();
117   MCACommentConsumer CC(Regions);
118   Lexer.setCommentConsumer(&CC);
119
120   // Create a target-specific parser and perform the parse.
121   std::unique_ptr<MCTargetAsmParser> TAP(
122       TheTarget.createMCAsmParser(STI, *Parser, MCII, Opts));
123   if (!TAP)
124     return make_error<StringError>(
125         "This target does not support assembly parsing.",
126         inconvertibleErrorCode());
127   Parser->setTargetParser(*TAP);
128   Parser->Run(false);
129
130   // Get the assembler dialect from the input.  llvm-mca will use this as the
131   // default dialect when printing reports.
132   AssemblerDialect = Parser->getAssemblerDialect();
133   return Regions;
134 }
135
136 } // namespace mca
137 } // namespace llvm