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