Path: blob/main/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.h
35258 views
//===----------------------- CodeRegionGenerator.h --------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7/// \file8///9/// This file declares classes responsible for generating llvm-mca10/// CodeRegions from various types of input. llvm-mca only analyzes CodeRegions,11/// so the classes here provide the input-to-CodeRegions translation.12//13//===----------------------------------------------------------------------===//1415#ifndef LLVM_TOOLS_LLVM_MCA_CODEREGION_GENERATOR_H16#define LLVM_TOOLS_LLVM_MCA_CODEREGION_GENERATOR_H1718#include "CodeRegion.h"19#include "llvm/MC/MCAsmInfo.h"20#include "llvm/MC/MCContext.h"21#include "llvm/MC/MCParser/MCAsmLexer.h"22#include "llvm/MC/MCStreamer.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>2930namespace llvm {31namespace mca {3233class MCACommentConsumer : public AsmCommentConsumer {34protected:35bool FoundError = false;3637public:38MCACommentConsumer() = default;3940bool hadErr() const { return FoundError; }41};4243/// A comment consumer that parses strings. The only valid tokens are strings.44class AnalysisRegionCommentConsumer : public MCACommentConsumer {45AnalysisRegions &Regions;4647public:48AnalysisRegionCommentConsumer(AnalysisRegions &R) : Regions(R) {}4950/// Parses a comment. It begins a new region if it is of the form51/// 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 form53/// LLVM-MCA-BEGIN <name> or LLVM-MCA-END <name>. Subregions are54/// permitted, but a region that begins while another region is active55/// must be ended before the outer region is ended. If thre is only one56/// active region, LLVM-MCA-END does not need to provide a name.57void HandleComment(SMLoc Loc, StringRef CommentText) override;58};5960/// A comment consumer that parses strings to create InstrumentRegions.61/// The only valid tokens are strings.62class InstrumentRegionCommentConsumer : public MCACommentConsumer {63llvm::SourceMgr &SM;6465InstrumentRegions &Regions;6667InstrumentManager &IM;6869public:70InstrumentRegionCommentConsumer(llvm::SourceMgr &SM, InstrumentRegions &R,71InstrumentManager &IM)72: SM(SM), Regions(R), IM(IM) {}7374/// Parses a comment. It begins a new region if it is of the form75/// LLVM-MCA-<INSTRUMENTATION_TYPE> <data> where INSTRUMENTATION_TYPE76/// is a valid InstrumentKind. If there is already an active77/// region of type INSTRUMENATION_TYPE, then it will end the active78/// one and begin a new one using the new data.79void HandleComment(SMLoc Loc, StringRef CommentText) override;8081InstrumentManager &getInstrumentManager() { return IM; }82};8384// This class provides the callbacks that occur when parsing input assembly.85class MCStreamerWrapper : public MCStreamer {86protected:87CodeRegions &Regions;8889public:90MCStreamerWrapper(MCContext &Context, mca::CodeRegions &R)91: MCStreamer(Context), Regions(R) {}9293// We only want to intercept the emission of new instructions.94void emitInstruction(const MCInst &Inst,95const MCSubtargetInfo & /* unused */) override {96Regions.addInstruction(Inst);97}9899bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {100return true;101}102103void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,104Align ByteAlignment) override {}105void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,106uint64_t Size = 0, Align ByteAlignment = Align(1),107SMLoc Loc = SMLoc()) override {}108void emitGPRel32Value(const MCExpr *Value) override {}109void beginCOFFSymbolDef(const MCSymbol *Symbol) override {}110void emitCOFFSymbolStorageClass(int StorageClass) override {}111void emitCOFFSymbolType(int Type) override {}112void endCOFFSymbolDef() override {}113114ArrayRef<MCInst> GetInstructionSequence(unsigned Index) const {115return Regions.getInstructionSequence(Index);116}117};118119class InstrumentMCStreamer : public MCStreamerWrapper {120InstrumentManager &IM;121122public:123InstrumentMCStreamer(MCContext &Context, mca::InstrumentRegions &R,124InstrumentManager &IM)125: MCStreamerWrapper(Context, R), IM(IM) {}126127void emitInstruction(const MCInst &Inst,128const MCSubtargetInfo &MCSI) override {129MCStreamerWrapper::emitInstruction(Inst, MCSI);130131// We know that Regions is an InstrumentRegions by the constructor.132for (UniqueInstrument &I : IM.createInstruments(Inst)) {133StringRef InstrumentKind = I.get()->getDesc();134// End InstrumentType region if one is open135if (Regions.isRegionActive(InstrumentKind))136Regions.endRegion(InstrumentKind, Inst.getLoc());137// Start new instrumentation region138Regions.beginRegion(InstrumentKind, Inst.getLoc(), std::move(I));139}140}141};142143/// 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:147CodeRegionGenerator(const CodeRegionGenerator &) = delete;148CodeRegionGenerator &operator=(const CodeRegionGenerator &) = delete;149virtual Expected<const CodeRegions &>150parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP,151bool SkipFailures) = 0;152153public:154CodeRegionGenerator() {}155virtual ~CodeRegionGenerator();156};157158/// Abastract CodeRegionGenerator with AnalysisRegions member159class AnalysisRegionGenerator : public virtual CodeRegionGenerator {160protected:161AnalysisRegions Regions;162163public:164AnalysisRegionGenerator(llvm::SourceMgr &SM) : Regions(SM) {}165166virtual Expected<const AnalysisRegions &>167parseAnalysisRegions(const std::unique_ptr<MCInstPrinter> &IP,168bool SkipFailures) = 0;169};170171/// Abstract CodeRegionGenerator with InstrumentRegionsRegions member172class InstrumentRegionGenerator : public virtual CodeRegionGenerator {173protected:174InstrumentRegions Regions;175176public:177InstrumentRegionGenerator(llvm::SourceMgr &SM) : Regions(SM) {}178179virtual Expected<const InstrumentRegions &>180parseInstrumentRegions(const std::unique_ptr<MCInstPrinter> &IP,181bool SkipFailures) = 0;182};183184/// This abstract class is responsible for parsing input ASM and185/// generating a CodeRegions instance.186class AsmCodeRegionGenerator : public virtual CodeRegionGenerator {187const Target &TheTarget;188const MCAsmInfo &MAI;189const MCSubtargetInfo &STI;190const MCInstrInfo &MCII;191unsigned AssemblerDialect; // This is set during parsing.192193protected:194MCContext &Ctx;195196public:197AsmCodeRegionGenerator(const Target &T, MCContext &C, const MCAsmInfo &A,198const MCSubtargetInfo &S, const MCInstrInfo &I)199: TheTarget(T), MAI(A), STI(S), MCII(I), AssemblerDialect(0), Ctx(C) {}200201virtual MCACommentConsumer *getCommentConsumer() = 0;202virtual CodeRegions &getRegions() = 0;203virtual MCStreamerWrapper *getMCStreamer() = 0;204205unsigned getAssemblerDialect() const { return AssemblerDialect; }206Expected<const CodeRegions &>207parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP,208bool SkipFailures) override;209};210211class AsmAnalysisRegionGenerator final : public AnalysisRegionGenerator,212public AsmCodeRegionGenerator {213AnalysisRegionCommentConsumer CC;214MCStreamerWrapper Streamer;215216public:217AsmAnalysisRegionGenerator(const Target &T, llvm::SourceMgr &SM, MCContext &C,218const MCAsmInfo &A, const MCSubtargetInfo &S,219const MCInstrInfo &I)220: AnalysisRegionGenerator(SM), AsmCodeRegionGenerator(T, C, A, S, I),221CC(Regions), Streamer(Ctx, Regions) {}222223MCACommentConsumer *getCommentConsumer() override { return &CC; };224CodeRegions &getRegions() override { return Regions; };225MCStreamerWrapper *getMCStreamer() override { return &Streamer; }226227Expected<const AnalysisRegions &>228parseAnalysisRegions(const std::unique_ptr<MCInstPrinter> &IP,229bool SkipFailures) override {230Expected<const CodeRegions &> RegionsOrErr =231parseCodeRegions(IP, SkipFailures);232if (!RegionsOrErr)233return RegionsOrErr.takeError();234else235return static_cast<const AnalysisRegions &>(*RegionsOrErr);236}237238Expected<const CodeRegions &>239parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP,240bool SkipFailures) override {241return AsmCodeRegionGenerator::parseCodeRegions(IP, SkipFailures);242}243};244245class AsmInstrumentRegionGenerator final : public InstrumentRegionGenerator,246public AsmCodeRegionGenerator {247InstrumentRegionCommentConsumer CC;248InstrumentMCStreamer Streamer;249250public:251AsmInstrumentRegionGenerator(const Target &T, llvm::SourceMgr &SM,252MCContext &C, const MCAsmInfo &A,253const MCSubtargetInfo &S, const MCInstrInfo &I,254InstrumentManager &IM)255: InstrumentRegionGenerator(SM), AsmCodeRegionGenerator(T, C, A, S, I),256CC(SM, Regions, IM), Streamer(Ctx, Regions, IM) {}257258MCACommentConsumer *getCommentConsumer() override { return &CC; };259CodeRegions &getRegions() override { return Regions; };260MCStreamerWrapper *getMCStreamer() override { return &Streamer; }261262Expected<const InstrumentRegions &>263parseInstrumentRegions(const std::unique_ptr<MCInstPrinter> &IP,264bool SkipFailures) override {265Expected<const CodeRegions &> RegionsOrErr =266parseCodeRegions(IP, SkipFailures);267if (!RegionsOrErr)268return RegionsOrErr.takeError();269else270return static_cast<const InstrumentRegions &>(*RegionsOrErr);271}272273Expected<const CodeRegions &>274parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP,275bool SkipFailures) override {276return AsmCodeRegionGenerator::parseCodeRegions(IP, SkipFailures);277}278};279280} // namespace mca281} // namespace llvm282283#endif // LLVM_TOOLS_LLVM_MCA_CODEREGION_GENERATOR_H284285286