1*b5893f02SDimitry Andric //===----------------------- CodeRegionGenerator.cpp ------------*- C++ -*-===//
2*b5893f02SDimitry Andric //
3*b5893f02SDimitry Andric // The LLVM Compiler Infrastructure
4*b5893f02SDimitry Andric //
5*b5893f02SDimitry Andric // This file is distributed under the University of Illinois Open Source
6*b5893f02SDimitry Andric // License. See LICENSE.TXT for details.
7*b5893f02SDimitry Andric //
8*b5893f02SDimitry Andric //===----------------------------------------------------------------------===//
9*b5893f02SDimitry Andric /// \file
10*b5893f02SDimitry Andric ///
11*b5893f02SDimitry Andric /// This file defines classes responsible for generating llvm-mca
12*b5893f02SDimitry Andric /// CodeRegions from various types of input. llvm-mca only analyzes CodeRegions,
13*b5893f02SDimitry Andric /// so the classes here provide the input-to-CodeRegions translation.
14*b5893f02SDimitry Andric //
15*b5893f02SDimitry Andric //===----------------------------------------------------------------------===//
16*b5893f02SDimitry Andric
17*b5893f02SDimitry Andric #include "CodeRegionGenerator.h"
18*b5893f02SDimitry Andric #include "llvm/ADT/ArrayRef.h"
19*b5893f02SDimitry Andric #include "llvm/ADT/StringRef.h"
20*b5893f02SDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h"
21*b5893f02SDimitry Andric #include "llvm/MC/MCStreamer.h"
22*b5893f02SDimitry Andric #include "llvm/MC/MCTargetOptions.h"
23*b5893f02SDimitry Andric #include "llvm/Support/Error.h"
24*b5893f02SDimitry Andric #include "llvm/Support/SMLoc.h"
25*b5893f02SDimitry Andric #include <memory>
26*b5893f02SDimitry Andric
27*b5893f02SDimitry Andric namespace llvm {
28*b5893f02SDimitry Andric namespace mca {
29*b5893f02SDimitry Andric
30*b5893f02SDimitry Andric // This virtual dtor serves as the anchor for the CodeRegionGenerator class.
~CodeRegionGenerator()31*b5893f02SDimitry Andric CodeRegionGenerator::~CodeRegionGenerator() {}
32*b5893f02SDimitry Andric
33*b5893f02SDimitry Andric // A comment consumer that parses strings. The only valid tokens are strings.
34*b5893f02SDimitry Andric class MCACommentConsumer : public AsmCommentConsumer {
35*b5893f02SDimitry Andric public:
36*b5893f02SDimitry Andric CodeRegions &Regions;
37*b5893f02SDimitry Andric
MCACommentConsumer(CodeRegions & R)38*b5893f02SDimitry Andric MCACommentConsumer(CodeRegions &R) : Regions(R) {}
39*b5893f02SDimitry Andric void HandleComment(SMLoc Loc, StringRef CommentText) override;
40*b5893f02SDimitry Andric };
41*b5893f02SDimitry Andric
42*b5893f02SDimitry Andric // This class provides the callbacks that occur when parsing input assembly.
43*b5893f02SDimitry Andric class MCStreamerWrapper final : public MCStreamer {
44*b5893f02SDimitry Andric CodeRegions &Regions;
45*b5893f02SDimitry Andric
46*b5893f02SDimitry Andric public:
MCStreamerWrapper(MCContext & Context,mca::CodeRegions & R)47*b5893f02SDimitry Andric MCStreamerWrapper(MCContext &Context, mca::CodeRegions &R)
48*b5893f02SDimitry Andric : MCStreamer(Context), Regions(R) {}
49*b5893f02SDimitry Andric
50*b5893f02SDimitry Andric // We only want to intercept the emission of new instructions.
EmitInstruction(const MCInst & Inst,const MCSubtargetInfo &,bool)51*b5893f02SDimitry Andric virtual void EmitInstruction(const MCInst &Inst,
52*b5893f02SDimitry Andric const MCSubtargetInfo & /* unused */,
53*b5893f02SDimitry Andric bool /* unused */) override {
54*b5893f02SDimitry Andric Regions.addInstruction(Inst);
55*b5893f02SDimitry Andric }
56*b5893f02SDimitry Andric
EmitSymbolAttribute(MCSymbol * Symbol,MCSymbolAttr Attribute)57*b5893f02SDimitry Andric bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {
58*b5893f02SDimitry Andric return true;
59*b5893f02SDimitry Andric }
60*b5893f02SDimitry Andric
EmitCommonSymbol(MCSymbol * Symbol,uint64_t Size,unsigned ByteAlignment)61*b5893f02SDimitry Andric void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
62*b5893f02SDimitry Andric unsigned ByteAlignment) override {}
EmitZerofill(MCSection * Section,MCSymbol * Symbol=nullptr,uint64_t Size=0,unsigned ByteAlignment=0,SMLoc Loc=SMLoc ())63*b5893f02SDimitry Andric void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
64*b5893f02SDimitry Andric uint64_t Size = 0, unsigned ByteAlignment = 0,
65*b5893f02SDimitry Andric SMLoc Loc = SMLoc()) override {}
EmitGPRel32Value(const MCExpr * Value)66*b5893f02SDimitry Andric void EmitGPRel32Value(const MCExpr *Value) override {}
BeginCOFFSymbolDef(const MCSymbol * Symbol)67*b5893f02SDimitry Andric void BeginCOFFSymbolDef(const MCSymbol *Symbol) override {}
EmitCOFFSymbolStorageClass(int StorageClass)68*b5893f02SDimitry Andric void EmitCOFFSymbolStorageClass(int StorageClass) override {}
EmitCOFFSymbolType(int Type)69*b5893f02SDimitry Andric void EmitCOFFSymbolType(int Type) override {}
EndCOFFSymbolDef()70*b5893f02SDimitry Andric void EndCOFFSymbolDef() override {}
71*b5893f02SDimitry Andric
GetInstructionSequence(unsigned Index) const72*b5893f02SDimitry Andric ArrayRef<MCInst> GetInstructionSequence(unsigned Index) const {
73*b5893f02SDimitry Andric return Regions.getInstructionSequence(Index);
74*b5893f02SDimitry Andric }
75*b5893f02SDimitry Andric };
76*b5893f02SDimitry Andric
HandleComment(SMLoc Loc,StringRef CommentText)77*b5893f02SDimitry Andric void MCACommentConsumer::HandleComment(SMLoc Loc, StringRef CommentText) {
78*b5893f02SDimitry Andric // Skip empty comments.
79*b5893f02SDimitry Andric StringRef Comment(CommentText);
80*b5893f02SDimitry Andric if (Comment.empty())
81*b5893f02SDimitry Andric return;
82*b5893f02SDimitry Andric
83*b5893f02SDimitry Andric // Skip spaces and tabs.
84*b5893f02SDimitry Andric unsigned Position = Comment.find_first_not_of(" \t");
85*b5893f02SDimitry Andric if (Position >= Comment.size())
86*b5893f02SDimitry Andric // We reached the end of the comment. Bail out.
87*b5893f02SDimitry Andric return;
88*b5893f02SDimitry Andric
89*b5893f02SDimitry Andric Comment = Comment.drop_front(Position);
90*b5893f02SDimitry Andric if (Comment.consume_front("LLVM-MCA-END")) {
91*b5893f02SDimitry Andric Regions.endRegion(Loc);
92*b5893f02SDimitry Andric return;
93*b5893f02SDimitry Andric }
94*b5893f02SDimitry Andric
95*b5893f02SDimitry Andric // Try to parse the LLVM-MCA-BEGIN comment.
96*b5893f02SDimitry Andric if (!Comment.consume_front("LLVM-MCA-BEGIN"))
97*b5893f02SDimitry Andric return;
98*b5893f02SDimitry Andric
99*b5893f02SDimitry Andric // Skip spaces and tabs.
100*b5893f02SDimitry Andric Position = Comment.find_first_not_of(" \t");
101*b5893f02SDimitry Andric if (Position < Comment.size())
102*b5893f02SDimitry Andric Comment = Comment.drop_front(Position);
103*b5893f02SDimitry Andric // Use the rest of the string as a descriptor for this code snippet.
104*b5893f02SDimitry Andric Regions.beginRegion(Comment, Loc);
105*b5893f02SDimitry Andric }
106*b5893f02SDimitry Andric
parseCodeRegions()107*b5893f02SDimitry Andric Expected<const CodeRegions &> AsmCodeRegionGenerator::parseCodeRegions() {
108*b5893f02SDimitry Andric MCTargetOptions Opts;
109*b5893f02SDimitry Andric Opts.PreserveAsmComments = false;
110*b5893f02SDimitry Andric MCStreamerWrapper Str(Ctx, Regions);
111*b5893f02SDimitry Andric
112*b5893f02SDimitry Andric // Create a MCAsmParser and setup the lexer to recognize llvm-mca ASM
113*b5893f02SDimitry Andric // comments.
114*b5893f02SDimitry Andric std::unique_ptr<MCAsmParser> Parser(
115*b5893f02SDimitry Andric createMCAsmParser(Regions.getSourceMgr(), Ctx, Str, MAI));
116*b5893f02SDimitry Andric MCAsmLexer &Lexer = Parser->getLexer();
117*b5893f02SDimitry Andric MCACommentConsumer CC(Regions);
118*b5893f02SDimitry Andric Lexer.setCommentConsumer(&CC);
119*b5893f02SDimitry Andric
120*b5893f02SDimitry Andric // Create a target-specific parser and perform the parse.
121*b5893f02SDimitry Andric std::unique_ptr<MCTargetAsmParser> TAP(
122*b5893f02SDimitry Andric TheTarget.createMCAsmParser(STI, *Parser, MCII, Opts));
123*b5893f02SDimitry Andric if (!TAP)
124*b5893f02SDimitry Andric return make_error<StringError>(
125*b5893f02SDimitry Andric "This target does not support assembly parsing.",
126*b5893f02SDimitry Andric inconvertibleErrorCode());
127*b5893f02SDimitry Andric Parser->setTargetParser(*TAP);
128*b5893f02SDimitry Andric Parser->Run(false);
129*b5893f02SDimitry Andric
130*b5893f02SDimitry Andric // Get the assembler dialect from the input. llvm-mca will use this as the
131*b5893f02SDimitry Andric // default dialect when printing reports.
132*b5893f02SDimitry Andric AssemblerDialect = Parser->getAssemblerDialect();
133*b5893f02SDimitry Andric return Regions;
134*b5893f02SDimitry Andric }
135*b5893f02SDimitry Andric
136*b5893f02SDimitry Andric } // namespace mca
137*b5893f02SDimitry Andric } // namespace llvm
138