Bug Summary

File:llvm/include/llvm/IR/DiagnosticInfo.h
Warning:line 475, column 28
Undefined or garbage value returned to caller

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name LLVMContext.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mthread-model posix -mframe-pointer=none -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-11/lib/clang/11.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/build-llvm/lib/IR -I /build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/IR -I /build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/build-llvm/include -I /build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-11/lib/clang/11.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/build-llvm/lib/IR -fdebug-prefix-map=/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347=. -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -o /tmp/scan-build-2020-03-09-184146-41876-1 -x c++ /build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/IR/LLVMContext.cpp

/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/IR/LLVMContext.cpp

1//===-- LLVMContext.cpp - Implement LLVMContext ---------------------------===//
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//
9// This file implements LLVMContext, as a wrapper around the opaque
10// class LLVMContextImpl.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/IR/LLVMContext.h"
15#include "LLVMContextImpl.h"
16#include "llvm/ADT/SmallVector.h"
17#include "llvm/ADT/StringMap.h"
18#include "llvm/ADT/StringRef.h"
19#include "llvm/ADT/Twine.h"
20#include "llvm/IR/DiagnosticInfo.h"
21#include "llvm/IR/DiagnosticPrinter.h"
22#include "llvm/IR/LLVMRemarkStreamer.h"
23#include "llvm/IR/Metadata.h"
24#include "llvm/IR/Module.h"
25#include "llvm/Remarks/RemarkStreamer.h"
26#include "llvm/Support/Casting.h"
27#include "llvm/Support/ErrorHandling.h"
28#include "llvm/Support/raw_ostream.h"
29#include <cassert>
30#include <cstdlib>
31#include <string>
32#include <utility>
33
34using namespace llvm;
35
36LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {
37 // Create the fixed metadata kinds. This is done in the same order as the
38 // MD_* enum values so that they correspond.
39 std::pair<unsigned, StringRef> MDKinds[] = {
40#define LLVM_FIXED_MD_KIND(EnumID, Name, Value) {EnumID, Name},
41#include "llvm/IR/FixedMetadataKinds.def"
42#undef LLVM_FIXED_MD_KIND
43 };
44
45 for (auto &MDKind : MDKinds) {
46 unsigned ID = getMDKindID(MDKind.second);
47 assert(ID == MDKind.first && "metadata kind id drifted")((ID == MDKind.first && "metadata kind id drifted") ?
static_cast<void> (0) : __assert_fail ("ID == MDKind.first && \"metadata kind id drifted\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/IR/LLVMContext.cpp"
, 47, __PRETTY_FUNCTION__))
;
48 (void)ID;
49 }
50
51 auto *DeoptEntry = pImpl->getOrInsertBundleTag("deopt");
52 assert(DeoptEntry->second == LLVMContext::OB_deopt &&((DeoptEntry->second == LLVMContext::OB_deopt && "deopt operand bundle id drifted!"
) ? static_cast<void> (0) : __assert_fail ("DeoptEntry->second == LLVMContext::OB_deopt && \"deopt operand bundle id drifted!\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/IR/LLVMContext.cpp"
, 53, __PRETTY_FUNCTION__))
53 "deopt operand bundle id drifted!")((DeoptEntry->second == LLVMContext::OB_deopt && "deopt operand bundle id drifted!"
) ? static_cast<void> (0) : __assert_fail ("DeoptEntry->second == LLVMContext::OB_deopt && \"deopt operand bundle id drifted!\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/IR/LLVMContext.cpp"
, 53, __PRETTY_FUNCTION__))
;
54 (void)DeoptEntry;
55
56 auto *FuncletEntry = pImpl->getOrInsertBundleTag("funclet");
57 assert(FuncletEntry->second == LLVMContext::OB_funclet &&((FuncletEntry->second == LLVMContext::OB_funclet &&
"funclet operand bundle id drifted!") ? static_cast<void>
(0) : __assert_fail ("FuncletEntry->second == LLVMContext::OB_funclet && \"funclet operand bundle id drifted!\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/IR/LLVMContext.cpp"
, 58, __PRETTY_FUNCTION__))
58 "funclet operand bundle id drifted!")((FuncletEntry->second == LLVMContext::OB_funclet &&
"funclet operand bundle id drifted!") ? static_cast<void>
(0) : __assert_fail ("FuncletEntry->second == LLVMContext::OB_funclet && \"funclet operand bundle id drifted!\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/IR/LLVMContext.cpp"
, 58, __PRETTY_FUNCTION__))
;
59 (void)FuncletEntry;
60
61 auto *GCTransitionEntry = pImpl->getOrInsertBundleTag("gc-transition");
62 assert(GCTransitionEntry->second == LLVMContext::OB_gc_transition &&((GCTransitionEntry->second == LLVMContext::OB_gc_transition
&& "gc-transition operand bundle id drifted!") ? static_cast
<void> (0) : __assert_fail ("GCTransitionEntry->second == LLVMContext::OB_gc_transition && \"gc-transition operand bundle id drifted!\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/IR/LLVMContext.cpp"
, 63, __PRETTY_FUNCTION__))
63 "gc-transition operand bundle id drifted!")((GCTransitionEntry->second == LLVMContext::OB_gc_transition
&& "gc-transition operand bundle id drifted!") ? static_cast
<void> (0) : __assert_fail ("GCTransitionEntry->second == LLVMContext::OB_gc_transition && \"gc-transition operand bundle id drifted!\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/IR/LLVMContext.cpp"
, 63, __PRETTY_FUNCTION__))
;
64 (void)GCTransitionEntry;
65
66 auto *CFGuardTargetEntry = pImpl->getOrInsertBundleTag("cfguardtarget");
67 assert(CFGuardTargetEntry->second == LLVMContext::OB_cfguardtarget &&((CFGuardTargetEntry->second == LLVMContext::OB_cfguardtarget
&& "cfguardtarget operand bundle id drifted!") ? static_cast
<void> (0) : __assert_fail ("CFGuardTargetEntry->second == LLVMContext::OB_cfguardtarget && \"cfguardtarget operand bundle id drifted!\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/IR/LLVMContext.cpp"
, 68, __PRETTY_FUNCTION__))
68 "cfguardtarget operand bundle id drifted!")((CFGuardTargetEntry->second == LLVMContext::OB_cfguardtarget
&& "cfguardtarget operand bundle id drifted!") ? static_cast
<void> (0) : __assert_fail ("CFGuardTargetEntry->second == LLVMContext::OB_cfguardtarget && \"cfguardtarget operand bundle id drifted!\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/IR/LLVMContext.cpp"
, 68, __PRETTY_FUNCTION__))
;
69 (void)CFGuardTargetEntry;
70
71 SyncScope::ID SingleThreadSSID =
72 pImpl->getOrInsertSyncScopeID("singlethread");
73 assert(SingleThreadSSID == SyncScope::SingleThread &&((SingleThreadSSID == SyncScope::SingleThread && "singlethread synchronization scope ID drifted!"
) ? static_cast<void> (0) : __assert_fail ("SingleThreadSSID == SyncScope::SingleThread && \"singlethread synchronization scope ID drifted!\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/IR/LLVMContext.cpp"
, 74, __PRETTY_FUNCTION__))
74 "singlethread synchronization scope ID drifted!")((SingleThreadSSID == SyncScope::SingleThread && "singlethread synchronization scope ID drifted!"
) ? static_cast<void> (0) : __assert_fail ("SingleThreadSSID == SyncScope::SingleThread && \"singlethread synchronization scope ID drifted!\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/IR/LLVMContext.cpp"
, 74, __PRETTY_FUNCTION__))
;
75 (void)SingleThreadSSID;
76
77 SyncScope::ID SystemSSID =
78 pImpl->getOrInsertSyncScopeID("");
79 assert(SystemSSID == SyncScope::System &&((SystemSSID == SyncScope::System && "system synchronization scope ID drifted!"
) ? static_cast<void> (0) : __assert_fail ("SystemSSID == SyncScope::System && \"system synchronization scope ID drifted!\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/IR/LLVMContext.cpp"
, 80, __PRETTY_FUNCTION__))
80 "system synchronization scope ID drifted!")((SystemSSID == SyncScope::System && "system synchronization scope ID drifted!"
) ? static_cast<void> (0) : __assert_fail ("SystemSSID == SyncScope::System && \"system synchronization scope ID drifted!\""
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/IR/LLVMContext.cpp"
, 80, __PRETTY_FUNCTION__))
;
81 (void)SystemSSID;
82}
83
84LLVMContext::~LLVMContext() { delete pImpl; }
85
86void LLVMContext::addModule(Module *M) {
87 pImpl->OwnedModules.insert(M);
88}
89
90void LLVMContext::removeModule(Module *M) {
91 pImpl->OwnedModules.erase(M);
92}
93
94//===----------------------------------------------------------------------===//
95// Recoverable Backend Errors
96//===----------------------------------------------------------------------===//
97
98void LLVMContext::
99setInlineAsmDiagnosticHandler(InlineAsmDiagHandlerTy DiagHandler,
100 void *DiagContext) {
101 pImpl->InlineAsmDiagHandler = DiagHandler;
102 pImpl->InlineAsmDiagContext = DiagContext;
103}
104
105/// getInlineAsmDiagnosticHandler - Return the diagnostic handler set by
106/// setInlineAsmDiagnosticHandler.
107LLVMContext::InlineAsmDiagHandlerTy
108LLVMContext::getInlineAsmDiagnosticHandler() const {
109 return pImpl->InlineAsmDiagHandler;
110}
111
112/// getInlineAsmDiagnosticContext - Return the diagnostic context set by
113/// setInlineAsmDiagnosticHandler.
114void *LLVMContext::getInlineAsmDiagnosticContext() const {
115 return pImpl->InlineAsmDiagContext;
116}
117
118void LLVMContext::setDiagnosticHandlerCallBack(
119 DiagnosticHandler::DiagnosticHandlerTy DiagnosticHandler,
120 void *DiagnosticContext, bool RespectFilters) {
121 pImpl->DiagHandler->DiagHandlerCallback = DiagnosticHandler;
122 pImpl->DiagHandler->DiagnosticContext = DiagnosticContext;
123 pImpl->RespectDiagnosticFilters = RespectFilters;
124}
125
126void LLVMContext::setDiagnosticHandler(std::unique_ptr<DiagnosticHandler> &&DH,
127 bool RespectFilters) {
128 pImpl->DiagHandler = std::move(DH);
129 pImpl->RespectDiagnosticFilters = RespectFilters;
130}
131
132void LLVMContext::setDiagnosticsHotnessRequested(bool Requested) {
133 pImpl->DiagnosticsHotnessRequested = Requested;
134}
135bool LLVMContext::getDiagnosticsHotnessRequested() const {
136 return pImpl->DiagnosticsHotnessRequested;
137}
138
139void LLVMContext::setDiagnosticsHotnessThreshold(uint64_t Threshold) {
140 pImpl->DiagnosticsHotnessThreshold = Threshold;
141}
142uint64_t LLVMContext::getDiagnosticsHotnessThreshold() const {
143 return pImpl->DiagnosticsHotnessThreshold;
144}
145
146remarks::RemarkStreamer *LLVMContext::getMainRemarkStreamer() {
147 return pImpl->MainRemarkStreamer.get();
148}
149const remarks::RemarkStreamer *LLVMContext::getMainRemarkStreamer() const {
150 return const_cast<LLVMContext *>(this)->getMainRemarkStreamer();
151}
152void LLVMContext::setMainRemarkStreamer(
153 std::unique_ptr<remarks::RemarkStreamer> RemarkStreamer) {
154 pImpl->MainRemarkStreamer = std::move(RemarkStreamer);
155}
156
157LLVMRemarkStreamer *LLVMContext::getLLVMRemarkStreamer() {
158 return pImpl->LLVMRS.get();
159}
160const LLVMRemarkStreamer *LLVMContext::getLLVMRemarkStreamer() const {
161 return const_cast<LLVMContext *>(this)->getLLVMRemarkStreamer();
162}
163void LLVMContext::setLLVMRemarkStreamer(
164 std::unique_ptr<LLVMRemarkStreamer> RemarkStreamer) {
165 pImpl->LLVMRS = std::move(RemarkStreamer);
166}
167
168DiagnosticHandler::DiagnosticHandlerTy
169LLVMContext::getDiagnosticHandlerCallBack() const {
170 return pImpl->DiagHandler->DiagHandlerCallback;
171}
172
173void *LLVMContext::getDiagnosticContext() const {
174 return pImpl->DiagHandler->DiagnosticContext;
175}
176
177void LLVMContext::setYieldCallback(YieldCallbackTy Callback, void *OpaqueHandle)
178{
179 pImpl->YieldCallback = Callback;
180 pImpl->YieldOpaqueHandle = OpaqueHandle;
181}
182
183void LLVMContext::yield() {
184 if (pImpl->YieldCallback)
185 pImpl->YieldCallback(this, pImpl->YieldOpaqueHandle);
186}
187
188void LLVMContext::emitError(const Twine &ErrorStr) {
189 diagnose(DiagnosticInfoInlineAsm(ErrorStr));
190}
191
192void LLVMContext::emitError(const Instruction *I, const Twine &ErrorStr) {
193 assert (I && "Invalid instruction")((I && "Invalid instruction") ? static_cast<void>
(0) : __assert_fail ("I && \"Invalid instruction\"",
"/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/IR/LLVMContext.cpp"
, 193, __PRETTY_FUNCTION__))
;
194 diagnose(DiagnosticInfoInlineAsm(*I, ErrorStr));
195}
196
197static bool isDiagnosticEnabled(const DiagnosticInfo &DI) {
198 // Optimization remarks are selective. They need to check whether the regexp
199 // pattern, passed via one of the -pass-remarks* flags, matches the name of
200 // the pass that is emitting the diagnostic. If there is no match, ignore the
201 // diagnostic and return.
202 //
203 // Also noisy remarks are only enabled if we have hotness information to sort
204 // them.
205 if (auto *Remark
7.1
'Remark' is non-null
7.1
'Remark' is non-null
= dyn_cast<DiagnosticInfoOptimizationBase>(&DI))
7
The object is a 'DiagnosticInfoOptimizationBase'
8
Taking true branch
206 return Remark->isEnabled() &&
9
Assuming the condition is true
207 (!Remark->isVerbose() || Remark->getHotness());
10
Calling 'DiagnosticInfoOptimizationBase::isVerbose'
208
209 return true;
210}
211
212const char *
213LLVMContext::getDiagnosticMessagePrefix(DiagnosticSeverity Severity) {
214 switch (Severity) {
215 case DS_Error:
216 return "error";
217 case DS_Warning:
218 return "warning";
219 case DS_Remark:
220 return "remark";
221 case DS_Note:
222 return "note";
223 }
224 llvm_unreachable("Unknown DiagnosticSeverity")::llvm::llvm_unreachable_internal("Unknown DiagnosticSeverity"
, "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/IR/LLVMContext.cpp"
, 224)
;
225}
226
227void LLVMContext::diagnose(const DiagnosticInfo &DI) {
228 if (auto *OptDiagBase
2.1
'OptDiagBase' is non-null
2.1
'OptDiagBase' is non-null
= dyn_cast<DiagnosticInfoOptimizationBase>(&DI))
2
Assuming the object is a 'DiagnosticInfoOptimizationBase'
3
Taking true branch
229 if (LLVMRemarkStreamer *RS = getLLVMRemarkStreamer())
4
Assuming 'RS' is null
5
Taking false branch
230 RS->emit(*OptDiagBase);
231
232 // If there is a report handler, use it.
233 if (pImpl->DiagHandler &&
234 (!pImpl->RespectDiagnosticFilters || isDiagnosticEnabled(DI)) &&
235 pImpl->DiagHandler->handleDiagnostics(DI))
236 return;
237
238 if (!isDiagnosticEnabled(DI))
6
Calling 'isDiagnosticEnabled'
239 return;
240
241 // Otherwise, print the message with a prefix based on the severity.
242 DiagnosticPrinterRawOStream DP(errs());
243 errs() << getDiagnosticMessagePrefix(DI.getSeverity()) << ": ";
244 DI.print(DP);
245 errs() << "\n";
246 if (DI.getSeverity() == DS_Error)
247 exit(1);
248}
249
250void LLVMContext::emitError(unsigned LocCookie, const Twine &ErrorStr) {
251 diagnose(DiagnosticInfoInlineAsm(LocCookie, ErrorStr));
1
Calling 'LLVMContext::diagnose'
252}
253
254//===----------------------------------------------------------------------===//
255// Metadata Kind Uniquing
256//===----------------------------------------------------------------------===//
257
258/// Return a unique non-zero ID for the specified metadata kind.
259unsigned LLVMContext::getMDKindID(StringRef Name) const {
260 // If this is new, assign it its ID.
261 return pImpl->CustomMDKindNames.insert(
262 std::make_pair(
263 Name, pImpl->CustomMDKindNames.size()))
264 .first->second;
265}
266
267/// getHandlerNames - Populate client-supplied smallvector using custom
268/// metadata name and ID.
269void LLVMContext::getMDKindNames(SmallVectorImpl<StringRef> &Names) const {
270 Names.resize(pImpl->CustomMDKindNames.size());
271 for (StringMap<unsigned>::const_iterator I = pImpl->CustomMDKindNames.begin(),
272 E = pImpl->CustomMDKindNames.end(); I != E; ++I)
273 Names[I->second] = I->first();
274}
275
276void LLVMContext::getOperandBundleTags(SmallVectorImpl<StringRef> &Tags) const {
277 pImpl->getOperandBundleTags(Tags);
278}
279
280uint32_t LLVMContext::getOperandBundleTagID(StringRef Tag) const {
281 return pImpl->getOperandBundleTagID(Tag);
282}
283
284SyncScope::ID LLVMContext::getOrInsertSyncScopeID(StringRef SSN) {
285 return pImpl->getOrInsertSyncScopeID(SSN);
286}
287
288void LLVMContext::getSyncScopeNames(SmallVectorImpl<StringRef> &SSNs) const {
289 pImpl->getSyncScopeNames(SSNs);
290}
291
292void LLVMContext::setGC(const Function &Fn, std::string GCName) {
293 auto It = pImpl->GCNames.find(&Fn);
294
295 if (It == pImpl->GCNames.end()) {
296 pImpl->GCNames.insert(std::make_pair(&Fn, std::move(GCName)));
297 return;
298 }
299 It->second = std::move(GCName);
300}
301
302const std::string &LLVMContext::getGC(const Function &Fn) {
303 return pImpl->GCNames[&Fn];
304}
305
306void LLVMContext::deleteGC(const Function &Fn) {
307 pImpl->GCNames.erase(&Fn);
308}
309
310bool LLVMContext::shouldDiscardValueNames() const {
311 return pImpl->DiscardValueNames;
312}
313
314bool LLVMContext::isODRUniquingDebugTypes() const { return !!pImpl->DITypeMap; }
315
316void LLVMContext::enableDebugTypeODRUniquing() {
317 if (pImpl->DITypeMap)
318 return;
319
320 pImpl->DITypeMap.emplace();
321}
322
323void LLVMContext::disableDebugTypeODRUniquing() { pImpl->DITypeMap.reset(); }
324
325void LLVMContext::setDiscardValueNames(bool Discard) {
326 pImpl->DiscardValueNames = Discard;
327}
328
329OptPassGate &LLVMContext::getOptPassGate() const {
330 return pImpl->getOptPassGate();
331}
332
333void LLVMContext::setOptPassGate(OptPassGate& OPG) {
334 pImpl->setOptPassGate(OPG);
335}
336
337const DiagnosticHandler *LLVMContext::getDiagHandlerPtr() const {
338 return pImpl->DiagHandler.get();
339}
340
341std::unique_ptr<DiagnosticHandler> LLVMContext::getDiagnosticHandler() {
342 return std::move(pImpl->DiagHandler);
343}

