1 //===----------------------- CodeRegionGenerator.cpp ------------*- C++ -*-===//
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-exception
7 //===----------------------------------------------------------------------===//
10 /// This file defines classes responsible for generating llvm-mca
11 /// CodeRegions from various types of input. llvm-mca only analyzes CodeRegions,
12 /// so the classes here provide the input-to-CodeRegions translation.
14 //===----------------------------------------------------------------------===//
16 #include "CodeRegionGenerator.h"
17 #include "llvm/ADT/ArrayRef.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
20 #include "llvm/MC/MCStreamer.h"
21 #include "llvm/MC/MCTargetOptions.h"
22 #include "llvm/Support/Error.h"
23 #include "llvm/Support/SMLoc.h"
29 // This virtual dtor serves as the anchor for the CodeRegionGenerator class.
30 CodeRegionGenerator::~CodeRegionGenerator() {}
32 // A comment consumer that parses strings. The only valid tokens are strings.
33 class MCACommentConsumer
: public AsmCommentConsumer
{
37 MCACommentConsumer(CodeRegions
&R
) : Regions(R
) {}
38 void HandleComment(SMLoc Loc
, StringRef CommentText
) override
;
41 // This class provides the callbacks that occur when parsing input assembly.
42 class MCStreamerWrapper final
: public MCStreamer
{
46 MCStreamerWrapper(MCContext
&Context
, mca::CodeRegions
&R
)
47 : MCStreamer(Context
), Regions(R
) {}
49 // We only want to intercept the emission of new instructions.
50 virtual void EmitInstruction(const MCInst
&Inst
,
51 const MCSubtargetInfo
&/* unused */) override
{
52 Regions
.addInstruction(Inst
);
55 bool EmitSymbolAttribute(MCSymbol
*Symbol
, MCSymbolAttr Attribute
) override
{
59 void EmitCommonSymbol(MCSymbol
*Symbol
, uint64_t Size
,
60 unsigned ByteAlignment
) override
{}
61 void EmitZerofill(MCSection
*Section
, MCSymbol
*Symbol
= nullptr,
62 uint64_t Size
= 0, unsigned ByteAlignment
= 0,
63 SMLoc Loc
= SMLoc()) override
{}
64 void EmitGPRel32Value(const MCExpr
*Value
) override
{}
65 void BeginCOFFSymbolDef(const MCSymbol
*Symbol
) override
{}
66 void EmitCOFFSymbolStorageClass(int StorageClass
) override
{}
67 void EmitCOFFSymbolType(int Type
) override
{}
68 void EndCOFFSymbolDef() override
{}
70 ArrayRef
<MCInst
> GetInstructionSequence(unsigned Index
) const {
71 return Regions
.getInstructionSequence(Index
);
75 void MCACommentConsumer::HandleComment(SMLoc Loc
, StringRef CommentText
) {
76 // Skip empty comments.
77 StringRef
Comment(CommentText
);
81 // Skip spaces and tabs.
82 unsigned Position
= Comment
.find_first_not_of(" \t");
83 if (Position
>= Comment
.size())
84 // We reached the end of the comment. Bail out.
87 Comment
= Comment
.drop_front(Position
);
88 if (Comment
.consume_front("LLVM-MCA-END")) {
89 // Skip spaces and tabs.
90 Position
= Comment
.find_first_not_of(" \t");
91 if (Position
< Comment
.size())
92 Comment
= Comment
.drop_front(Position
);
93 Regions
.endRegion(Comment
, Loc
);
97 // Try to parse the LLVM-MCA-BEGIN comment.
98 if (!Comment
.consume_front("LLVM-MCA-BEGIN"))
101 // Skip spaces and tabs.
102 Position
= Comment
.find_first_not_of(" \t");
103 if (Position
< Comment
.size())
104 Comment
= Comment
.drop_front(Position
);
105 // Use the rest of the string as a descriptor for this code snippet.
106 Regions
.beginRegion(Comment
, Loc
);
109 Expected
<const CodeRegions
&> AsmCodeRegionGenerator::parseCodeRegions() {
110 MCTargetOptions Opts
;
111 Opts
.PreserveAsmComments
= false;
112 MCStreamerWrapper
Str(Ctx
, Regions
);
114 // Create a MCAsmParser and setup the lexer to recognize llvm-mca ASM
116 std::unique_ptr
<MCAsmParser
> Parser(
117 createMCAsmParser(Regions
.getSourceMgr(), Ctx
, Str
, MAI
));
118 MCAsmLexer
&Lexer
= Parser
->getLexer();
119 MCACommentConsumer
CC(Regions
);
120 Lexer
.setCommentConsumer(&CC
);
121 // Enable support for MASM literal numbers (example: 05h, 101b).
122 Lexer
.setLexMasmIntegers(true);
124 std::unique_ptr
<MCTargetAsmParser
> TAP(
125 TheTarget
.createMCAsmParser(STI
, *Parser
, MCII
, Opts
));
127 return make_error
<StringError
>(
128 "This target does not support assembly parsing.",
129 inconvertibleErrorCode());
130 Parser
->setTargetParser(*TAP
);
133 // Set the assembler dialect from the input. llvm-mca will use this as the
134 // default dialect when printing reports.
135 AssemblerDialect
= Parser
->getAssemblerDialect();