xref: /freebsd-src/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===----------------------- CodeRegionGenerator.h --------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric /// \file
90b57cec5SDimitry Andric ///
100b57cec5SDimitry Andric /// This file declares classes responsible for generating llvm-mca
110b57cec5SDimitry Andric /// CodeRegions from various types of input. llvm-mca only analyzes CodeRegions,
120b57cec5SDimitry Andric /// so the classes here provide the input-to-CodeRegions translation.
130b57cec5SDimitry Andric //
140b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #ifndef LLVM_TOOLS_LLVM_MCA_CODEREGION_GENERATOR_H
170b57cec5SDimitry Andric #define LLVM_TOOLS_LLVM_MCA_CODEREGION_GENERATOR_H
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric #include "CodeRegion.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
22bdd1243dSDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h"
2306c3fb27SDimitry Andric #include "llvm/MC/MCStreamer.h"
240b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
25349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
26bdd1243dSDimitry Andric #include "llvm/MCA/CustomBehaviour.h"
270b57cec5SDimitry Andric #include "llvm/Support/Error.h"
280b57cec5SDimitry Andric #include "llvm/Support/SourceMgr.h"
290b57cec5SDimitry Andric #include <memory>
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric namespace llvm {
320b57cec5SDimitry Andric namespace mca {
330b57cec5SDimitry Andric 
34bdd1243dSDimitry Andric class MCACommentConsumer : public AsmCommentConsumer {
350b57cec5SDimitry Andric protected:
3606c3fb27SDimitry Andric   bool FoundError = false;
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric public:
3906c3fb27SDimitry Andric   MCACommentConsumer() = default;
40bdd1243dSDimitry Andric 
41bdd1243dSDimitry Andric   bool hadErr() const { return FoundError; }
420b57cec5SDimitry Andric };
430b57cec5SDimitry Andric 
44bdd1243dSDimitry Andric /// A comment consumer that parses strings.  The only valid tokens are strings.
45bdd1243dSDimitry Andric class AnalysisRegionCommentConsumer : public MCACommentConsumer {
46bdd1243dSDimitry Andric   AnalysisRegions &Regions;
47bdd1243dSDimitry Andric 
48bdd1243dSDimitry Andric public:
49bdd1243dSDimitry Andric   AnalysisRegionCommentConsumer(AnalysisRegions &R) : Regions(R) {}
50bdd1243dSDimitry Andric 
51bdd1243dSDimitry Andric   /// Parses a comment. It begins a new region if it is of the form
52bdd1243dSDimitry Andric   /// LLVM-MCA-BEGIN. It ends a region if it is of the form LLVM-MCA-END.
53bdd1243dSDimitry Andric   /// Regions can be optionally named if they are of the form
54bdd1243dSDimitry Andric   /// LLVM-MCA-BEGIN <name> or LLVM-MCA-END <name>. Subregions are
55bdd1243dSDimitry Andric   /// permitted, but a region that begins while another region is active
56bdd1243dSDimitry Andric   /// must be ended before the outer region is ended. If thre is only one
57bdd1243dSDimitry Andric   /// active region, LLVM-MCA-END does not need to provide a name.
58bdd1243dSDimitry Andric   void HandleComment(SMLoc Loc, StringRef CommentText) override;
59bdd1243dSDimitry Andric };
60bdd1243dSDimitry Andric 
61bdd1243dSDimitry Andric /// A comment consumer that parses strings to create InstrumentRegions.
62bdd1243dSDimitry Andric /// The only valid tokens are strings.
63bdd1243dSDimitry Andric class InstrumentRegionCommentConsumer : public MCACommentConsumer {
64bdd1243dSDimitry Andric   llvm::SourceMgr &SM;
65bdd1243dSDimitry Andric 
66bdd1243dSDimitry Andric   InstrumentRegions &Regions;
67bdd1243dSDimitry Andric 
68bdd1243dSDimitry Andric   InstrumentManager &IM;
69bdd1243dSDimitry Andric 
70bdd1243dSDimitry Andric public:
71bdd1243dSDimitry Andric   InstrumentRegionCommentConsumer(llvm::SourceMgr &SM, InstrumentRegions &R,
72bdd1243dSDimitry Andric                                   InstrumentManager &IM)
73bdd1243dSDimitry Andric       : SM(SM), Regions(R), IM(IM) {}
74bdd1243dSDimitry Andric 
75bdd1243dSDimitry Andric   /// Parses a comment. It begins a new region if it is of the form
76bdd1243dSDimitry Andric   /// LLVM-MCA-<INSTRUMENTATION_TYPE> <data> where INSTRUMENTATION_TYPE
77bdd1243dSDimitry Andric   /// is a valid InstrumentKind. If there is already an active
78bdd1243dSDimitry Andric   /// region of type INSTRUMENATION_TYPE, then it will end the active
79bdd1243dSDimitry Andric   /// one and begin a new one using the new data.
80bdd1243dSDimitry Andric   void HandleComment(SMLoc Loc, StringRef CommentText) override;
8106c3fb27SDimitry Andric 
8206c3fb27SDimitry Andric   InstrumentManager &getInstrumentManager() { return IM; }
8306c3fb27SDimitry Andric };
8406c3fb27SDimitry Andric 
8506c3fb27SDimitry Andric // This class provides the callbacks that occur when parsing input assembly.
8606c3fb27SDimitry Andric class MCStreamerWrapper : public MCStreamer {
8706c3fb27SDimitry Andric protected:
8806c3fb27SDimitry Andric   CodeRegions &Regions;
8906c3fb27SDimitry Andric 
9006c3fb27SDimitry Andric public:
9106c3fb27SDimitry Andric   MCStreamerWrapper(MCContext &Context, mca::CodeRegions &R)
9206c3fb27SDimitry Andric       : MCStreamer(Context), Regions(R) {}
9306c3fb27SDimitry Andric 
9406c3fb27SDimitry Andric   // We only want to intercept the emission of new instructions.
9506c3fb27SDimitry Andric   void emitInstruction(const MCInst &Inst,
9606c3fb27SDimitry Andric                        const MCSubtargetInfo & /* unused */) override {
9706c3fb27SDimitry Andric     Regions.addInstruction(Inst);
9806c3fb27SDimitry Andric   }
9906c3fb27SDimitry Andric 
10006c3fb27SDimitry Andric   bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {
10106c3fb27SDimitry Andric     return true;
10206c3fb27SDimitry Andric   }
10306c3fb27SDimitry Andric 
10406c3fb27SDimitry Andric   void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
10506c3fb27SDimitry Andric                         Align ByteAlignment) override {}
10606c3fb27SDimitry Andric   void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
10706c3fb27SDimitry Andric                     uint64_t Size = 0, Align ByteAlignment = Align(1),
10806c3fb27SDimitry Andric                     SMLoc Loc = SMLoc()) override {}
10906c3fb27SDimitry Andric   void emitGPRel32Value(const MCExpr *Value) override {}
11006c3fb27SDimitry Andric   void beginCOFFSymbolDef(const MCSymbol *Symbol) override {}
11106c3fb27SDimitry Andric   void emitCOFFSymbolStorageClass(int StorageClass) override {}
11206c3fb27SDimitry Andric   void emitCOFFSymbolType(int Type) override {}
11306c3fb27SDimitry Andric   void endCOFFSymbolDef() override {}
11406c3fb27SDimitry Andric 
11506c3fb27SDimitry Andric   ArrayRef<MCInst> GetInstructionSequence(unsigned Index) const {
11606c3fb27SDimitry Andric     return Regions.getInstructionSequence(Index);
11706c3fb27SDimitry Andric   }
11806c3fb27SDimitry Andric };
11906c3fb27SDimitry Andric 
12006c3fb27SDimitry Andric class InstrumentMCStreamer : public MCStreamerWrapper {
12106c3fb27SDimitry Andric   InstrumentManager &IM;
12206c3fb27SDimitry Andric 
12306c3fb27SDimitry Andric public:
12406c3fb27SDimitry Andric   InstrumentMCStreamer(MCContext &Context, mca::InstrumentRegions &R,
12506c3fb27SDimitry Andric                        InstrumentManager &IM)
12606c3fb27SDimitry Andric       : MCStreamerWrapper(Context, R), IM(IM) {}
12706c3fb27SDimitry Andric 
12806c3fb27SDimitry Andric   void emitInstruction(const MCInst &Inst,
12906c3fb27SDimitry Andric                        const MCSubtargetInfo &MCSI) override {
13006c3fb27SDimitry Andric     MCStreamerWrapper::emitInstruction(Inst, MCSI);
13106c3fb27SDimitry Andric 
13206c3fb27SDimitry Andric     // We know that Regions is an InstrumentRegions by the constructor.
13306c3fb27SDimitry Andric     for (UniqueInstrument &I : IM.createInstruments(Inst)) {
13406c3fb27SDimitry Andric       StringRef InstrumentKind = I.get()->getDesc();
13506c3fb27SDimitry Andric       // End InstrumentType region if one is open
13606c3fb27SDimitry Andric       if (Regions.isRegionActive(InstrumentKind))
13706c3fb27SDimitry Andric         Regions.endRegion(InstrumentKind, Inst.getLoc());
13806c3fb27SDimitry Andric       // Start new instrumentation region
13906c3fb27SDimitry Andric       Regions.beginRegion(InstrumentKind, Inst.getLoc(), std::move(I));
14006c3fb27SDimitry Andric     }
14106c3fb27SDimitry Andric   }
142bdd1243dSDimitry Andric };
143bdd1243dSDimitry Andric 
144bdd1243dSDimitry Andric /// This abstract class is responsible for parsing the input given to
145bdd1243dSDimitry Andric /// the llvm-mca driver, and converting that into a CodeRegions instance.
146bdd1243dSDimitry Andric class CodeRegionGenerator {
147bdd1243dSDimitry Andric protected:
148bdd1243dSDimitry Andric   CodeRegionGenerator(const CodeRegionGenerator &) = delete;
149bdd1243dSDimitry Andric   CodeRegionGenerator &operator=(const CodeRegionGenerator &) = delete;
150bdd1243dSDimitry Andric   virtual Expected<const CodeRegions &>
151*0fca6ea1SDimitry Andric   parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP,
152*0fca6ea1SDimitry Andric                    bool SkipFailures) = 0;
153bdd1243dSDimitry Andric 
154bdd1243dSDimitry Andric public:
155bdd1243dSDimitry Andric   CodeRegionGenerator() {}
156bdd1243dSDimitry Andric   virtual ~CodeRegionGenerator();
157bdd1243dSDimitry Andric };
158bdd1243dSDimitry Andric 
159bdd1243dSDimitry Andric /// Abastract CodeRegionGenerator with AnalysisRegions member
160bdd1243dSDimitry Andric class AnalysisRegionGenerator : public virtual CodeRegionGenerator {
161bdd1243dSDimitry Andric protected:
162bdd1243dSDimitry Andric   AnalysisRegions Regions;
163bdd1243dSDimitry Andric 
164bdd1243dSDimitry Andric public:
165bdd1243dSDimitry Andric   AnalysisRegionGenerator(llvm::SourceMgr &SM) : Regions(SM) {}
166bdd1243dSDimitry Andric 
167bdd1243dSDimitry Andric   virtual Expected<const AnalysisRegions &>
168*0fca6ea1SDimitry Andric   parseAnalysisRegions(const std::unique_ptr<MCInstPrinter> &IP,
169*0fca6ea1SDimitry Andric                        bool SkipFailures) = 0;
170bdd1243dSDimitry Andric };
171bdd1243dSDimitry Andric 
172bdd1243dSDimitry Andric /// Abstract CodeRegionGenerator with InstrumentRegionsRegions member
173bdd1243dSDimitry Andric class InstrumentRegionGenerator : public virtual CodeRegionGenerator {
174bdd1243dSDimitry Andric protected:
175bdd1243dSDimitry Andric   InstrumentRegions Regions;
176bdd1243dSDimitry Andric 
177bdd1243dSDimitry Andric public:
178bdd1243dSDimitry Andric   InstrumentRegionGenerator(llvm::SourceMgr &SM) : Regions(SM) {}
179bdd1243dSDimitry Andric 
180bdd1243dSDimitry Andric   virtual Expected<const InstrumentRegions &>
181*0fca6ea1SDimitry Andric   parseInstrumentRegions(const std::unique_ptr<MCInstPrinter> &IP,
182*0fca6ea1SDimitry Andric                          bool SkipFailures) = 0;
183bdd1243dSDimitry Andric };
184bdd1243dSDimitry Andric 
185bdd1243dSDimitry Andric /// This abstract class is responsible for parsing input ASM and
186bdd1243dSDimitry Andric /// generating a CodeRegions instance.
187bdd1243dSDimitry Andric class AsmCodeRegionGenerator : public virtual CodeRegionGenerator {
1880b57cec5SDimitry Andric   const Target &TheTarget;
1890b57cec5SDimitry Andric   const MCAsmInfo &MAI;
1900b57cec5SDimitry Andric   const MCSubtargetInfo &STI;
1910b57cec5SDimitry Andric   const MCInstrInfo &MCII;
1920b57cec5SDimitry Andric   unsigned AssemblerDialect; // This is set during parsing.
1930b57cec5SDimitry Andric 
19406c3fb27SDimitry Andric protected:
19506c3fb27SDimitry Andric   MCContext &Ctx;
19606c3fb27SDimitry Andric 
1970b57cec5SDimitry Andric public:
198bdd1243dSDimitry Andric   AsmCodeRegionGenerator(const Target &T, MCContext &C, const MCAsmInfo &A,
199bdd1243dSDimitry Andric                          const MCSubtargetInfo &S, const MCInstrInfo &I)
20006c3fb27SDimitry Andric       : TheTarget(T), MAI(A), STI(S), MCII(I), AssemblerDialect(0), Ctx(C) {}
201bdd1243dSDimitry Andric 
202bdd1243dSDimitry Andric   virtual MCACommentConsumer *getCommentConsumer() = 0;
203bdd1243dSDimitry Andric   virtual CodeRegions &getRegions() = 0;
20406c3fb27SDimitry Andric   virtual MCStreamerWrapper *getMCStreamer() = 0;
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric   unsigned getAssemblerDialect() const { return AssemblerDialect; }
207fe6060f1SDimitry Andric   Expected<const CodeRegions &>
208*0fca6ea1SDimitry Andric   parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP,
209*0fca6ea1SDimitry Andric                    bool SkipFailures) override;
2100b57cec5SDimitry Andric };
2110b57cec5SDimitry Andric 
212bdd1243dSDimitry Andric class AsmAnalysisRegionGenerator final : public AnalysisRegionGenerator,
213bdd1243dSDimitry Andric                                          public AsmCodeRegionGenerator {
214bdd1243dSDimitry Andric   AnalysisRegionCommentConsumer CC;
21506c3fb27SDimitry Andric   MCStreamerWrapper Streamer;
216bdd1243dSDimitry Andric 
217bdd1243dSDimitry Andric public:
218bdd1243dSDimitry Andric   AsmAnalysisRegionGenerator(const Target &T, llvm::SourceMgr &SM, MCContext &C,
219bdd1243dSDimitry Andric                              const MCAsmInfo &A, const MCSubtargetInfo &S,
220bdd1243dSDimitry Andric                              const MCInstrInfo &I)
221bdd1243dSDimitry Andric       : AnalysisRegionGenerator(SM), AsmCodeRegionGenerator(T, C, A, S, I),
22206c3fb27SDimitry Andric         CC(Regions), Streamer(Ctx, Regions) {}
223bdd1243dSDimitry Andric 
224bdd1243dSDimitry Andric   MCACommentConsumer *getCommentConsumer() override { return &CC; };
225bdd1243dSDimitry Andric   CodeRegions &getRegions() override { return Regions; };
22606c3fb27SDimitry Andric   MCStreamerWrapper *getMCStreamer() override { return &Streamer; }
227bdd1243dSDimitry Andric 
228bdd1243dSDimitry Andric   Expected<const AnalysisRegions &>
229*0fca6ea1SDimitry Andric   parseAnalysisRegions(const std::unique_ptr<MCInstPrinter> &IP,
230*0fca6ea1SDimitry Andric                        bool SkipFailures) override {
231*0fca6ea1SDimitry Andric     Expected<const CodeRegions &> RegionsOrErr =
232*0fca6ea1SDimitry Andric         parseCodeRegions(IP, SkipFailures);
233bdd1243dSDimitry Andric     if (!RegionsOrErr)
234bdd1243dSDimitry Andric       return RegionsOrErr.takeError();
235bdd1243dSDimitry Andric     else
236bdd1243dSDimitry Andric       return static_cast<const AnalysisRegions &>(*RegionsOrErr);
237bdd1243dSDimitry Andric   }
238bdd1243dSDimitry Andric 
239bdd1243dSDimitry Andric   Expected<const CodeRegions &>
240*0fca6ea1SDimitry Andric   parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP,
241*0fca6ea1SDimitry Andric                    bool SkipFailures) override {
242*0fca6ea1SDimitry Andric     return AsmCodeRegionGenerator::parseCodeRegions(IP, SkipFailures);
243bdd1243dSDimitry Andric   }
244bdd1243dSDimitry Andric };
245bdd1243dSDimitry Andric 
246bdd1243dSDimitry Andric class AsmInstrumentRegionGenerator final : public InstrumentRegionGenerator,
247bdd1243dSDimitry Andric                                            public AsmCodeRegionGenerator {
248bdd1243dSDimitry Andric   InstrumentRegionCommentConsumer CC;
24906c3fb27SDimitry Andric   InstrumentMCStreamer Streamer;
250bdd1243dSDimitry Andric 
251bdd1243dSDimitry Andric public:
252bdd1243dSDimitry Andric   AsmInstrumentRegionGenerator(const Target &T, llvm::SourceMgr &SM,
253bdd1243dSDimitry Andric                                MCContext &C, const MCAsmInfo &A,
254bdd1243dSDimitry Andric                                const MCSubtargetInfo &S, const MCInstrInfo &I,
255bdd1243dSDimitry Andric                                InstrumentManager &IM)
256bdd1243dSDimitry Andric       : InstrumentRegionGenerator(SM), AsmCodeRegionGenerator(T, C, A, S, I),
25706c3fb27SDimitry Andric         CC(SM, Regions, IM), Streamer(Ctx, Regions, IM) {}
258bdd1243dSDimitry Andric 
259bdd1243dSDimitry Andric   MCACommentConsumer *getCommentConsumer() override { return &CC; };
260bdd1243dSDimitry Andric   CodeRegions &getRegions() override { return Regions; };
26106c3fb27SDimitry Andric   MCStreamerWrapper *getMCStreamer() override { return &Streamer; }
262bdd1243dSDimitry Andric 
263bdd1243dSDimitry Andric   Expected<const InstrumentRegions &>
264*0fca6ea1SDimitry Andric   parseInstrumentRegions(const std::unique_ptr<MCInstPrinter> &IP,
265*0fca6ea1SDimitry Andric                          bool SkipFailures) override {
266*0fca6ea1SDimitry Andric     Expected<const CodeRegions &> RegionsOrErr =
267*0fca6ea1SDimitry Andric         parseCodeRegions(IP, SkipFailures);
268bdd1243dSDimitry Andric     if (!RegionsOrErr)
269bdd1243dSDimitry Andric       return RegionsOrErr.takeError();
270bdd1243dSDimitry Andric     else
271bdd1243dSDimitry Andric       return static_cast<const InstrumentRegions &>(*RegionsOrErr);
272bdd1243dSDimitry Andric   }
273bdd1243dSDimitry Andric 
274bdd1243dSDimitry Andric   Expected<const CodeRegions &>
275*0fca6ea1SDimitry Andric   parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP,
276*0fca6ea1SDimitry Andric                    bool SkipFailures) override {
277*0fca6ea1SDimitry Andric     return AsmCodeRegionGenerator::parseCodeRegions(IP, SkipFailures);
278bdd1243dSDimitry Andric   }
279bdd1243dSDimitry Andric };
280bdd1243dSDimitry Andric 
2810b57cec5SDimitry Andric } // namespace mca
2820b57cec5SDimitry Andric } // namespace llvm
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric #endif // LLVM_TOOLS_LLVM_MCA_CODEREGION_GENERATOR_H
285