Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.cpp
35258 views
1
//===----------------------- CodeRegionGenerator.cpp ------------*- 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-exception
6
//
7
//===----------------------------------------------------------------------===//
8
/// \file
9
///
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.
13
//
14
//===----------------------------------------------------------------------===//
15
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/MCTargetOptions.h"
21
#include "llvm/Support/Error.h"
22
#include "llvm/Support/SMLoc.h"
23
#include <memory>
24
25
namespace llvm {
26
namespace mca {
27
28
// This virtual dtor serves as the anchor for the CodeRegionGenerator class.
29
CodeRegionGenerator::~CodeRegionGenerator() {}
30
31
Expected<const CodeRegions &> AsmCodeRegionGenerator::parseCodeRegions(
32
const std::unique_ptr<MCInstPrinter> &IP, bool SkipFailures) {
33
MCTargetOptions Opts;
34
Opts.PreserveAsmComments = false;
35
CodeRegions &Regions = getRegions();
36
MCStreamerWrapper *Str = getMCStreamer();
37
38
// Need to initialize an MCTargetStreamer otherwise
39
// certain asm directives will cause a segfault.
40
// Using nulls() so that anything emitted by the MCTargetStreamer
41
// doesn't show up in the llvm-mca output.
42
raw_ostream &OSRef = nulls();
43
formatted_raw_ostream FOSRef(OSRef);
44
TheTarget.createAsmTargetStreamer(*Str, FOSRef, IP.get());
45
46
// Create a MCAsmParser and setup the lexer to recognize llvm-mca ASM
47
// comments.
48
std::unique_ptr<MCAsmParser> Parser(
49
createMCAsmParser(Regions.getSourceMgr(), Ctx, *Str, MAI));
50
MCAsmLexer &Lexer = Parser->getLexer();
51
MCACommentConsumer *CCP = getCommentConsumer();
52
Lexer.setCommentConsumer(CCP);
53
// Enable support for MASM literal numbers (example: 05h, 101b).
54
Lexer.setLexMasmIntegers(true);
55
56
std::unique_ptr<MCTargetAsmParser> TAP(
57
TheTarget.createMCAsmParser(STI, *Parser, MCII, Opts));
58
if (!TAP)
59
return make_error<StringError>(
60
"This target does not support assembly parsing.",
61
inconvertibleErrorCode());
62
Parser->setTargetParser(*TAP);
63
// Parser->Run() confusingly returns true on errors, in which case the errors
64
// were already shown to the user. SkipFailures implies continuing in the
65
// presence of any kind of failure within the parser, in which case failing
66
// input lines are not represented, but the rest of the input remains.
67
if (Parser->Run(false) && !SkipFailures) {
68
const char *Message = "Assembly input parsing had errors, use "
69
"-skip-unsupported-instructions=parse-failure "
70
"to drop failing lines from the input.";
71
return make_error<StringError>(Message, inconvertibleErrorCode());
72
}
73
74
if (CCP->hadErr())
75
return make_error<StringError>("There was an error parsing comments.",
76
inconvertibleErrorCode());
77
78
// Set the assembler dialect from the input. llvm-mca will use this as the
79
// default dialect when printing reports.
80
AssemblerDialect = Parser->getAssemblerDialect();
81
return Regions;
82
}
83
84
void AnalysisRegionCommentConsumer::HandleComment(SMLoc Loc,
85
StringRef CommentText) {
86
// Skip empty comments.
87
StringRef Comment(CommentText);
88
if (Comment.empty())
89
return;
90
91
// Skip spaces and tabs.
92
unsigned Position = Comment.find_first_not_of(" \t");
93
if (Position >= Comment.size())
94
// We reached the end of the comment. Bail out.
95
return;
96
97
Comment = Comment.drop_front(Position);
98
if (Comment.consume_front("LLVM-MCA-END")) {
99
// Skip spaces and tabs.
100
Position = Comment.find_first_not_of(" \t");
101
if (Position < Comment.size())
102
Comment = Comment.drop_front(Position);
103
Regions.endRegion(Comment, Loc);
104
return;
105
}
106
107
// Try to parse the LLVM-MCA-BEGIN comment.
108
if (!Comment.consume_front("LLVM-MCA-BEGIN"))
109
return;
110
111
// Skip spaces and tabs.
112
Position = Comment.find_first_not_of(" \t");
113
if (Position < Comment.size())
114
Comment = Comment.drop_front(Position);
115
// Use the rest of the string as a descriptor for this code snippet.
116
Regions.beginRegion(Comment, Loc);
117
}
118
119
void InstrumentRegionCommentConsumer::HandleComment(SMLoc Loc,
120
StringRef CommentText) {
121
// Skip empty comments.
122
StringRef Comment(CommentText);
123
if (Comment.empty())
124
return;
125
126
// Skip spaces and tabs.
127
unsigned Position = Comment.find_first_not_of(" \t");
128
if (Position >= Comment.size())
129
// We reached the end of the comment. Bail out.
130
return;
131
Comment = Comment.drop_front(Position);
132
133
// Bail out if not an MCA style comment
134
if (!Comment.consume_front("LLVM-MCA-"))
135
return;
136
137
// Skip AnalysisRegion comments
138
if (Comment.consume_front("BEGIN") || Comment.consume_front("END"))
139
return;
140
141
if (IM.shouldIgnoreInstruments())
142
return;
143
144
auto [InstrumentKind, Data] = Comment.split(" ");
145
146
// An error if not of the form LLVM-MCA-TARGET-KIND
147
if (!IM.supportsInstrumentType(InstrumentKind)) {
148
if (InstrumentKind.empty())
149
SM.PrintMessage(
150
Loc, llvm::SourceMgr::DK_Error,
151
"No instrumentation kind was provided in LLVM-MCA comment");
152
else
153
SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
154
"Unknown instrumentation type in LLVM-MCA comment: " +
155
InstrumentKind);
156
FoundError = true;
157
return;
158
}
159
160
UniqueInstrument I = IM.createInstrument(InstrumentKind, Data);
161
if (!I) {
162
if (Data.empty())
163
SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
164
"Failed to create " + InstrumentKind +
165
" instrument with no data");
166
else
167
SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
168
"Failed to create " + InstrumentKind +
169
" instrument with data: " + Data);
170
FoundError = true;
171
return;
172
}
173
174
// End InstrumentType region if one is open
175
if (Regions.isRegionActive(InstrumentKind))
176
Regions.endRegion(InstrumentKind, Loc);
177
// Start new instrumentation region
178
Regions.beginRegion(InstrumentKind, Loc, std::move(I));
179
}
180
181
} // namespace mca
182
} // namespace llvm
183
184