/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/include/llvm/IR/DiagnosticInfo.h

1//===- llvm/IR/DiagnosticInfo.h - Diagnostic Declaration --------*- 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//
9// This file declares the different classes involved in low level diagnostics.
10//
11// Diagnostics reporting is still done as part of the LLVMContext.
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_IR_DIAGNOSTICINFO_H
15#define LLVM_IR_DIAGNOSTICINFO_H
16
17#include "llvm-c/Types.h"
18#include "llvm/ADT/Optional.h"
19#include "llvm/ADT/SmallVector.h"
20#include "llvm/ADT/StringRef.h"
21#include "llvm/ADT/Twine.h"
22#include "llvm/IR/DebugLoc.h"
23#include "llvm/Support/CBindingWrapping.h"
24#include "llvm/Support/YAMLTraits.h"
25#include <algorithm>
26#include <cstdint>
27#include <functional>
28#include <iterator>
29#include <string>
30
31namespace llvm {
32
33// Forward declarations.
34class DiagnosticPrinter;
35class Function;
36class Instruction;
37class LLVMContext;
38class Module;
39class SMDiagnostic;
40
41/// Defines the different supported severity of a diagnostic.
42enum DiagnosticSeverity : char {
43 DS_Error,
44 DS_Warning,
45 DS_Remark,
46 // A note attaches additional information to one of the previous diagnostic
47 // types.
48 DS_Note
49};
50
51/// Defines the different supported kind of a diagnostic.
52/// This enum should be extended with a new ID for each added concrete subclass.
53enum DiagnosticKind {
54 DK_InlineAsm,
55 DK_ResourceLimit,
56 DK_StackSize,
57 DK_Linker,
58 DK_DebugMetadataVersion,
59 DK_DebugMetadataInvalid,
60 DK_ISelFallback,
61 DK_SampleProfile,
62 DK_OptimizationRemark,
63 DK_OptimizationRemarkMissed,
64 DK_OptimizationRemarkAnalysis,
65 DK_OptimizationRemarkAnalysisFPCommute,
66 DK_OptimizationRemarkAnalysisAliasing,
67 DK_OptimizationFailure,
68 DK_FirstRemark = DK_OptimizationRemark,
69 DK_LastRemark = DK_OptimizationFailure,
70 DK_MachineOptimizationRemark,
71 DK_MachineOptimizationRemarkMissed,
72 DK_MachineOptimizationRemarkAnalysis,
73 DK_FirstMachineRemark = DK_MachineOptimizationRemark,
74 DK_LastMachineRemark = DK_MachineOptimizationRemarkAnalysis,
75 DK_MIRParser,
76 DK_PGOProfile,
77 DK_MisExpect,
78 DK_Unsupported,
79 DK_FirstPluginKind // Must be last value to work with
80 // getNextAvailablePluginDiagnosticKind
81};
82
83/// Get the next available kind ID for a plugin diagnostic.
84/// Each time this function is called, it returns a different number.
85/// Therefore, a plugin that wants to "identify" its own classes
86/// with a dynamic identifier, just have to use this method to get a new ID
87/// and assign it to each of its classes.
88/// The returned ID will be greater than or equal to DK_FirstPluginKind.
89/// Thus, the plugin identifiers will not conflict with the
90/// DiagnosticKind values.
91int getNextAvailablePluginDiagnosticKind();
92
93/// This is the base abstract class for diagnostic reporting in
94/// the backend.
95/// The print method must be overloaded by the subclasses to print a
96/// user-friendly message in the client of the backend (let us call it a
97/// frontend).
98class DiagnosticInfo {
99private:
100 /// Kind defines the kind of report this is about.
101 const /* DiagnosticKind */ int Kind;
102 /// Severity gives the severity of the diagnostic.
103 const DiagnosticSeverity Severity;
104
105 virtual void anchor();
106public:
107 DiagnosticInfo(/* DiagnosticKind */ int Kind, DiagnosticSeverity Severity)
108 : Kind(Kind), Severity(Severity) {}
109
110 virtual ~DiagnosticInfo() = default;
111
112 /* DiagnosticKind */ int getKind() const { return Kind; }
113 DiagnosticSeverity getSeverity() const { return Severity; }
114
115 /// Print using the given \p DP a user-friendly message.
116 /// This is the default message that will be printed to the user.
117 /// It is used when the frontend does not directly take advantage
118 /// of the information contained in fields of the subclasses.
119 /// The printed message must not end with '.' nor start with a severity
120 /// keyword.
121 virtual void print(DiagnosticPrinter &DP) const = 0;
122};
123
124using DiagnosticHandlerFunction = std::function<void(const DiagnosticInfo &)>;
125
126/// Diagnostic information for inline asm reporting.
127/// This is basically a message and an optional location.
128class DiagnosticInfoInlineAsm : public DiagnosticInfo {
129private:
130 /// Optional line information. 0 if not set.
131 unsigned LocCookie = 0;
132 /// Message to be reported.
133 const Twine &MsgStr;
134 /// Optional origin of the problem.
135 const Instruction *Instr = nullptr;
136
137public:
138 /// \p MsgStr is the message to be reported to the frontend.
139 /// This class does not copy \p MsgStr, therefore the reference must be valid
140 /// for the whole life time of the Diagnostic.
141 DiagnosticInfoInlineAsm(const Twine &MsgStr,
142 DiagnosticSeverity Severity = DS_Error)
143 : DiagnosticInfo(DK_InlineAsm, Severity), MsgStr(MsgStr) {}
144
145 /// \p LocCookie if non-zero gives the line number for this report.
146 /// \p MsgStr gives the message.
147 /// This class does not copy \p MsgStr, therefore the reference must be valid
148 /// for the whole life time of the Diagnostic.
149 DiagnosticInfoInlineAsm(unsigned LocCookie, const Twine &MsgStr,
150 DiagnosticSeverity Severity = DS_Error)
151 : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(LocCookie),
152 MsgStr(MsgStr) {}
153
154 /// \p Instr gives the original instruction that triggered the diagnostic.
155 /// \p MsgStr gives the message.
156 /// This class does not copy \p MsgStr, therefore the reference must be valid
157 /// for the whole life time of the Diagnostic.
158 /// Same for \p I.
159 DiagnosticInfoInlineAsm(const Instruction &I, const Twine &MsgStr,
160 DiagnosticSeverity Severity = DS_Error);
161
162 unsigned getLocCookie() const { return LocCookie; }
163 const Twine &getMsgStr() const { return MsgStr; }
164 const Instruction *getInstruction() const { return Instr; }
165
166 /// \see DiagnosticInfo::print.
167 void print(DiagnosticPrinter &DP) const override;
168
169 static bool classof(const DiagnosticInfo *DI) {
170 return DI->getKind() == DK_InlineAsm;
171 }
172};
173
174/// Diagnostic information for stack size etc. reporting.
175/// This is basically a function and a size.
176class DiagnosticInfoResourceLimit : public DiagnosticInfo {
177private:
178 /// The function that is concerned by this resource limit diagnostic.
179 const Function &Fn;
180
181 /// Description of the resource type (e.g. stack size)
182 const char *ResourceName;
183
184 /// The computed size usage
185 uint64_t ResourceSize;
186
187 // Threshould passed
188 uint64_t ResourceLimit;
189
190public:
191 /// \p The function that is concerned by this stack size diagnostic.
192 /// \p The computed stack size.
193 DiagnosticInfoResourceLimit(const Function &Fn, const char *ResourceName,
194 uint64_t ResourceSize,
195 DiagnosticSeverity Severity = DS_Warning,
196 DiagnosticKind Kind = DK_ResourceLimit,
197 uint64_t ResourceLimit = 0)
198 : DiagnosticInfo(Kind, Severity), Fn(Fn), ResourceName(ResourceName),
199 ResourceSize(ResourceSize), ResourceLimit(ResourceLimit) {}
200
201 const Function &getFunction() const { return Fn; }
202 const char *getResourceName() const { return ResourceName; }
203 uint64_t getResourceSize() const { return ResourceSize; }
204 uint64_t getResourceLimit() const { return ResourceLimit; }
205
206 /// \see DiagnosticInfo::print.
207 void print(DiagnosticPrinter &DP) const override;
208
209 static bool classof(const DiagnosticInfo *DI) {
210 return DI->getKind() == DK_ResourceLimit || DI->getKind() == DK_StackSize;
211 }
212};
213
214class DiagnosticInfoStackSize : public DiagnosticInfoResourceLimit {
215 virtual void anchor() override;
216public:
217 DiagnosticInfoStackSize(const Function &Fn, uint64_t StackSize,
218 DiagnosticSeverity Severity = DS_Warning,
219 uint64_t StackLimit = 0)
220 : DiagnosticInfoResourceLimit(Fn, "stack size", StackSize, Severity,
221 DK_StackSize, StackLimit) {}
222
223 uint64_t getStackSize() const { return getResourceSize(); }
224 uint64_t getStackLimit() const { return getResourceLimit(); }
225
226 static bool classof(const DiagnosticInfo *DI) {
227 return DI->getKind() == DK_StackSize;
228 }
229};
230
231/// Diagnostic information for debug metadata version reporting.
232/// This is basically a module and a version.
233class DiagnosticInfoDebugMetadataVersion : public DiagnosticInfo {
234private:
235 /// The module that is concerned by this debug metadata version diagnostic.
236 const Module &M;
237 /// The actual metadata version.
238 unsigned MetadataVersion;
239
240public:
241 /// \p The module that is concerned by this debug metadata version diagnostic.
242 /// \p The actual metadata version.
243 DiagnosticInfoDebugMetadataVersion(const Module &M, unsigned MetadataVersion,
244 DiagnosticSeverity Severity = DS_Warning)
245 : DiagnosticInfo(DK_DebugMetadataVersion, Severity), M(M),
246 MetadataVersion(MetadataVersion) {}
247
248 const Module &getModule() const { return M; }
249 unsigned getMetadataVersion() const { return MetadataVersion; }
250
251 /// \see DiagnosticInfo::print.
252 void print(DiagnosticPrinter &DP) const override;
253
254 static bool classof(const DiagnosticInfo *DI) {
255 return DI->getKind() == DK_DebugMetadataVersion;
256 }
257};
258
259/// Diagnostic information for stripping invalid debug metadata.
260class DiagnosticInfoIgnoringInvalidDebugMetadata : public DiagnosticInfo {
261private:
262 /// The module that is concerned by this debug metadata version diagnostic.
263 const Module &M;
264
265public:
266 /// \p The module that is concerned by this debug metadata version diagnostic.
267 DiagnosticInfoIgnoringInvalidDebugMetadata(
268 const Module &M, DiagnosticSeverity Severity = DS_Warning)
269 : DiagnosticInfo(DK_DebugMetadataVersion, Severity), M(M) {}
270
271 const Module &getModule() const { return M; }
272
273 /// \see DiagnosticInfo::print.
274 void print(DiagnosticPrinter &DP) const override;
275
276 static bool classof(const DiagnosticInfo *DI) {
277 return DI->getKind() == DK_DebugMetadataInvalid;
278 }
279};
280
281/// Diagnostic information for the sample profiler.
282class DiagnosticInfoSampleProfile : public DiagnosticInfo {
283public:
284 DiagnosticInfoSampleProfile(StringRef FileName, unsigned LineNum,
285 const Twine &Msg,
286 DiagnosticSeverity Severity = DS_Error)
287 : DiagnosticInfo(DK_SampleProfile, Severity), FileName(FileName),
288 LineNum(LineNum), Msg(Msg) {}
289 DiagnosticInfoSampleProfile(StringRef FileName, const Twine &Msg,
290 DiagnosticSeverity Severity = DS_Error)
291 : DiagnosticInfo(DK_SampleProfile, Severity), FileName(FileName),
292 Msg(Msg) {}
293 DiagnosticInfoSampleProfile(const Twine &Msg,
294 DiagnosticSeverity Severity = DS_Error)
295 : DiagnosticInfo(DK_SampleProfile, Severity), Msg(Msg) {}
296
297 /// \see DiagnosticInfo::print.
298 void print(DiagnosticPrinter &DP) const override;
299
300 static bool classof(const DiagnosticInfo *DI) {
301 return DI->getKind() == DK_SampleProfile;
302 }
303
304 StringRef getFileName() const { return FileName; }
305 unsigned getLineNum() const { return LineNum; }
306 const Twine &getMsg() const { return Msg; }
307
308private:
309 /// Name of the input file associated with this diagnostic.
310 StringRef FileName;
311
312 /// Line number where the diagnostic occurred. If 0, no line number will
313 /// be emitted in the message.
314 unsigned LineNum = 0;
315
316 /// Message to report.
317 const Twine &Msg;
318};
319
320/// Diagnostic information for the PGO profiler.
321class DiagnosticInfoPGOProfile : public DiagnosticInfo {
322public:
323 DiagnosticInfoPGOProfile(const char *FileName, const Twine &Msg,
324 DiagnosticSeverity Severity = DS_Error)
325 : DiagnosticInfo(DK_PGOProfile, Severity), FileName(FileName), Msg(Msg) {}
326
327 /// \see DiagnosticInfo::print.
328 void print(DiagnosticPrinter &DP) const override;
329
330 static bool classof(const DiagnosticInfo *DI) {
331 return DI->getKind() == DK_PGOProfile;
332 }
333
334 const char *getFileName() const { return FileName; }
335 const Twine &getMsg() const { return Msg; }
336
337private:
338 /// Name of the input file associated with this diagnostic.
339 const char *FileName;
340
341 /// Message to report.
342 const Twine &Msg;
343};
344
345class DiagnosticLocation {
346 DIFile *File = nullptr;
347 unsigned Line = 0;
348 unsigned Column = 0;
349
350public:
351 DiagnosticLocation() = default;
352 DiagnosticLocation(const DebugLoc &DL);
353 DiagnosticLocation(const DISubprogram *SP);
354
355 bool isValid() const { return File; }
356 /// Return the full path to the file.
357 std::string getAbsolutePath() const;
358 /// Return the file name relative to the compilation directory.
359 StringRef getRelativePath() const;
360 unsigned getLine() const { return Line; }
361 unsigned getColumn() const { return Column; }
362};
363
364/// Common features for diagnostics with an associated location.
365class DiagnosticInfoWithLocationBase : public DiagnosticInfo {
366 virtual void anchor() override;
367public:
368 /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
369 /// the location information to use in the diagnostic.
370 DiagnosticInfoWithLocationBase(enum DiagnosticKind Kind,
371 enum DiagnosticSeverity Severity,
372 const Function &Fn,
373 const DiagnosticLocation &Loc)
374 : DiagnosticInfo(Kind, Severity), Fn(Fn), Loc(Loc) {}
375
376 /// Return true if location information is available for this diagnostic.
377 bool isLocationAvailable() const { return Loc.isValid(); }
378
379 /// Return a string with the location information for this diagnostic
380 /// in the format "file:line:col". If location information is not available,
381 /// it returns "<unknown>:0:0".
382 const std::string getLocationStr() const;
383
384 /// Return location information for this diagnostic in three parts:
385 /// the relative source file path, line number and column.
386 void getLocation(StringRef &RelativePath, unsigned &Line,
387 unsigned &Column) const;
388
389 /// Return the absolute path tot the file.
390 std::string getAbsolutePath() const;
391
392 const Function &getFunction() const { return Fn; }
393 DiagnosticLocation getLocation() const { return Loc; }
394
395private:
396 /// Function where this diagnostic is triggered.
397 const Function &Fn;
398
399 /// Debug location where this diagnostic is triggered.
400 DiagnosticLocation Loc;
401};
402
403/// Common features for diagnostics dealing with optimization remarks
404/// that are used by both IR and MIR passes.
405class DiagnosticInfoOptimizationBase : public DiagnosticInfoWithLocationBase {
406public:
407 /// Used to set IsVerbose via the stream interface.
408 struct setIsVerbose {};
409
410 /// When an instance of this is inserted into the stream, the arguments
411 /// following will not appear in the remark printed in the compiler output
412 /// (-Rpass) but only in the optimization record file
413 /// (-fsave-optimization-record).
414 struct setExtraArgs {};
415
416 /// Used in the streaming interface as the general argument type. It
417 /// internally converts everything into a key-value pair.
418 struct Argument {
419 std::string Key;
420 std::string Val;
421 // If set, the debug location corresponding to the value.
422 DiagnosticLocation Loc;
423
424 explicit Argument(StringRef Str = "") : Key("String"), Val(Str) {}
425 Argument(StringRef Key, const Value *V);
426 Argument(StringRef Key, const Type *T);
427 Argument(StringRef Key, StringRef S);
428 Argument(StringRef Key, const char *S) : Argument(Key, StringRef(S)) {};
429 Argument(StringRef Key, int N);
430 Argument(StringRef Key, float N);
431 Argument(StringRef Key, long N);
432 Argument(StringRef Key, long long N);
433 Argument(StringRef Key, unsigned N);
434 Argument(StringRef Key, unsigned long N);
435 Argument(StringRef Key, unsigned long long N);
436 Argument(StringRef Key, bool B) : Key(Key), Val(B ? "true" : "false") {}
437 Argument(StringRef Key, DebugLoc dl);
438 };
439
440 /// \p PassName is the name of the pass emitting this diagnostic. \p
441 /// RemarkName is a textual identifier for the remark (single-word,
442 /// camel-case). \p Fn is the function where the diagnostic is being emitted.
443 /// \p Loc is the location information to use in the diagnostic. If line table
444 /// information is available, the diagnostic will include the source code
445 /// location.
446 DiagnosticInfoOptimizationBase(enum DiagnosticKind Kind,
447 enum DiagnosticSeverity Severity,
448 const char *PassName, StringRef RemarkName,
449 const Function &Fn,
450 const DiagnosticLocation &Loc)
451 : DiagnosticInfoWithLocationBase(Kind, Severity, Fn, Loc),
452 PassName(PassName), RemarkName(RemarkName) {}
453
454 void insert(StringRef S);
455 void insert(Argument A);
456 void insert(setIsVerbose V);
457 void insert(setExtraArgs EA);
458
459 /// \see DiagnosticInfo::print.
460 void print(DiagnosticPrinter &DP) const override;
461
462 /// Return true if this optimization remark is enabled by one of
463 /// of the LLVM command line flags (-pass-remarks, -pass-remarks-missed,
464 /// or -pass-remarks-analysis). Note that this only handles the LLVM
465 /// flags. We cannot access Clang flags from here (they are handled
466 /// in BackendConsumer::OptimizationRemarkHandler).
467 virtual bool isEnabled() const = 0;
468
469 StringRef getPassName() const { return PassName; }
470 StringRef getRemarkName() const { return RemarkName; }
471 std::string getMsg() const;
472 Optional<uint64_t> getHotness() const { return Hotness; }
473 void setHotness(Optional<uint64_t> H) { Hotness = H; }
474
475 bool isVerbose() const { return IsVerbose; }
11
Undefined or garbage value returned to caller
476
477 ArrayRef<Argument> getArgs() const { return Args; }
478
479 static bool classof(const DiagnosticInfo *DI) {
480 return (DI->getKind() >= DK_FirstRemark &&
481 DI->getKind() <= DK_LastRemark) ||
482 (DI->getKind() >= DK_FirstMachineRemark &&
483 DI->getKind() <= DK_LastMachineRemark);
484 }
485
486 bool isPassed() const {
487 return (getKind() == DK_OptimizationRemark ||
488 getKind() == DK_MachineOptimizationRemark);
489 }
490
491 bool isMissed() const {
492 return (getKind() == DK_OptimizationRemarkMissed ||
493 getKind() == DK_MachineOptimizationRemarkMissed);
494 }
495
496 bool isAnalysis() const {
497 return (getKind() == DK_OptimizationRemarkAnalysis ||
498 getKind() == DK_MachineOptimizationRemarkAnalysis);
499 }
500
501protected:
502 /// Name of the pass that triggers this report. If this matches the
503 /// regular expression given in -Rpass=regexp, then the remark will
504 /// be emitted.
505 const char *PassName;
506
507 /// Textual identifier for the remark (single-word, camel-case). Can be used
508 /// by external tools reading the output file for optimization remarks to
509 /// identify the remark.
510 StringRef RemarkName;
511
512 /// If profile information is available, this is the number of times the
513 /// corresponding code was executed in a profile instrumentation run.
514 Optional<uint64_t> Hotness;
515
516 /// Arguments collected via the streaming interface.
517 SmallVector<Argument, 4> Args;
518
519 /// The remark is expected to be noisy.
520 bool IsVerbose = false;
521
522 /// If positive, the index of the first argument that only appear in
523 /// the optimization records and not in the remark printed in the compiler
524 /// output.
525 int FirstExtraArgIndex = -1;
526};
527
528/// Allow the insertion operator to return the actual remark type rather than a
529/// common base class. This allows returning the result of the insertion
530/// directly by value, e.g. return OptimizationRemarkAnalysis(...) << "blah".
531template <class RemarkT>
532RemarkT &
533operator<<(RemarkT &R,
534 std::enable_if_t<
535 std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
536 StringRef>
537 S) {
538 R.insert(S);
539 return R;
540}
541
542/// Also allow r-value for the remark to allow insertion into a
543/// temporarily-constructed remark.
544template <class RemarkT>
545RemarkT &
546operator<<(RemarkT &&R,
547 std::enable_if_t<
548 std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
549 StringRef>
550 S) {
551 R.insert(S);
552 return R;
553}
554
555template <class RemarkT>
556RemarkT &
557operator<<(RemarkT &R,
558 std::enable_if_t<
559 std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
560 DiagnosticInfoOptimizationBase::Argument>
561 A) {
562 R.insert(A);
563 return R;
564}
565
566template <class RemarkT>
567RemarkT &
568operator<<(RemarkT &&R,
569 std::enable_if_t<
570 std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
571 DiagnosticInfoOptimizationBase::Argument>
572 A) {
573 R.insert(A);
574 return R;
575}
576
577template <class RemarkT>
578RemarkT &
579operator<<(RemarkT &R,
580 std::enable_if_t<
581 std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
582 DiagnosticInfoOptimizationBase::setIsVerbose>
583 V) {
584 R.insert(V);
585 return R;
586}
587
588template <class RemarkT>
589RemarkT &
590operator<<(RemarkT &&R,
591 std::enable_if_t<
592 std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
593 DiagnosticInfoOptimizationBase::setIsVerbose>
594 V) {
595 R.insert(V);
596 return R;
597}
598
599template <class RemarkT>
600RemarkT &
601operator<<(RemarkT &R,
602 std::enable_if_t<
603 std::is_base_of<DiagnosticInfoOptimizationBase, RemarkT>::value,
604 DiagnosticInfoOptimizationBase::setExtraArgs>
605 EA) {
606 R.insert(EA);
607 return R;
608}
609
610/// Common features for diagnostics dealing with optimization remarks
611/// that are used by IR passes.
612class DiagnosticInfoIROptimization : public DiagnosticInfoOptimizationBase {
613 virtual void anchor() override;
614public:
615 /// \p PassName is the name of the pass emitting this diagnostic. \p
616 /// RemarkName is a textual identifier for the remark (single-word,
617 /// camel-case). \p Fn is the function where the diagnostic is being emitted.
618 /// \p Loc is the location information to use in the diagnostic. If line table
619 /// information is available, the diagnostic will include the source code
620 /// location. \p CodeRegion is IR value (currently basic block) that the
621 /// optimization operates on. This is currently used to provide run-time
622 /// hotness information with PGO.
623 DiagnosticInfoIROptimization(enum DiagnosticKind Kind,
624 enum DiagnosticSeverity Severity,
625 const char *PassName, StringRef RemarkName,
626 const Function &Fn,
627 const DiagnosticLocation &Loc,
628 const Value *CodeRegion = nullptr)
629 : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, RemarkName, Fn,
630 Loc),
631 CodeRegion(CodeRegion) {}
632
633 /// This is ctor variant allows a pass to build an optimization remark
634 /// from an existing remark.
635 ///
636 /// This is useful when a transformation pass (e.g LV) wants to emit a remark
637 /// (\p Orig) generated by one of its analyses (e.g. LAA) as its own analysis
638 /// remark. The string \p Prepend will be emitted before the original
639 /// message.
640 DiagnosticInfoIROptimization(const char *PassName, StringRef Prepend,
641 const DiagnosticInfoIROptimization &Orig)
642 : DiagnosticInfoOptimizationBase(
643 (DiagnosticKind)Orig.getKind(), Orig.getSeverity(), PassName,
644 Orig.RemarkName, Orig.getFunction(), Orig.getLocation()),
645 CodeRegion(Orig.getCodeRegion()) {
646 *this << Prepend;
647 std::copy(Orig.Args.begin(), Orig.Args.end(), std::back_inserter(Args));
648 }
649
650 /// Legacy interface.
651 /// \p PassName is the name of the pass emitting this diagnostic.
652 /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
653 /// the location information to use in the diagnostic. If line table
654 /// information is available, the diagnostic will include the source code
655 /// location. \p Msg is the message to show. Note that this class does not
656 /// copy this message, so this reference must be valid for the whole life time
657 /// of the diagnostic.
658 DiagnosticInfoIROptimization(enum DiagnosticKind Kind,
659 enum DiagnosticSeverity Severity,
660 const char *PassName, const Function &Fn,
661 const DiagnosticLocation &Loc, const Twine &Msg)
662 : DiagnosticInfoOptimizationBase(Kind, Severity, PassName, "", Fn, Loc) {
663 *this << Msg.str();
664 }
665
666 const Value *getCodeRegion() const { return CodeRegion; }
667
668 static bool classof(const DiagnosticInfo *DI) {
669 return DI->getKind() >= DK_FirstRemark && DI->getKind() <= DK_LastRemark;
670 }
671
672private:
673 /// The IR value (currently basic block) that the optimization operates on.
674 /// This is currently used to provide run-time hotness information with PGO.
675 const Value *CodeRegion = nullptr;
676};
677
678/// Diagnostic information for applied optimization remarks.
679class OptimizationRemark : public DiagnosticInfoIROptimization {
680public:
681 /// \p PassName is the name of the pass emitting this diagnostic. If this name
682 /// matches the regular expression given in -Rpass=, then the diagnostic will
683 /// be emitted. \p RemarkName is a textual identifier for the remark (single-
684 /// word, camel-case). \p Loc is the debug location and \p CodeRegion is the
685 /// region that the optimization operates on (currently only block is
686 /// supported).
687 OptimizationRemark(const char *PassName, StringRef RemarkName,
688 const DiagnosticLocation &Loc, const Value *CodeRegion);
689
690 /// Same as above, but the debug location and code region are derived from \p
691 /// Instr.
692 OptimizationRemark(const char *PassName, StringRef RemarkName,
693 const Instruction *Inst);
694
695 /// Same as above, but the debug location and code region are derived from \p
696 /// Func.
697 OptimizationRemark(const char *PassName, StringRef RemarkName,
698 const Function *Func);
699
700 static bool classof(const DiagnosticInfo *DI) {
701 return DI->getKind() == DK_OptimizationRemark;
702 }
703
704 /// \see DiagnosticInfoOptimizationBase::isEnabled.
705 bool isEnabled() const override;
706
707private:
708 /// This is deprecated now and only used by the function API below.
709 /// \p PassName is the name of the pass emitting this diagnostic. If
710 /// this name matches the regular expression given in -Rpass=, then the
711 /// diagnostic will be emitted. \p Fn is the function where the diagnostic
712 /// is being emitted. \p Loc is the location information to use in the
713 /// diagnostic. If line table information is available, the diagnostic
714 /// will include the source code location. \p Msg is the message to show.
715 /// Note that this class does not copy this message, so this reference
716 /// must be valid for the whole life time of the diagnostic.
717 OptimizationRemark(const char *PassName, const Function &Fn,
718 const DiagnosticLocation &Loc, const Twine &Msg)
719 : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,
720 Fn, Loc, Msg) {}
721};
722
723/// Diagnostic information for missed-optimization remarks.
724class OptimizationRemarkMissed : public DiagnosticInfoIROptimization {
725public:
726 /// \p PassName is the name of the pass emitting this diagnostic. If this name
727 /// matches the regular expression given in -Rpass-missed=, then the
728 /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
729 /// remark (single-word, camel-case). \p Loc is the debug location and \p
730 /// CodeRegion is the region that the optimization operates on (currently only
731 /// block is supported).
732 OptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
733 const DiagnosticLocation &Loc,
734 const Value *CodeRegion);
735
736 /// Same as above but \p Inst is used to derive code region and debug
737 /// location.
738 OptimizationRemarkMissed(const char *PassName, StringRef RemarkName,
739 const Instruction *Inst);
740
741 static bool classof(const DiagnosticInfo *DI) {
742 return DI->getKind() == DK_OptimizationRemarkMissed;
743 }
744
745 /// \see DiagnosticInfoOptimizationBase::isEnabled.
746 bool isEnabled() const override;
747
748private:
749 /// This is deprecated now and only used by the function API below.
750 /// \p PassName is the name of the pass emitting this diagnostic. If
751 /// this name matches the regular expression given in -Rpass-missed=, then the
752 /// diagnostic will be emitted. \p Fn is the function where the diagnostic
753 /// is being emitted. \p Loc is the location information to use in the
754 /// diagnostic. If line table information is available, the diagnostic
755 /// will include the source code location. \p Msg is the message to show.
756 /// Note that this class does not copy this message, so this reference
757 /// must be valid for the whole life time of the diagnostic.
758 OptimizationRemarkMissed(const char *PassName, const Function &Fn,
759 const DiagnosticLocation &Loc, const Twine &Msg)
760 : DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark,
761 PassName, Fn, Loc, Msg) {}
762};
763
764/// Diagnostic information for optimization analysis remarks.
765class OptimizationRemarkAnalysis : public DiagnosticInfoIROptimization {
766public:
767 /// \p PassName is the name of the pass emitting this diagnostic. If this name
768 /// matches the regular expression given in -Rpass-analysis=, then the
769 /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
770 /// remark (single-word, camel-case). \p Loc is the debug location and \p
771 /// CodeRegion is the region that the optimization operates on (currently only
772 /// block is supported).
773 OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
774 const DiagnosticLocation &Loc,
775 const Value *CodeRegion);
776
777 /// This is ctor variant allows a pass to build an optimization remark
778 /// from an existing remark.
779 ///
780 /// This is useful when a transformation pass (e.g LV) wants to emit a remark
781 /// (\p Orig) generated by one of its analyses (e.g. LAA) as its own analysis
782 /// remark. The string \p Prepend will be emitted before the original
783 /// message.
784 OptimizationRemarkAnalysis(const char *PassName, StringRef Prepend,
785 const OptimizationRemarkAnalysis &Orig)
786 : DiagnosticInfoIROptimization(PassName, Prepend, Orig) {}
787
788 /// Same as above but \p Inst is used to derive code region and debug
789 /// location.
790 OptimizationRemarkAnalysis(const char *PassName, StringRef RemarkName,
791 const Instruction *Inst);
792
793 static bool classof(const DiagnosticInfo *DI) {
794 return DI->getKind() == DK_OptimizationRemarkAnalysis;
795 }
796
797 /// \see DiagnosticInfoOptimizationBase::isEnabled.
798 bool isEnabled() const override;
799
800 static const char *AlwaysPrint;
801
802 bool shouldAlwaysPrint() const { return getPassName() == AlwaysPrint; }
803
804protected:
805 OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName,
806 const Function &Fn, const DiagnosticLocation &Loc,
807 const Twine &Msg)
808 : DiagnosticInfoIROptimization(Kind, DS_Remark, PassName, Fn, Loc, Msg) {}
809
810 OptimizationRemarkAnalysis(enum DiagnosticKind Kind, const char *PassName,
811 StringRef RemarkName,
812 const DiagnosticLocation &Loc,
813 const Value *CodeRegion);
814
815private:
816 /// This is deprecated now and only used by the function API below.
817 /// \p PassName is the name of the pass emitting this diagnostic. If
818 /// this name matches the regular expression given in -Rpass-analysis=, then
819 /// the diagnostic will be emitted. \p Fn is the function where the diagnostic
820 /// is being emitted. \p Loc is the location information to use in the
821 /// diagnostic. If line table information is available, the diagnostic will
822 /// include the source code location. \p Msg is the message to show. Note that
823 /// this class does not copy this message, so this reference must be valid for
824 /// the whole life time of the diagnostic.
825 OptimizationRemarkAnalysis(const char *PassName, const Function &Fn,
826 const DiagnosticLocation &Loc, const Twine &Msg)
827 : DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark,
828 PassName, Fn, Loc, Msg) {}
829};
830
831/// Diagnostic information for optimization analysis remarks related to
832/// floating-point non-commutativity.
833class OptimizationRemarkAnalysisFPCommute : public OptimizationRemarkAnalysis {
834 virtual void anchor();
835public:
836 /// \p PassName is the name of the pass emitting this diagnostic. If this name
837 /// matches the regular expression given in -Rpass-analysis=, then the
838 /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
839 /// remark (single-word, camel-case). \p Loc is the debug location and \p
840 /// CodeRegion is the region that the optimization operates on (currently only
841 /// block is supported). The front-end will append its own message related to
842 /// options that address floating-point non-commutativity.
843 OptimizationRemarkAnalysisFPCommute(const char *PassName,
844 StringRef RemarkName,
845 const DiagnosticLocation &Loc,
846 const Value *CodeRegion)
847 : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute,
848 PassName, RemarkName, Loc, CodeRegion) {}
849
850 static bool classof(const DiagnosticInfo *DI) {
851 return DI->getKind() == DK_OptimizationRemarkAnalysisFPCommute;
852 }
853
854private:
855 /// This is deprecated now and only used by the function API below.
856 /// \p PassName is the name of the pass emitting this diagnostic. If
857 /// this name matches the regular expression given in -Rpass-analysis=, then
858 /// the diagnostic will be emitted. \p Fn is the function where the diagnostic
859 /// is being emitted. \p Loc is the location information to use in the
860 /// diagnostic. If line table information is available, the diagnostic will
861 /// include the source code location. \p Msg is the message to show. The
862 /// front-end will append its own message related to options that address
863 /// floating-point non-commutativity. Note that this class does not copy this
864 /// message, so this reference must be valid for the whole life time of the
865 /// diagnostic.
866 OptimizationRemarkAnalysisFPCommute(const char *PassName, const Function &Fn,
867 const DiagnosticLocation &Loc,
868 const Twine &Msg)
869 : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisFPCommute,
870 PassName, Fn, Loc, Msg) {}
871};
872
873/// Diagnostic information for optimization analysis remarks related to
874/// pointer aliasing.
875class OptimizationRemarkAnalysisAliasing : public OptimizationRemarkAnalysis {
876 virtual void anchor();
877public:
878 /// \p PassName is the name of the pass emitting this diagnostic. If this name
879 /// matches the regular expression given in -Rpass-analysis=, then the
880 /// diagnostic will be emitted. \p RemarkName is a textual identifier for the
881 /// remark (single-word, camel-case). \p Loc is the debug location and \p
882 /// CodeRegion is the region that the optimization operates on (currently only
883 /// block is supported). The front-end will append its own message related to
884 /// options that address pointer aliasing legality.
885 OptimizationRemarkAnalysisAliasing(const char *PassName, StringRef RemarkName,
886 const DiagnosticLocation &Loc,
887 const Value *CodeRegion)
888 : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing,
889 PassName, RemarkName, Loc, CodeRegion) {}
890
891 static bool classof(const DiagnosticInfo *DI) {
892 return DI->getKind() == DK_OptimizationRemarkAnalysisAliasing;
893 }
894
895private:
896 /// This is deprecated now and only used by the function API below.
897 /// \p PassName is the name of the pass emitting this diagnostic. If
898 /// this name matches the regular expression given in -Rpass-analysis=, then
899 /// the diagnostic will be emitted. \p Fn is the function where the diagnostic
900 /// is being emitted. \p Loc is the location information to use in the
901 /// diagnostic. If line table information is available, the diagnostic will
902 /// include the source code location. \p Msg is the message to show. The
903 /// front-end will append its own message related to options that address
904 /// pointer aliasing legality. Note that this class does not copy this
905 /// message, so this reference must be valid for the whole life time of the
906 /// diagnostic.
907 OptimizationRemarkAnalysisAliasing(const char *PassName, const Function &Fn,
908 const DiagnosticLocation &Loc,
909 const Twine &Msg)
910 : OptimizationRemarkAnalysis(DK_OptimizationRemarkAnalysisAliasing,
911 PassName, Fn, Loc, Msg) {}
912};
913
914/// Diagnostic information for machine IR parser.
915class DiagnosticInfoMIRParser : public DiagnosticInfo {
916 const SMDiagnostic &Diagnostic;
917
918public:
919 DiagnosticInfoMIRParser(DiagnosticSeverity Severity,
920 const SMDiagnostic &Diagnostic)
921 : DiagnosticInfo(DK_MIRParser, Severity), Diagnostic(Diagnostic) {}
922
923 const SMDiagnostic &getDiagnostic() const { return Diagnostic; }
924
925 void print(DiagnosticPrinter &DP) const override;
926
927 static bool classof(const DiagnosticInfo *DI) {
928 return DI->getKind() == DK_MIRParser;
929 }
930};
931
932/// Diagnostic information for ISel fallback path.
933class DiagnosticInfoISelFallback : public DiagnosticInfo {
934 /// The function that is concerned by this diagnostic.
935 const Function &Fn;
936
937public:
938 DiagnosticInfoISelFallback(const Function &Fn,
939 DiagnosticSeverity Severity = DS_Warning)
940 : DiagnosticInfo(DK_ISelFallback, Severity), Fn(Fn) {}
941
942 const Function &getFunction() const { return Fn; }
943
944 void print(DiagnosticPrinter &DP) const override;
945
946 static bool classof(const DiagnosticInfo *DI) {
947 return DI->getKind() == DK_ISelFallback;
948 }
949};
950
951// Create wrappers for C Binding types (see CBindingWrapping.h).
952DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DiagnosticInfo, LLVMDiagnosticInfoRef)inline DiagnosticInfo *unwrap(LLVMDiagnosticInfoRef P) { return
reinterpret_cast<DiagnosticInfo*>(P); } inline LLVMDiagnosticInfoRef
wrap(const DiagnosticInfo *P) { return reinterpret_cast<LLVMDiagnosticInfoRef
>(const_cast<DiagnosticInfo*>(P)); }
953
954/// Diagnostic information for optimization failures.
955class DiagnosticInfoOptimizationFailure : public DiagnosticInfoIROptimization {
956public:
957 /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
958 /// the location information to use in the diagnostic. If line table
959 /// information is available, the diagnostic will include the source code
960 /// location. \p Msg is the message to show. Note that this class does not
961 /// copy this message, so this reference must be valid for the whole life time
962 /// of the diagnostic.
963 DiagnosticInfoOptimizationFailure(const Function &Fn,
964 const DiagnosticLocation &Loc,
965 const Twine &Msg)
966 : DiagnosticInfoIROptimization(DK_OptimizationFailure, DS_Warning,
967 nullptr, Fn, Loc, Msg) {}
968
969 /// \p PassName is the name of the pass emitting this diagnostic. \p
970 /// RemarkName is a textual identifier for the remark (single-word,
971 /// camel-case). \p Loc is the debug location and \p CodeRegion is the
972 /// region that the optimization operates on (currently basic block is
973 /// supported).
974 DiagnosticInfoOptimizationFailure(const char *PassName, StringRef RemarkName,
975 const DiagnosticLocation &Loc,
976 const Value *CodeRegion);
977
978 static bool classof(const DiagnosticInfo *DI) {
979 return DI->getKind() == DK_OptimizationFailure;
980 }
981
982 /// \see DiagnosticInfoOptimizationBase::isEnabled.
983 bool isEnabled() const override;
984};
985
986/// Diagnostic information for unsupported feature in backend.
987class DiagnosticInfoUnsupported : public DiagnosticInfoWithLocationBase {
988private:
989 Twine Msg;
990
991public:
992 /// \p Fn is the function where the diagnostic is being emitted. \p Loc is
993 /// the location information to use in the diagnostic. If line table
994 /// information is available, the diagnostic will include the source code
995 /// location. \p Msg is the message to show. Note that this class does not
996 /// copy this message, so this reference must be valid for the whole life time
997 /// of the diagnostic.
998 DiagnosticInfoUnsupported(
999 const Function &Fn, const Twine &Msg,
1000 const DiagnosticLocation &Loc = DiagnosticLocation(),
1001 DiagnosticSeverity Severity = DS_Error)
1002 : DiagnosticInfoWithLocationBase(DK_Unsupported, Severity, Fn, Loc),
1003 Msg(Msg) {}
1004
1005 static bool classof(const DiagnosticInfo *DI) {
1006 return DI->getKind() == DK_Unsupported;
1007 }
1008
1009 const Twine &getMessage() const { return Msg; }
1010
1011 void print(DiagnosticPrinter &DP) const override;
1012};
1013
1014/// Diagnostic information for MisExpect analysis.
1015class DiagnosticInfoMisExpect : public DiagnosticInfoWithLocationBase {
1016public:
1017 DiagnosticInfoMisExpect(const Instruction *Inst, Twine &Msg);
1018
1019 /// \see DiagnosticInfo::print.
1020 void print(DiagnosticPrinter &DP) const override;
1021
1022 static bool classof(const DiagnosticInfo *DI) {
1023 return DI->getKind() == DK_MisExpect;
1024 }
1025
1026 const Twine &getMsg() const { return Msg; }
1027
1028private:
1029 /// Message to report.
1030 const Twine &Msg;
1031};
1032
1033} // end namespace llvm
1034
1035#endif // LLVM_IR_DIAGNOSTICINFO_H