xref: /llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.h (revision 1de0535e84f03941badc8021bbc87a8c674a379f)
123f7106eSMatt Davis //===----------------------- CodeRegionGenerator.h --------------*- C++ -*-===//
223f7106eSMatt Davis //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
623f7106eSMatt Davis //
723f7106eSMatt Davis //===----------------------------------------------------------------------===//
823f7106eSMatt Davis /// \file
923f7106eSMatt Davis ///
1023f7106eSMatt Davis /// This file declares classes responsible for generating llvm-mca
1123f7106eSMatt Davis /// CodeRegions from various types of input. llvm-mca only analyzes CodeRegions,
1223f7106eSMatt Davis /// so the classes here provide the input-to-CodeRegions translation.
1323f7106eSMatt Davis //
1423f7106eSMatt Davis //===----------------------------------------------------------------------===//
1523f7106eSMatt Davis 
1623f7106eSMatt Davis #ifndef LLVM_TOOLS_LLVM_MCA_CODEREGION_GENERATOR_H
1723f7106eSMatt Davis #define LLVM_TOOLS_LLVM_MCA_CODEREGION_GENERATOR_H
1823f7106eSMatt Davis 
1923f7106eSMatt Davis #include "CodeRegion.h"
2023f7106eSMatt Davis #include "llvm/MC/MCAsmInfo.h"
2123f7106eSMatt Davis #include "llvm/MC/MCContext.h"
2298e342dcSMichael Maitland #include "llvm/MC/MCParser/MCAsmLexer.h"
23ecf372f9SMichael Maitland #include "llvm/MC/MCStreamer.h"
2423f7106eSMatt Davis #include "llvm/MC/MCSubtargetInfo.h"
2589b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h"
2698e342dcSMichael Maitland #include "llvm/MCA/CustomBehaviour.h"
2723f7106eSMatt Davis #include "llvm/Support/Error.h"
2823f7106eSMatt Davis #include "llvm/Support/SourceMgr.h"
2923f7106eSMatt Davis #include <memory>
3023f7106eSMatt Davis 
3123f7106eSMatt Davis namespace llvm {
3223f7106eSMatt Davis namespace mca {
3323f7106eSMatt Davis 
3498e342dcSMichael Maitland class MCACommentConsumer : public AsmCommentConsumer {
35b88b8307SMichael Maitland protected:
3687709b71SKazu Hirata   bool FoundError = false;
37e8e92c83SMichael Maitland 
38e8e92c83SMichael Maitland public:
3987709b71SKazu Hirata   MCACommentConsumer() = default;
4098e342dcSMichael Maitland 
hadErr()4198e342dcSMichael Maitland   bool hadErr() const { return FoundError; }
42b88b8307SMichael Maitland };
43b88b8307SMichael Maitland 
4498e342dcSMichael Maitland /// A comment consumer that parses strings.  The only valid tokens are strings.
4598e342dcSMichael Maitland class AnalysisRegionCommentConsumer : public MCACommentConsumer {
4698e342dcSMichael Maitland   AnalysisRegions &Regions;
4798e342dcSMichael Maitland 
4898e342dcSMichael Maitland public:
AnalysisRegionCommentConsumer(AnalysisRegions & R)4998e342dcSMichael Maitland   AnalysisRegionCommentConsumer(AnalysisRegions &R) : Regions(R) {}
5098e342dcSMichael Maitland 
5198e342dcSMichael Maitland   /// Parses a comment. It begins a new region if it is of the form
5298e342dcSMichael Maitland   /// LLVM-MCA-BEGIN. It ends a region if it is of the form LLVM-MCA-END.
5398e342dcSMichael Maitland   /// Regions can be optionally named if they are of the form
5498e342dcSMichael Maitland   /// LLVM-MCA-BEGIN <name> or LLVM-MCA-END <name>. Subregions are
5598e342dcSMichael Maitland   /// permitted, but a region that begins while another region is active
5698e342dcSMichael Maitland   /// must be ended before the outer region is ended. If thre is only one
5798e342dcSMichael Maitland   /// active region, LLVM-MCA-END does not need to provide a name.
5898e342dcSMichael Maitland   void HandleComment(SMLoc Loc, StringRef CommentText) override;
5998e342dcSMichael Maitland };
6098e342dcSMichael Maitland 
6198e342dcSMichael Maitland /// A comment consumer that parses strings to create InstrumentRegions.
6298e342dcSMichael Maitland /// The only valid tokens are strings.
6398e342dcSMichael Maitland class InstrumentRegionCommentConsumer : public MCACommentConsumer {
6498e342dcSMichael Maitland   llvm::SourceMgr &SM;
6598e342dcSMichael Maitland 
6698e342dcSMichael Maitland   InstrumentRegions &Regions;
6798e342dcSMichael Maitland 
6898e342dcSMichael Maitland   InstrumentManager &IM;
6998e342dcSMichael Maitland 
7098e342dcSMichael Maitland public:
InstrumentRegionCommentConsumer(llvm::SourceMgr & SM,InstrumentRegions & R,InstrumentManager & IM)7198e342dcSMichael Maitland   InstrumentRegionCommentConsumer(llvm::SourceMgr &SM, InstrumentRegions &R,
7298e342dcSMichael Maitland                                   InstrumentManager &IM)
7398e342dcSMichael Maitland       : SM(SM), Regions(R), IM(IM) {}
7498e342dcSMichael Maitland 
7598e342dcSMichael Maitland   /// Parses a comment. It begins a new region if it is of the form
7698e342dcSMichael Maitland   /// LLVM-MCA-<INSTRUMENTATION_TYPE> <data> where INSTRUMENTATION_TYPE
7798e342dcSMichael Maitland   /// is a valid InstrumentKind. If there is already an active
7898e342dcSMichael Maitland   /// region of type INSTRUMENATION_TYPE, then it will end the active
7998e342dcSMichael Maitland   /// one and begin a new one using the new data.
8098e342dcSMichael Maitland   void HandleComment(SMLoc Loc, StringRef CommentText) override;
81ecf372f9SMichael Maitland 
getInstrumentManager()82ecf372f9SMichael Maitland   InstrumentManager &getInstrumentManager() { return IM; }
83ecf372f9SMichael Maitland };
84ecf372f9SMichael Maitland 
85ecf372f9SMichael Maitland // This class provides the callbacks that occur when parsing input assembly.
86ecf372f9SMichael Maitland class MCStreamerWrapper : public MCStreamer {
87ecf372f9SMichael Maitland protected:
88ecf372f9SMichael Maitland   CodeRegions &Regions;
89ecf372f9SMichael Maitland 
90ecf372f9SMichael Maitland public:
MCStreamerWrapper(MCContext & Context,mca::CodeRegions & R)91ecf372f9SMichael Maitland   MCStreamerWrapper(MCContext &Context, mca::CodeRegions &R)
92ecf372f9SMichael Maitland       : MCStreamer(Context), Regions(R) {}
93ecf372f9SMichael Maitland 
94ecf372f9SMichael Maitland   // We only want to intercept the emission of new instructions.
emitInstruction(const MCInst & Inst,const MCSubtargetInfo &)95ecf372f9SMichael Maitland   void emitInstruction(const MCInst &Inst,
96ecf372f9SMichael Maitland                        const MCSubtargetInfo & /* unused */) override {
97ecf372f9SMichael Maitland     Regions.addInstruction(Inst);
98ecf372f9SMichael Maitland   }
99ecf372f9SMichael Maitland 
emitSymbolAttribute(MCSymbol * Symbol,MCSymbolAttr Attribute)100ecf372f9SMichael Maitland   bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {
101ecf372f9SMichael Maitland     return true;
102ecf372f9SMichael Maitland   }
103ecf372f9SMichael Maitland 
emitCommonSymbol(MCSymbol * Symbol,uint64_t Size,Align ByteAlignment)104ecf372f9SMichael Maitland   void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
105ecf372f9SMichael Maitland                         Align ByteAlignment) override {}
106ecf372f9SMichael Maitland   void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
107ecf372f9SMichael Maitland                     uint64_t Size = 0, Align ByteAlignment = Align(1),
108ecf372f9SMichael Maitland                     SMLoc Loc = SMLoc()) override {}
emitGPRel32Value(const MCExpr * Value)109ecf372f9SMichael Maitland   void emitGPRel32Value(const MCExpr *Value) override {}
beginCOFFSymbolDef(const MCSymbol * Symbol)110ecf372f9SMichael Maitland   void beginCOFFSymbolDef(const MCSymbol *Symbol) override {}
emitCOFFSymbolStorageClass(int StorageClass)111ecf372f9SMichael Maitland   void emitCOFFSymbolStorageClass(int StorageClass) override {}
emitCOFFSymbolType(int Type)112ecf372f9SMichael Maitland   void emitCOFFSymbolType(int Type) override {}
endCOFFSymbolDef()113ecf372f9SMichael Maitland   void endCOFFSymbolDef() override {}
114ecf372f9SMichael Maitland 
GetInstructionSequence(unsigned Index)115ecf372f9SMichael Maitland   ArrayRef<MCInst> GetInstructionSequence(unsigned Index) const {
116ecf372f9SMichael Maitland     return Regions.getInstructionSequence(Index);
117ecf372f9SMichael Maitland   }
118ecf372f9SMichael Maitland };
119ecf372f9SMichael Maitland 
120ecf372f9SMichael Maitland class InstrumentMCStreamer : public MCStreamerWrapper {
121ecf372f9SMichael Maitland   InstrumentManager &IM;
122ecf372f9SMichael Maitland 
123ecf372f9SMichael Maitland public:
InstrumentMCStreamer(MCContext & Context,mca::InstrumentRegions & R,InstrumentManager & IM)124ecf372f9SMichael Maitland   InstrumentMCStreamer(MCContext &Context, mca::InstrumentRegions &R,
125ecf372f9SMichael Maitland                        InstrumentManager &IM)
126ecf372f9SMichael Maitland       : MCStreamerWrapper(Context, R), IM(IM) {}
127ecf372f9SMichael Maitland 
emitInstruction(const MCInst & Inst,const MCSubtargetInfo & MCSI)128ecf372f9SMichael Maitland   void emitInstruction(const MCInst &Inst,
129ecf372f9SMichael Maitland                        const MCSubtargetInfo &MCSI) override {
130ecf372f9SMichael Maitland     MCStreamerWrapper::emitInstruction(Inst, MCSI);
131ecf372f9SMichael Maitland 
132ecf372f9SMichael Maitland     // We know that Regions is an InstrumentRegions by the constructor.
133ecf372f9SMichael Maitland     for (UniqueInstrument &I : IM.createInstruments(Inst)) {
134ecf372f9SMichael Maitland       StringRef InstrumentKind = I.get()->getDesc();
135ecf372f9SMichael Maitland       // End InstrumentType region if one is open
136ecf372f9SMichael Maitland       if (Regions.isRegionActive(InstrumentKind))
137ecf372f9SMichael Maitland         Regions.endRegion(InstrumentKind, Inst.getLoc());
138ecf372f9SMichael Maitland       // Start new instrumentation region
139ecf372f9SMichael Maitland       Regions.beginRegion(InstrumentKind, Inst.getLoc(), std::move(I));
140ecf372f9SMichael Maitland     }
141ecf372f9SMichael Maitland   }
14298e342dcSMichael Maitland };
14398e342dcSMichael Maitland 
14498e342dcSMichael Maitland /// This abstract class is responsible for parsing the input given to
14598e342dcSMichael Maitland /// the llvm-mca driver, and converting that into a CodeRegions instance.
14698e342dcSMichael Maitland class CodeRegionGenerator {
14798e342dcSMichael Maitland protected:
14898e342dcSMichael Maitland   CodeRegionGenerator(const CodeRegionGenerator &) = delete;
14998e342dcSMichael Maitland   CodeRegionGenerator &operator=(const CodeRegionGenerator &) = delete;
15098e342dcSMichael Maitland   virtual Expected<const CodeRegions &>
151*1de0535eSPeter Waller   parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP,
152*1de0535eSPeter Waller                    bool SkipFailures) = 0;
15398e342dcSMichael Maitland 
15498e342dcSMichael Maitland public:
CodeRegionGenerator()15598e342dcSMichael Maitland   CodeRegionGenerator() {}
15698e342dcSMichael Maitland   virtual ~CodeRegionGenerator();
15798e342dcSMichael Maitland };
15898e342dcSMichael Maitland 
15998e342dcSMichael Maitland /// Abastract CodeRegionGenerator with AnalysisRegions member
16098e342dcSMichael Maitland class AnalysisRegionGenerator : public virtual CodeRegionGenerator {
16198e342dcSMichael Maitland protected:
16298e342dcSMichael Maitland   AnalysisRegions Regions;
16398e342dcSMichael Maitland 
16498e342dcSMichael Maitland public:
AnalysisRegionGenerator(llvm::SourceMgr & SM)16598e342dcSMichael Maitland   AnalysisRegionGenerator(llvm::SourceMgr &SM) : Regions(SM) {}
16698e342dcSMichael Maitland 
16798e342dcSMichael Maitland   virtual Expected<const AnalysisRegions &>
168*1de0535eSPeter Waller   parseAnalysisRegions(const std::unique_ptr<MCInstPrinter> &IP,
169*1de0535eSPeter Waller                        bool SkipFailures) = 0;
17098e342dcSMichael Maitland };
17198e342dcSMichael Maitland 
17298e342dcSMichael Maitland /// Abstract CodeRegionGenerator with InstrumentRegionsRegions member
17398e342dcSMichael Maitland class InstrumentRegionGenerator : public virtual CodeRegionGenerator {
17498e342dcSMichael Maitland protected:
17598e342dcSMichael Maitland   InstrumentRegions Regions;
17698e342dcSMichael Maitland 
17798e342dcSMichael Maitland public:
InstrumentRegionGenerator(llvm::SourceMgr & SM)17898e342dcSMichael Maitland   InstrumentRegionGenerator(llvm::SourceMgr &SM) : Regions(SM) {}
17998e342dcSMichael Maitland 
18098e342dcSMichael Maitland   virtual Expected<const InstrumentRegions &>
181*1de0535eSPeter Waller   parseInstrumentRegions(const std::unique_ptr<MCInstPrinter> &IP,
182*1de0535eSPeter Waller                          bool SkipFailures) = 0;
18398e342dcSMichael Maitland };
18498e342dcSMichael Maitland 
18598e342dcSMichael Maitland /// This abstract class is responsible for parsing input ASM and
18698e342dcSMichael Maitland /// generating a CodeRegions instance.
18798e342dcSMichael Maitland class AsmCodeRegionGenerator : public virtual CodeRegionGenerator {
18823f7106eSMatt Davis   const Target &TheTarget;
18923f7106eSMatt Davis   const MCAsmInfo &MAI;
19023f7106eSMatt Davis   const MCSubtargetInfo &STI;
19123f7106eSMatt Davis   const MCInstrInfo &MCII;
19223f7106eSMatt Davis   unsigned AssemblerDialect; // This is set during parsing.
19323f7106eSMatt Davis 
194ecf372f9SMichael Maitland protected:
195ecf372f9SMichael Maitland   MCContext &Ctx;
196ecf372f9SMichael Maitland 
19723f7106eSMatt Davis public:
AsmCodeRegionGenerator(const Target & T,MCContext & C,const MCAsmInfo & A,const MCSubtargetInfo & S,const MCInstrInfo & I)19898e342dcSMichael Maitland   AsmCodeRegionGenerator(const Target &T, MCContext &C, const MCAsmInfo &A,
19998e342dcSMichael Maitland                          const MCSubtargetInfo &S, const MCInstrInfo &I)
200ecf372f9SMichael Maitland       : TheTarget(T), MAI(A), STI(S), MCII(I), AssemblerDialect(0), Ctx(C) {}
20198e342dcSMichael Maitland 
20298e342dcSMichael Maitland   virtual MCACommentConsumer *getCommentConsumer() = 0;
20398e342dcSMichael Maitland   virtual CodeRegions &getRegions() = 0;
204ecf372f9SMichael Maitland   virtual MCStreamerWrapper *getMCStreamer() = 0;
20523f7106eSMatt Davis 
getAssemblerDialect()20623f7106eSMatt Davis   unsigned getAssemblerDialect() const { return AssemblerDialect; }
207e5d59db4SPatrick Holland   Expected<const CodeRegions &>
208*1de0535eSPeter Waller   parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP,
209*1de0535eSPeter Waller                    bool SkipFailures) override;
21023f7106eSMatt Davis };
21123f7106eSMatt Davis 
21298e342dcSMichael Maitland class AsmAnalysisRegionGenerator final : public AnalysisRegionGenerator,
21398e342dcSMichael Maitland                                          public AsmCodeRegionGenerator {
21498e342dcSMichael Maitland   AnalysisRegionCommentConsumer CC;
215ecf372f9SMichael Maitland   MCStreamerWrapper Streamer;
21698e342dcSMichael Maitland 
21798e342dcSMichael Maitland public:
AsmAnalysisRegionGenerator(const Target & T,llvm::SourceMgr & SM,MCContext & C,const MCAsmInfo & A,const MCSubtargetInfo & S,const MCInstrInfo & I)21898e342dcSMichael Maitland   AsmAnalysisRegionGenerator(const Target &T, llvm::SourceMgr &SM, MCContext &C,
21998e342dcSMichael Maitland                              const MCAsmInfo &A, const MCSubtargetInfo &S,
22098e342dcSMichael Maitland                              const MCInstrInfo &I)
22198e342dcSMichael Maitland       : AnalysisRegionGenerator(SM), AsmCodeRegionGenerator(T, C, A, S, I),
222ecf372f9SMichael Maitland         CC(Regions), Streamer(Ctx, Regions) {}
22398e342dcSMichael Maitland 
getCommentConsumer()22498e342dcSMichael Maitland   MCACommentConsumer *getCommentConsumer() override { return &CC; };
getRegions()22598e342dcSMichael Maitland   CodeRegions &getRegions() override { return Regions; };
getMCStreamer()226ecf372f9SMichael Maitland   MCStreamerWrapper *getMCStreamer() override { return &Streamer; }
22798e342dcSMichael Maitland 
22898e342dcSMichael Maitland   Expected<const AnalysisRegions &>
parseAnalysisRegions(const std::unique_ptr<MCInstPrinter> & IP,bool SkipFailures)229*1de0535eSPeter Waller   parseAnalysisRegions(const std::unique_ptr<MCInstPrinter> &IP,
230*1de0535eSPeter Waller                        bool SkipFailures) override {
231*1de0535eSPeter Waller     Expected<const CodeRegions &> RegionsOrErr =
232*1de0535eSPeter Waller         parseCodeRegions(IP, SkipFailures);
23398e342dcSMichael Maitland     if (!RegionsOrErr)
23498e342dcSMichael Maitland       return RegionsOrErr.takeError();
23598e342dcSMichael Maitland     else
23698e342dcSMichael Maitland       return static_cast<const AnalysisRegions &>(*RegionsOrErr);
23798e342dcSMichael Maitland   }
238c7631606SMichael Maitland 
239c7631606SMichael Maitland   Expected<const CodeRegions &>
parseCodeRegions(const std::unique_ptr<MCInstPrinter> & IP,bool SkipFailures)240*1de0535eSPeter Waller   parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP,
241*1de0535eSPeter Waller                    bool SkipFailures) override {
242*1de0535eSPeter Waller     return AsmCodeRegionGenerator::parseCodeRegions(IP, SkipFailures);
243c7631606SMichael Maitland   }
24498e342dcSMichael Maitland };
24598e342dcSMichael Maitland 
24698e342dcSMichael Maitland class AsmInstrumentRegionGenerator final : public InstrumentRegionGenerator,
24798e342dcSMichael Maitland                                            public AsmCodeRegionGenerator {
24898e342dcSMichael Maitland   InstrumentRegionCommentConsumer CC;
249ecf372f9SMichael Maitland   InstrumentMCStreamer Streamer;
25098e342dcSMichael Maitland 
25198e342dcSMichael Maitland public:
AsmInstrumentRegionGenerator(const Target & T,llvm::SourceMgr & SM,MCContext & C,const MCAsmInfo & A,const MCSubtargetInfo & S,const MCInstrInfo & I,InstrumentManager & IM)25298e342dcSMichael Maitland   AsmInstrumentRegionGenerator(const Target &T, llvm::SourceMgr &SM,
25398e342dcSMichael Maitland                                MCContext &C, const MCAsmInfo &A,
25498e342dcSMichael Maitland                                const MCSubtargetInfo &S, const MCInstrInfo &I,
25598e342dcSMichael Maitland                                InstrumentManager &IM)
25698e342dcSMichael Maitland       : InstrumentRegionGenerator(SM), AsmCodeRegionGenerator(T, C, A, S, I),
257ecf372f9SMichael Maitland         CC(SM, Regions, IM), Streamer(Ctx, Regions, IM) {}
25898e342dcSMichael Maitland 
getCommentConsumer()25998e342dcSMichael Maitland   MCACommentConsumer *getCommentConsumer() override { return &CC; };
getRegions()26098e342dcSMichael Maitland   CodeRegions &getRegions() override { return Regions; };
getMCStreamer()261ecf372f9SMichael Maitland   MCStreamerWrapper *getMCStreamer() override { return &Streamer; }
26298e342dcSMichael Maitland 
26398e342dcSMichael Maitland   Expected<const InstrumentRegions &>
parseInstrumentRegions(const std::unique_ptr<MCInstPrinter> & IP,bool SkipFailures)264*1de0535eSPeter Waller   parseInstrumentRegions(const std::unique_ptr<MCInstPrinter> &IP,
265*1de0535eSPeter Waller                          bool SkipFailures) override {
266*1de0535eSPeter Waller     Expected<const CodeRegions &> RegionsOrErr =
267*1de0535eSPeter Waller         parseCodeRegions(IP, SkipFailures);
26898e342dcSMichael Maitland     if (!RegionsOrErr)
26998e342dcSMichael Maitland       return RegionsOrErr.takeError();
27098e342dcSMichael Maitland     else
27198e342dcSMichael Maitland       return static_cast<const InstrumentRegions &>(*RegionsOrErr);
27298e342dcSMichael Maitland   }
273c7631606SMichael Maitland 
274c7631606SMichael Maitland   Expected<const CodeRegions &>
parseCodeRegions(const std::unique_ptr<MCInstPrinter> & IP,bool SkipFailures)275*1de0535eSPeter Waller   parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP,
276*1de0535eSPeter Waller                    bool SkipFailures) override {
277*1de0535eSPeter Waller     return AsmCodeRegionGenerator::parseCodeRegions(IP, SkipFailures);
278c7631606SMichael Maitland   }
27998e342dcSMichael Maitland };
28098e342dcSMichael Maitland 
28123f7106eSMatt Davis } // namespace mca
28223f7106eSMatt Davis } // namespace llvm
28323f7106eSMatt Davis 
28423f7106eSMatt Davis #endif // LLVM_TOOLS_LLVM_MCA_CODEREGION_GENERATOR_H
285