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 30 namespace llvm { 31 namespace mca { 32 33 class MCACommentConsumer : public AsmCommentConsumer { 34 protected: 35 bool FoundError; 36 37 public: 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. 44 class AnalysisRegionCommentConsumer : public MCACommentConsumer { 45 AnalysisRegions &Regions; 46 47 public: 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. 62 class InstrumentRegionCommentConsumer : public MCACommentConsumer { 63 llvm::SourceMgr &SM; 64 65 InstrumentRegions &Regions; 66 67 InstrumentManager &IM; 68 69 public: 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. 84 class CodeRegionGenerator { 85 protected: 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 91 public: 92 CodeRegionGenerator() {} 93 virtual ~CodeRegionGenerator(); 94 }; 95 96 /// Abastract CodeRegionGenerator with AnalysisRegions member 97 class AnalysisRegionGenerator : public virtual CodeRegionGenerator { 98 protected: 99 AnalysisRegions Regions; 100 101 public: 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 109 class InstrumentRegionGenerator : public virtual CodeRegionGenerator { 110 protected: 111 InstrumentRegions Regions; 112 113 public: 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. 122 class 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 130 public: 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 143 class AsmAnalysisRegionGenerator final : public AnalysisRegionGenerator, 144 public AsmCodeRegionGenerator { 145 AnalysisRegionCommentConsumer CC; 146 147 public: 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 172 class AsmInstrumentRegionGenerator final : public InstrumentRegionGenerator, 173 public AsmCodeRegionGenerator { 174 InstrumentRegionCommentConsumer CC; 175 176 public: 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