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