284 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8/// \file9///10/// This file declares classes responsible for generating llvm-mca11/// 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_H17#define LLVM_TOOLS_LLVM_MCA_CODEREGION_GENERATOR_H18 19#include "CodeRegion.h"20#include "llvm/MC/MCAsmInfo.h"21#include "llvm/MC/MCContext.h"22#include "llvm/MC/MCParser/AsmLexer.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"29#include <memory>30 31namespace llvm {32namespace mca {33 34class MCACommentConsumer : public AsmCommentConsumer {35protected:36 bool FoundError = false;37 38public:39 MCACommentConsumer() = default;40 41 bool hadErr() const { return FoundError; }42};43 44/// A comment consumer that parses strings. The only valid tokens are strings.45class AnalysisRegionCommentConsumer : public MCACommentConsumer {46 AnalysisRegions &Regions;47 48public:49 AnalysisRegionCommentConsumer(AnalysisRegions &R) : Regions(R) {}50 51 /// Parses a comment. It begins a new region if it is of the form52 /// 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 form54 /// LLVM-MCA-BEGIN <name> or LLVM-MCA-END <name>. Subregions are55 /// permitted, but a region that begins while another region is active56 /// must be ended before the outer region is ended. If thre is only one57 /// active region, LLVM-MCA-END does not need to provide a name.58 void HandleComment(SMLoc Loc, StringRef CommentText) override;59};60 61/// A comment consumer that parses strings to create InstrumentRegions.62/// The only valid tokens are strings.63class InstrumentRegionCommentConsumer : public MCACommentConsumer {64 llvm::SourceMgr &SM;65 66 InstrumentRegions &Regions;67 68 InstrumentManager &IM;69 70public:71 InstrumentRegionCommentConsumer(llvm::SourceMgr &SM, InstrumentRegions &R,72 InstrumentManager &IM)73 : SM(SM), Regions(R), IM(IM) {}74 75 /// Parses a comment. It begins a new region if it is of the form76 /// LLVM-MCA-<INSTRUMENTATION_TYPE> <data> where INSTRUMENTATION_TYPE77 /// is a valid InstrumentKind. If there is already an active78 /// region of type INSTRUMENATION_TYPE, then it will end the active79 /// one and begin a new one using the new data.80 void HandleComment(SMLoc Loc, StringRef CommentText) override;81 82 InstrumentManager &getInstrumentManager() { return IM; }83};84 85// This class provides the callbacks that occur when parsing input assembly.86class MCStreamerWrapper : public MCStreamer {87protected:88 CodeRegions &Regions;89 90public:91 MCStreamerWrapper(MCContext &Context, mca::CodeRegions &R)92 : MCStreamer(Context), Regions(R) {}93 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);98 }99 100 bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {101 return true;102 }103 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 beginCOFFSymbolDef(const MCSymbol *Symbol) override {}110 void emitCOFFSymbolStorageClass(int StorageClass) override {}111 void emitCOFFSymbolType(int Type) override {}112 void endCOFFSymbolDef() override {}113 114 ArrayRef<MCInst> GetInstructionSequence(unsigned Index) const {115 return Regions.getInstructionSequence(Index);116 }117};118 119class InstrumentMCStreamer : public MCStreamerWrapper {120 InstrumentManager &IM;121 122public:123 InstrumentMCStreamer(MCContext &Context, mca::InstrumentRegions &R,124 InstrumentManager &IM)125 : MCStreamerWrapper(Context, R), IM(IM) {}126 127 void emitInstruction(const MCInst &Inst,128 const MCSubtargetInfo &MCSI) override {129 MCStreamerWrapper::emitInstruction(Inst, MCSI);130 131 // We know that Regions is an InstrumentRegions by the constructor.132 for (UniqueInstrument &I : IM.createInstruments(Inst)) {133 StringRef InstrumentKind = I.get()->getDesc();134 // End InstrumentType region if one is open135 if (Regions.isRegionActive(InstrumentKind))136 Regions.endRegion(InstrumentKind, Inst.getLoc());137 // Start new instrumentation region138 Regions.beginRegion(InstrumentKind, Inst.getLoc(), std::move(I));139 }140 }141};142 143/// This abstract class is responsible for parsing the input given to144/// the llvm-mca driver, and converting that into a CodeRegions instance.145class CodeRegionGenerator {146protected:147 CodeRegionGenerator(const CodeRegionGenerator &) = delete;148 CodeRegionGenerator &operator=(const CodeRegionGenerator &) = delete;149 virtual Expected<const CodeRegions &>150 parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP,151 bool SkipFailures) = 0;152 153public:154 CodeRegionGenerator() = default;155 virtual ~CodeRegionGenerator();156};157 158/// Abastract CodeRegionGenerator with AnalysisRegions member159class AnalysisRegionGenerator : public virtual CodeRegionGenerator {160protected:161 AnalysisRegions Regions;162 163public:164 AnalysisRegionGenerator(llvm::SourceMgr &SM) : Regions(SM) {}165 166 virtual Expected<const AnalysisRegions &>167 parseAnalysisRegions(const std::unique_ptr<MCInstPrinter> &IP,168 bool SkipFailures) = 0;169};170 171/// Abstract CodeRegionGenerator with InstrumentRegionsRegions member172class InstrumentRegionGenerator : public virtual CodeRegionGenerator {173protected:174 InstrumentRegions Regions;175 176public:177 InstrumentRegionGenerator(llvm::SourceMgr &SM) : Regions(SM) {}178 179 virtual Expected<const InstrumentRegions &>180 parseInstrumentRegions(const std::unique_ptr<MCInstPrinter> &IP,181 bool SkipFailures) = 0;182};183 184/// This abstract class is responsible for parsing input ASM and185/// generating a CodeRegions instance.186class AsmCodeRegionGenerator : public virtual CodeRegionGenerator {187 const Target &TheTarget;188 const MCAsmInfo &MAI;189 const MCSubtargetInfo &STI;190 const MCInstrInfo &MCII;191 unsigned AssemblerDialect; // This is set during parsing.192 193protected:194 MCContext &Ctx;195 196public:197 AsmCodeRegionGenerator(const Target &T, MCContext &C, const MCAsmInfo &A,198 const MCSubtargetInfo &S, const MCInstrInfo &I)199 : TheTarget(T), MAI(A), STI(S), MCII(I), AssemblerDialect(0), Ctx(C) {}200 201 virtual MCACommentConsumer *getCommentConsumer() = 0;202 virtual CodeRegions &getRegions() = 0;203 virtual MCStreamerWrapper *getMCStreamer() = 0;204 205 unsigned getAssemblerDialect() const { return AssemblerDialect; }206 Expected<const CodeRegions &>207 parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP,208 bool SkipFailures) override;209};210 211class AsmAnalysisRegionGenerator final : public AnalysisRegionGenerator,212 public AsmCodeRegionGenerator {213 AnalysisRegionCommentConsumer CC;214 MCStreamerWrapper Streamer;215 216public:217 AsmAnalysisRegionGenerator(const Target &T, llvm::SourceMgr &SM, MCContext &C,218 const MCAsmInfo &A, const MCSubtargetInfo &S,219 const MCInstrInfo &I)220 : AnalysisRegionGenerator(SM), AsmCodeRegionGenerator(T, C, A, S, I),221 CC(Regions), Streamer(Ctx, Regions) {}222 223 MCACommentConsumer *getCommentConsumer() override { return &CC; };224 CodeRegions &getRegions() override { return Regions; };225 MCStreamerWrapper *getMCStreamer() override { return &Streamer; }226 227 Expected<const AnalysisRegions &>228 parseAnalysisRegions(const std::unique_ptr<MCInstPrinter> &IP,229 bool SkipFailures) override {230 Expected<const CodeRegions &> RegionsOrErr =231 parseCodeRegions(IP, SkipFailures);232 if (!RegionsOrErr)233 return RegionsOrErr.takeError();234 else235 return static_cast<const AnalysisRegions &>(*RegionsOrErr);236 }237 238 Expected<const CodeRegions &>239 parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP,240 bool SkipFailures) override {241 return AsmCodeRegionGenerator::parseCodeRegions(IP, SkipFailures);242 }243};244 245class AsmInstrumentRegionGenerator final : public InstrumentRegionGenerator,246 public AsmCodeRegionGenerator {247 InstrumentRegionCommentConsumer CC;248 InstrumentMCStreamer Streamer;249 250public:251 AsmInstrumentRegionGenerator(const Target &T, llvm::SourceMgr &SM,252 MCContext &C, const MCAsmInfo &A,253 const MCSubtargetInfo &S, const MCInstrInfo &I,254 InstrumentManager &IM)255 : InstrumentRegionGenerator(SM), AsmCodeRegionGenerator(T, C, A, S, I),256 CC(SM, Regions, IM), Streamer(Ctx, Regions, IM) {}257 258 MCACommentConsumer *getCommentConsumer() override { return &CC; };259 CodeRegions &getRegions() override { return Regions; };260 MCStreamerWrapper *getMCStreamer() override { return &Streamer; }261 262 Expected<const InstrumentRegions &>263 parseInstrumentRegions(const std::unique_ptr<MCInstPrinter> &IP,264 bool SkipFailures) override {265 Expected<const CodeRegions &> RegionsOrErr =266 parseCodeRegions(IP, SkipFailures);267 if (!RegionsOrErr)268 return RegionsOrErr.takeError();269 else270 return static_cast<const InstrumentRegions &>(*RegionsOrErr);271 }272 273 Expected<const CodeRegions &>274 parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP,275 bool SkipFailures) override {276 return AsmCodeRegionGenerator::parseCodeRegions(IP, SkipFailures);277 }278};279 280} // namespace mca281} // namespace llvm282 283#endif // LLVM_TOOLS_LLVM_MCA_CODEREGION_GENERATOR_H284