1 //===----------------------- CodeRegionGenerator.h --------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 /// This file declares classes responsible for generating llvm-mca
11 /// CodeRegions from various types of input. llvm-mca only analyzes CodeRegions,
12 /// so the classes here provide the input-to-CodeRegions translation.
14 //===----------------------------------------------------------------------===//
16 #ifndef LLVM_TOOLS_LLVM_MCA_CODEREGION_GENERATOR_H
17 #define LLVM_TOOLS_LLVM_MCA_CODEREGION_GENERATOR_H
19 #include "CodeRegion.h"
20 #include "llvm/MC/MCAsmInfo.h"
21 #include "llvm/MC/MCContext.h"
22 #include "llvm/MC/MCParser/MCAsmLexer.h"
23 #include "llvm/MC/MCStreamer.h"
24 #include "llvm/MC/MCSubtargetInfo.h"
25 #include "llvm/MC/TargetRegistry.h"
26 #include "llvm/MCA/CustomBehaviour.h"
27 #include "llvm/Support/Error.h"
28 #include "llvm/Support/SourceMgr.h"
34 class MCACommentConsumer
: public AsmCommentConsumer
{
36 bool FoundError
= false;
39 MCACommentConsumer() = default;
41 bool hadErr() const { return FoundError
; }
44 /// A comment consumer that parses strings. The only valid tokens are strings.
45 class AnalysisRegionCommentConsumer
: public MCACommentConsumer
{
46 AnalysisRegions
&Regions
;
49 AnalysisRegionCommentConsumer(AnalysisRegions
&R
) : Regions(R
) {}
51 /// Parses a comment. It begins a new region if it is of the form
52 /// LLVM-MCA-BEGIN. It ends a region if it is of the form LLVM-MCA-END.
53 /// Regions can be optionally named if they are of the form
54 /// LLVM-MCA-BEGIN <name> or LLVM-MCA-END <name>. Subregions are
55 /// permitted, but a region that begins while another region is active
56 /// must be ended before the outer region is ended. If thre is only one
57 /// active region, LLVM-MCA-END does not need to provide a name.
58 void HandleComment(SMLoc Loc
, StringRef CommentText
) override
;
61 /// A comment consumer that parses strings to create InstrumentRegions.
62 /// The only valid tokens are strings.
63 class InstrumentRegionCommentConsumer
: public MCACommentConsumer
{
66 InstrumentRegions
&Regions
;
68 InstrumentManager
&IM
;
71 InstrumentRegionCommentConsumer(llvm::SourceMgr
&SM
, InstrumentRegions
&R
,
72 InstrumentManager
&IM
)
73 : SM(SM
), Regions(R
), IM(IM
) {}
75 /// Parses a comment. It begins a new region if it is of the form
76 /// LLVM-MCA-<INSTRUMENTATION_TYPE> <data> where INSTRUMENTATION_TYPE
77 /// is a valid InstrumentKind. If there is already an active
78 /// region of type INSTRUMENATION_TYPE, then it will end the active
79 /// one and begin a new one using the new data.
80 void HandleComment(SMLoc Loc
, StringRef CommentText
) override
;
82 InstrumentManager
&getInstrumentManager() { return IM
; }
85 // This class provides the callbacks that occur when parsing input assembly.
86 class MCStreamerWrapper
: public MCStreamer
{
91 MCStreamerWrapper(MCContext
&Context
, mca::CodeRegions
&R
)
92 : MCStreamer(Context
), Regions(R
) {}
94 // We only want to intercept the emission of new instructions.
95 void emitInstruction(const MCInst
&Inst
,
96 const MCSubtargetInfo
& /* unused */) override
{
97 Regions
.addInstruction(Inst
);
100 bool emitSymbolAttribute(MCSymbol
*Symbol
, MCSymbolAttr Attribute
) override
{
104 void emitCommonSymbol(MCSymbol
*Symbol
, uint64_t Size
,
105 Align ByteAlignment
) override
{}
106 void emitZerofill(MCSection
*Section
, MCSymbol
*Symbol
= nullptr,
107 uint64_t Size
= 0, Align ByteAlignment
= Align(1),
108 SMLoc Loc
= SMLoc()) override
{}
109 void emitGPRel32Value(const MCExpr
*Value
) override
{}
110 void beginCOFFSymbolDef(const MCSymbol
*Symbol
) override
{}
111 void emitCOFFSymbolStorageClass(int StorageClass
) override
{}
112 void emitCOFFSymbolType(int Type
) override
{}
113 void endCOFFSymbolDef() override
{}
115 ArrayRef
<MCInst
> GetInstructionSequence(unsigned Index
) const {
116 return Regions
.getInstructionSequence(Index
);
120 class InstrumentMCStreamer
: public MCStreamerWrapper
{
121 InstrumentManager
&IM
;
124 InstrumentMCStreamer(MCContext
&Context
, mca::InstrumentRegions
&R
,
125 InstrumentManager
&IM
)
126 : MCStreamerWrapper(Context
, R
), IM(IM
) {}
128 void emitInstruction(const MCInst
&Inst
,
129 const MCSubtargetInfo
&MCSI
) override
{
130 MCStreamerWrapper::emitInstruction(Inst
, MCSI
);
132 // We know that Regions is an InstrumentRegions by the constructor.
133 for (UniqueInstrument
&I
: IM
.createInstruments(Inst
)) {
134 StringRef InstrumentKind
= I
.get()->getDesc();
135 // End InstrumentType region if one is open
136 if (Regions
.isRegionActive(InstrumentKind
))
137 Regions
.endRegion(InstrumentKind
, Inst
.getLoc());
138 // Start new instrumentation region
139 Regions
.beginRegion(InstrumentKind
, Inst
.getLoc(), std::move(I
));
144 /// This abstract class is responsible for parsing the input given to
145 /// the llvm-mca driver, and converting that into a CodeRegions instance.
146 class CodeRegionGenerator
{
148 CodeRegionGenerator(const CodeRegionGenerator
&) = delete;
149 CodeRegionGenerator
&operator=(const CodeRegionGenerator
&) = delete;
150 virtual Expected
<const CodeRegions
&>
151 parseCodeRegions(const std::unique_ptr
<MCInstPrinter
> &IP
) = 0;
154 CodeRegionGenerator() {}
155 virtual ~CodeRegionGenerator();
158 /// Abastract CodeRegionGenerator with AnalysisRegions member
159 class AnalysisRegionGenerator
: public virtual CodeRegionGenerator
{
161 AnalysisRegions Regions
;
164 AnalysisRegionGenerator(llvm::SourceMgr
&SM
) : Regions(SM
) {}
166 virtual Expected
<const AnalysisRegions
&>
167 parseAnalysisRegions(const std::unique_ptr
<MCInstPrinter
> &IP
) = 0;
170 /// Abstract CodeRegionGenerator with InstrumentRegionsRegions member
171 class InstrumentRegionGenerator
: public virtual CodeRegionGenerator
{
173 InstrumentRegions Regions
;
176 InstrumentRegionGenerator(llvm::SourceMgr
&SM
) : Regions(SM
) {}
178 virtual Expected
<const InstrumentRegions
&>
179 parseInstrumentRegions(const std::unique_ptr
<MCInstPrinter
> &IP
) = 0;
182 /// This abstract class is responsible for parsing input ASM and
183 /// generating a CodeRegions instance.
184 class AsmCodeRegionGenerator
: public virtual CodeRegionGenerator
{
185 const Target
&TheTarget
;
186 const MCAsmInfo
&MAI
;
187 const MCSubtargetInfo
&STI
;
188 const MCInstrInfo
&MCII
;
189 unsigned AssemblerDialect
; // This is set during parsing.
195 AsmCodeRegionGenerator(const Target
&T
, MCContext
&C
, const MCAsmInfo
&A
,
196 const MCSubtargetInfo
&S
, const MCInstrInfo
&I
)
197 : TheTarget(T
), MAI(A
), STI(S
), MCII(I
), AssemblerDialect(0), Ctx(C
) {}
199 virtual MCACommentConsumer
*getCommentConsumer() = 0;
200 virtual CodeRegions
&getRegions() = 0;
201 virtual MCStreamerWrapper
*getMCStreamer() = 0;
203 unsigned getAssemblerDialect() const { return AssemblerDialect
; }
204 Expected
<const CodeRegions
&>
205 parseCodeRegions(const std::unique_ptr
<MCInstPrinter
> &IP
) override
;
208 class AsmAnalysisRegionGenerator final
: public AnalysisRegionGenerator
,
209 public AsmCodeRegionGenerator
{
210 AnalysisRegionCommentConsumer CC
;
211 MCStreamerWrapper Streamer
;
214 AsmAnalysisRegionGenerator(const Target
&T
, llvm::SourceMgr
&SM
, MCContext
&C
,
215 const MCAsmInfo
&A
, const MCSubtargetInfo
&S
,
216 const MCInstrInfo
&I
)
217 : AnalysisRegionGenerator(SM
), AsmCodeRegionGenerator(T
, C
, A
, S
, I
),
218 CC(Regions
), Streamer(Ctx
, Regions
) {}
220 MCACommentConsumer
*getCommentConsumer() override
{ return &CC
; };
221 CodeRegions
&getRegions() override
{ return Regions
; };
222 MCStreamerWrapper
*getMCStreamer() override
{ return &Streamer
; }
224 Expected
<const AnalysisRegions
&>
225 parseAnalysisRegions(const std::unique_ptr
<MCInstPrinter
> &IP
) override
{
226 Expected
<const CodeRegions
&> RegionsOrErr
= parseCodeRegions(IP
);
228 return RegionsOrErr
.takeError();
230 return static_cast<const AnalysisRegions
&>(*RegionsOrErr
);
233 Expected
<const CodeRegions
&>
234 parseCodeRegions(const std::unique_ptr
<MCInstPrinter
> &IP
) override
{
235 return AsmCodeRegionGenerator::parseCodeRegions(IP
);
239 class AsmInstrumentRegionGenerator final
: public InstrumentRegionGenerator
,
240 public AsmCodeRegionGenerator
{
241 InstrumentRegionCommentConsumer CC
;
242 InstrumentMCStreamer Streamer
;
245 AsmInstrumentRegionGenerator(const Target
&T
, llvm::SourceMgr
&SM
,
246 MCContext
&C
, const MCAsmInfo
&A
,
247 const MCSubtargetInfo
&S
, const MCInstrInfo
&I
,
248 InstrumentManager
&IM
)
249 : InstrumentRegionGenerator(SM
), AsmCodeRegionGenerator(T
, C
, A
, S
, I
),
250 CC(SM
, Regions
, IM
), Streamer(Ctx
, Regions
, IM
) {}
252 MCACommentConsumer
*getCommentConsumer() override
{ return &CC
; };
253 CodeRegions
&getRegions() override
{ return Regions
; };
254 MCStreamerWrapper
*getMCStreamer() override
{ return &Streamer
; }
256 Expected
<const InstrumentRegions
&>
257 parseInstrumentRegions(const std::unique_ptr
<MCInstPrinter
> &IP
) override
{
258 Expected
<const CodeRegions
&> RegionsOrErr
= parseCodeRegions(IP
);
260 return RegionsOrErr
.takeError();
262 return static_cast<const InstrumentRegions
&>(*RegionsOrErr
);
265 Expected
<const CodeRegions
&>
266 parseCodeRegions(const std::unique_ptr
<MCInstPrinter
> &IP
) override
{
267 return AsmCodeRegionGenerator::parseCodeRegions(IP
);
274 #endif // LLVM_TOOLS_LLVM_MCA_CODEREGION_GENERATOR_H