1//===----------------------- CodeRegionGenerator.h --------------*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8/// \file
9///
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.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_TOOLS_LLVM_MCA_CODEREGION_GENERATOR_H
17#define LLVM_TOOLS_LLVM_MCA_CODEREGION_GENERATOR_H
18
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/MCSubtargetInfo.h"
24#include "llvm/MC/TargetRegistry.h"
25#include "llvm/MCA/CustomBehaviour.h"
26#include "llvm/Support/Error.h"
27#include "llvm/Support/SourceMgr.h"
28#include <memory>
29
30namespace llvm {
31namespace mca {
32
33class MCACommentConsumer : public AsmCommentConsumer {
34protected:
35  bool FoundError;
36
37public:
38  MCACommentConsumer() : FoundError(false) {}
39
40  bool hadErr() const { return FoundError; }
41};
42
43/// A comment consumer that parses strings.  The only valid tokens are strings.
44class AnalysisRegionCommentConsumer : public MCACommentConsumer {
45  AnalysisRegions &Regions;
46
47public:
48  AnalysisRegionCommentConsumer(AnalysisRegions &R) : Regions(R) {}
49
50  /// Parses a comment. It begins a new region if it is of the form
51  /// LLVM-MCA-BEGIN. It ends a region if it is of the form LLVM-MCA-END.
52  /// Regions can be optionally named if they are of the form
53  /// LLVM-MCA-BEGIN <name> or LLVM-MCA-END <name>. Subregions are
54  /// permitted, but a region that begins while another region is active
55  /// must be ended before the outer region is ended. If thre is only one
56  /// active region, LLVM-MCA-END does not need to provide a name.
57  void HandleComment(SMLoc Loc, StringRef CommentText) override;
58};
59
60/// A comment consumer that parses strings to create InstrumentRegions.
61/// The only valid tokens are strings.
62class InstrumentRegionCommentConsumer : public MCACommentConsumer {
63  llvm::SourceMgr &SM;
64
65  InstrumentRegions &Regions;
66
67  InstrumentManager &IM;
68
69public:
70  InstrumentRegionCommentConsumer(llvm::SourceMgr &SM, InstrumentRegions &R,
71                                  InstrumentManager &IM)
72      : SM(SM), Regions(R), IM(IM) {}
73
74  /// Parses a comment. It begins a new region if it is of the form
75  /// LLVM-MCA-<INSTRUMENTATION_TYPE> <data> where INSTRUMENTATION_TYPE
76  /// is a valid InstrumentKind. If there is already an active
77  /// region of type INSTRUMENATION_TYPE, then it will end the active
78  /// one and begin a new one using the new data.
79  void HandleComment(SMLoc Loc, StringRef CommentText) override;
80};
81
82/// This abstract class is responsible for parsing the input given to
83/// the llvm-mca driver, and converting that into a CodeRegions instance.
84class CodeRegionGenerator {
85protected:
86  CodeRegionGenerator(const CodeRegionGenerator &) = delete;
87  CodeRegionGenerator &operator=(const CodeRegionGenerator &) = delete;
88  virtual Expected<const CodeRegions &>
89  parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP) = 0;
90
91public:
92  CodeRegionGenerator() {}
93  virtual ~CodeRegionGenerator();
94};
95
96/// Abastract CodeRegionGenerator with AnalysisRegions member
97class AnalysisRegionGenerator : public virtual CodeRegionGenerator {
98protected:
99  AnalysisRegions Regions;
100
101public:
102  AnalysisRegionGenerator(llvm::SourceMgr &SM) : Regions(SM) {}
103
104  virtual Expected<const AnalysisRegions &>
105  parseAnalysisRegions(const std::unique_ptr<MCInstPrinter> &IP) = 0;
106};
107
108/// Abstract CodeRegionGenerator with InstrumentRegionsRegions member
109class InstrumentRegionGenerator : public virtual CodeRegionGenerator {
110protected:
111  InstrumentRegions Regions;
112
113public:
114  InstrumentRegionGenerator(llvm::SourceMgr &SM) : Regions(SM) {}
115
116  virtual Expected<const InstrumentRegions &>
117  parseInstrumentRegions(const std::unique_ptr<MCInstPrinter> &IP) = 0;
118};
119
120/// This abstract class is responsible for parsing input ASM and
121/// generating a CodeRegions instance.
122class AsmCodeRegionGenerator : public virtual CodeRegionGenerator {
123  const Target &TheTarget;
124  MCContext &Ctx;
125  const MCAsmInfo &MAI;
126  const MCSubtargetInfo &STI;
127  const MCInstrInfo &MCII;
128  unsigned AssemblerDialect; // This is set during parsing.
129
130public:
131  AsmCodeRegionGenerator(const Target &T, MCContext &C, const MCAsmInfo &A,
132                         const MCSubtargetInfo &S, const MCInstrInfo &I)
133      : TheTarget(T), Ctx(C), MAI(A), STI(S), MCII(I), AssemblerDialect(0) {}
134
135  virtual MCACommentConsumer *getCommentConsumer() = 0;
136  virtual CodeRegions &getRegions() = 0;
137
138  unsigned getAssemblerDialect() const { return AssemblerDialect; }
139  Expected<const CodeRegions &>
140  parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP) override;
141};
142
143class AsmAnalysisRegionGenerator final : public AnalysisRegionGenerator,
144                                         public AsmCodeRegionGenerator {
145  AnalysisRegionCommentConsumer CC;
146
147public:
148  AsmAnalysisRegionGenerator(const Target &T, llvm::SourceMgr &SM, MCContext &C,
149                             const MCAsmInfo &A, const MCSubtargetInfo &S,
150                             const MCInstrInfo &I)
151      : AnalysisRegionGenerator(SM), AsmCodeRegionGenerator(T, C, A, S, I),
152        CC(Regions) {}
153
154  MCACommentConsumer *getCommentConsumer() override { return &CC; };
155  CodeRegions &getRegions() override { return Regions; };
156
157  Expected<const AnalysisRegions &>
158  parseAnalysisRegions(const std::unique_ptr<MCInstPrinter> &IP) override {
159    Expected<const CodeRegions &> RegionsOrErr = parseCodeRegions(IP);
160    if (!RegionsOrErr)
161      return RegionsOrErr.takeError();
162    else
163      return static_cast<const AnalysisRegions &>(*RegionsOrErr);
164  }
165
166  Expected<const CodeRegions &>
167  parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP) override {
168    return AsmCodeRegionGenerator::parseCodeRegions(IP);
169  }
170};
171
172class AsmInstrumentRegionGenerator final : public InstrumentRegionGenerator,
173                                           public AsmCodeRegionGenerator {
174  InstrumentRegionCommentConsumer CC;
175
176public:
177  AsmInstrumentRegionGenerator(const Target &T, llvm::SourceMgr &SM,
178                               MCContext &C, const MCAsmInfo &A,
179                               const MCSubtargetInfo &S, const MCInstrInfo &I,
180                               InstrumentManager &IM)
181      : InstrumentRegionGenerator(SM), AsmCodeRegionGenerator(T, C, A, S, I),
182        CC(SM, Regions, IM) {}
183
184  MCACommentConsumer *getCommentConsumer() override { return &CC; };
185  CodeRegions &getRegions() override { return Regions; };
186
187  Expected<const InstrumentRegions &>
188  parseInstrumentRegions(const std::unique_ptr<MCInstPrinter> &IP) override {
189    Expected<const CodeRegions &> RegionsOrErr = parseCodeRegions(IP);
190    if (!RegionsOrErr)
191      return RegionsOrErr.takeError();
192    else
193      return static_cast<const InstrumentRegions &>(*RegionsOrErr);
194  }
195
196  Expected<const CodeRegions &>
197  parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP) override {
198    return AsmCodeRegionGenerator::parseCodeRegions(IP);
199  }
200};
201
202} // namespace mca
203} // namespace llvm
204
205#endif // LLVM_TOOLS_LLVM_MCA_CODEREGION_GENERATOR_H
206