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 hadErr()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: AnalysisRegionCommentConsumer(AnalysisRegions & R)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: InstrumentRegionCommentConsumer(llvm::SourceMgr & SM,InstrumentRegions & R,InstrumentManager & IM)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 getInstrumentManager()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: MCStreamerWrapper(MCContext & Context,mca::CodeRegions & R)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. emitInstruction(const MCInst & Inst,const MCSubtargetInfo &)9506c3fb27SDimitry Andric void emitInstruction(const MCInst &Inst, 9606c3fb27SDimitry Andric const MCSubtargetInfo & /* unused */) override { 9706c3fb27SDimitry Andric Regions.addInstruction(Inst); 9806c3fb27SDimitry Andric } 9906c3fb27SDimitry Andric emitSymbolAttribute(MCSymbol * Symbol,MCSymbolAttr Attribute)10006c3fb27SDimitry Andric bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override { 10106c3fb27SDimitry Andric return true; 10206c3fb27SDimitry Andric } 10306c3fb27SDimitry Andric emitCommonSymbol(MCSymbol * Symbol,uint64_t Size,Align ByteAlignment)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 {} emitGPRel32Value(const MCExpr * Value)10906c3fb27SDimitry Andric void emitGPRel32Value(const MCExpr *Value) override {} beginCOFFSymbolDef(const MCSymbol * Symbol)11006c3fb27SDimitry Andric void beginCOFFSymbolDef(const MCSymbol *Symbol) override {} emitCOFFSymbolStorageClass(int StorageClass)11106c3fb27SDimitry Andric void emitCOFFSymbolStorageClass(int StorageClass) override {} emitCOFFSymbolType(int Type)11206c3fb27SDimitry Andric void emitCOFFSymbolType(int Type) override {} endCOFFSymbolDef()11306c3fb27SDimitry Andric void endCOFFSymbolDef() override {} 11406c3fb27SDimitry Andric GetInstructionSequence(unsigned Index)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: InstrumentMCStreamer(MCContext & Context,mca::InstrumentRegions & R,InstrumentManager & IM)12406c3fb27SDimitry Andric InstrumentMCStreamer(MCContext &Context, mca::InstrumentRegions &R, 12506c3fb27SDimitry Andric InstrumentManager &IM) 12606c3fb27SDimitry Andric : MCStreamerWrapper(Context, R), IM(IM) {} 12706c3fb27SDimitry Andric emitInstruction(const MCInst & Inst,const MCSubtargetInfo & MCSI)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 &> 151bdd1243dSDimitry Andric parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP) = 0; 152bdd1243dSDimitry Andric 153bdd1243dSDimitry Andric public: CodeRegionGenerator()154bdd1243dSDimitry Andric CodeRegionGenerator() {} 155bdd1243dSDimitry Andric virtual ~CodeRegionGenerator(); 156bdd1243dSDimitry Andric }; 157bdd1243dSDimitry Andric 158bdd1243dSDimitry Andric /// Abastract CodeRegionGenerator with AnalysisRegions member 159bdd1243dSDimitry Andric class AnalysisRegionGenerator : public virtual CodeRegionGenerator { 160bdd1243dSDimitry Andric protected: 161bdd1243dSDimitry Andric AnalysisRegions Regions; 162bdd1243dSDimitry Andric 163bdd1243dSDimitry Andric public: AnalysisRegionGenerator(llvm::SourceMgr & SM)164bdd1243dSDimitry Andric AnalysisRegionGenerator(llvm::SourceMgr &SM) : Regions(SM) {} 165bdd1243dSDimitry Andric 166bdd1243dSDimitry Andric virtual Expected<const AnalysisRegions &> 167bdd1243dSDimitry Andric parseAnalysisRegions(const std::unique_ptr<MCInstPrinter> &IP) = 0; 168bdd1243dSDimitry Andric }; 169bdd1243dSDimitry Andric 170bdd1243dSDimitry Andric /// Abstract CodeRegionGenerator with InstrumentRegionsRegions member 171bdd1243dSDimitry Andric class InstrumentRegionGenerator : public virtual CodeRegionGenerator { 172bdd1243dSDimitry Andric protected: 173bdd1243dSDimitry Andric InstrumentRegions Regions; 174bdd1243dSDimitry Andric 175bdd1243dSDimitry Andric public: InstrumentRegionGenerator(llvm::SourceMgr & SM)176bdd1243dSDimitry Andric InstrumentRegionGenerator(llvm::SourceMgr &SM) : Regions(SM) {} 177bdd1243dSDimitry Andric 178bdd1243dSDimitry Andric virtual Expected<const InstrumentRegions &> 179bdd1243dSDimitry Andric parseInstrumentRegions(const std::unique_ptr<MCInstPrinter> &IP) = 0; 180bdd1243dSDimitry Andric }; 181bdd1243dSDimitry Andric 182bdd1243dSDimitry Andric /// This abstract class is responsible for parsing input ASM and 183bdd1243dSDimitry Andric /// generating a CodeRegions instance. 184bdd1243dSDimitry Andric class AsmCodeRegionGenerator : public virtual CodeRegionGenerator { 1850b57cec5SDimitry Andric const Target &TheTarget; 1860b57cec5SDimitry Andric const MCAsmInfo &MAI; 1870b57cec5SDimitry Andric const MCSubtargetInfo &STI; 1880b57cec5SDimitry Andric const MCInstrInfo &MCII; 1890b57cec5SDimitry Andric unsigned AssemblerDialect; // This is set during parsing. 1900b57cec5SDimitry Andric 19106c3fb27SDimitry Andric protected: 19206c3fb27SDimitry Andric MCContext &Ctx; 19306c3fb27SDimitry Andric 1940b57cec5SDimitry Andric public: AsmCodeRegionGenerator(const Target & T,MCContext & C,const MCAsmInfo & A,const MCSubtargetInfo & S,const MCInstrInfo & I)195bdd1243dSDimitry Andric AsmCodeRegionGenerator(const Target &T, MCContext &C, const MCAsmInfo &A, 196bdd1243dSDimitry Andric const MCSubtargetInfo &S, const MCInstrInfo &I) 19706c3fb27SDimitry Andric : TheTarget(T), MAI(A), STI(S), MCII(I), AssemblerDialect(0), Ctx(C) {} 198bdd1243dSDimitry Andric 199bdd1243dSDimitry Andric virtual MCACommentConsumer *getCommentConsumer() = 0; 200bdd1243dSDimitry Andric virtual CodeRegions &getRegions() = 0; 20106c3fb27SDimitry Andric virtual MCStreamerWrapper *getMCStreamer() = 0; 2020b57cec5SDimitry Andric getAssemblerDialect()2030b57cec5SDimitry Andric unsigned getAssemblerDialect() const { return AssemblerDialect; } 204fe6060f1SDimitry Andric Expected<const CodeRegions &> 205fe6060f1SDimitry Andric parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP) override; 2060b57cec5SDimitry Andric }; 2070b57cec5SDimitry Andric 208bdd1243dSDimitry Andric class AsmAnalysisRegionGenerator final : public AnalysisRegionGenerator, 209bdd1243dSDimitry Andric public AsmCodeRegionGenerator { 210bdd1243dSDimitry Andric AnalysisRegionCommentConsumer CC; 21106c3fb27SDimitry Andric MCStreamerWrapper Streamer; 212bdd1243dSDimitry Andric 213bdd1243dSDimitry Andric public: AsmAnalysisRegionGenerator(const Target & T,llvm::SourceMgr & SM,MCContext & C,const MCAsmInfo & A,const MCSubtargetInfo & S,const MCInstrInfo & I)214bdd1243dSDimitry Andric AsmAnalysisRegionGenerator(const Target &T, llvm::SourceMgr &SM, MCContext &C, 215bdd1243dSDimitry Andric const MCAsmInfo &A, const MCSubtargetInfo &S, 216bdd1243dSDimitry Andric const MCInstrInfo &I) 217bdd1243dSDimitry Andric : AnalysisRegionGenerator(SM), AsmCodeRegionGenerator(T, C, A, S, I), 21806c3fb27SDimitry Andric CC(Regions), Streamer(Ctx, Regions) {} 219bdd1243dSDimitry Andric getCommentConsumer()220bdd1243dSDimitry Andric MCACommentConsumer *getCommentConsumer() override { return &CC; }; getRegions()221bdd1243dSDimitry Andric CodeRegions &getRegions() override { return Regions; }; getMCStreamer()22206c3fb27SDimitry Andric MCStreamerWrapper *getMCStreamer() override { return &Streamer; } 223bdd1243dSDimitry Andric 224bdd1243dSDimitry Andric Expected<const AnalysisRegions &> parseAnalysisRegions(const std::unique_ptr<MCInstPrinter> & IP)225bdd1243dSDimitry Andric parseAnalysisRegions(const std::unique_ptr<MCInstPrinter> &IP) override { 226bdd1243dSDimitry Andric Expected<const CodeRegions &> RegionsOrErr = parseCodeRegions(IP); 227bdd1243dSDimitry Andric if (!RegionsOrErr) 228bdd1243dSDimitry Andric return RegionsOrErr.takeError(); 229bdd1243dSDimitry Andric else 230bdd1243dSDimitry Andric return static_cast<const AnalysisRegions &>(*RegionsOrErr); 231bdd1243dSDimitry Andric } 232bdd1243dSDimitry Andric 233bdd1243dSDimitry Andric Expected<const CodeRegions &> parseCodeRegions(const std::unique_ptr<MCInstPrinter> & IP)234bdd1243dSDimitry Andric parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP) override { 235bdd1243dSDimitry Andric return AsmCodeRegionGenerator::parseCodeRegions(IP); 236bdd1243dSDimitry Andric } 237bdd1243dSDimitry Andric }; 238bdd1243dSDimitry Andric 239bdd1243dSDimitry Andric class AsmInstrumentRegionGenerator final : public InstrumentRegionGenerator, 240bdd1243dSDimitry Andric public AsmCodeRegionGenerator { 241bdd1243dSDimitry Andric InstrumentRegionCommentConsumer CC; 24206c3fb27SDimitry Andric InstrumentMCStreamer Streamer; 243bdd1243dSDimitry Andric 244bdd1243dSDimitry Andric public: AsmInstrumentRegionGenerator(const Target & T,llvm::SourceMgr & SM,MCContext & C,const MCAsmInfo & A,const MCSubtargetInfo & S,const MCInstrInfo & I,InstrumentManager & IM)245bdd1243dSDimitry Andric AsmInstrumentRegionGenerator(const Target &T, llvm::SourceMgr &SM, 246bdd1243dSDimitry Andric MCContext &C, const MCAsmInfo &A, 247bdd1243dSDimitry Andric const MCSubtargetInfo &S, const MCInstrInfo &I, 248bdd1243dSDimitry Andric InstrumentManager &IM) 249bdd1243dSDimitry Andric : InstrumentRegionGenerator(SM), AsmCodeRegionGenerator(T, C, A, S, I), 25006c3fb27SDimitry Andric CC(SM, Regions, IM), Streamer(Ctx, Regions, IM) {} 251bdd1243dSDimitry Andric getCommentConsumer()252bdd1243dSDimitry Andric MCACommentConsumer *getCommentConsumer() override { return &CC; }; getRegions()253bdd1243dSDimitry Andric CodeRegions &getRegions() override { return Regions; }; getMCStreamer()25406c3fb27SDimitry Andric MCStreamerWrapper *getMCStreamer() override { return &Streamer; } 255bdd1243dSDimitry Andric 256bdd1243dSDimitry Andric Expected<const InstrumentRegions &> parseInstrumentRegions(const std::unique_ptr<MCInstPrinter> & IP)257bdd1243dSDimitry Andric parseInstrumentRegions(const std::unique_ptr<MCInstPrinter> &IP) override { 258bdd1243dSDimitry Andric Expected<const CodeRegions &> RegionsOrErr = parseCodeRegions(IP); 259bdd1243dSDimitry Andric if (!RegionsOrErr) 260bdd1243dSDimitry Andric return RegionsOrErr.takeError(); 261bdd1243dSDimitry Andric else 262bdd1243dSDimitry Andric return static_cast<const InstrumentRegions &>(*RegionsOrErr); 263bdd1243dSDimitry Andric } 264bdd1243dSDimitry Andric 265bdd1243dSDimitry Andric Expected<const CodeRegions &> parseCodeRegions(const std::unique_ptr<MCInstPrinter> & IP)266bdd1243dSDimitry Andric parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP) override { 267bdd1243dSDimitry Andric return AsmCodeRegionGenerator::parseCodeRegions(IP); 268bdd1243dSDimitry Andric } 269bdd1243dSDimitry Andric }; 270bdd1243dSDimitry Andric 2710b57cec5SDimitry Andric } // namespace mca 2720b57cec5SDimitry Andric } // namespace llvm 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric #endif // LLVM_TOOLS_LLVM_MCA_CODEREGION_GENERATOR_H 275