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