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 | pImpl->MachineFunctionNums.erase(Val: M); |
122 | } |
123 | |
124 | unsigned LLVMContext::generateMachineFunctionNum(Function &F) { |
125 | Module *M = F.getParent(); |
126 | assert(pImpl->OwnedModules.contains(M) && "Unexpected module!" ); |
127 | return pImpl->MachineFunctionNums[M]++; |
128 | } |
129 | |
130 | //===----------------------------------------------------------------------===// |
131 | // Recoverable Backend Errors |
132 | //===----------------------------------------------------------------------===// |
133 | |
134 | void LLVMContext::setDiagnosticHandlerCallBack( |
135 | DiagnosticHandler::DiagnosticHandlerTy DiagnosticHandler, |
136 | void *DiagnosticContext, bool RespectFilters) { |
137 | pImpl->DiagHandler->DiagHandlerCallback = DiagnosticHandler; |
138 | pImpl->DiagHandler->DiagnosticContext = DiagnosticContext; |
139 | pImpl->RespectDiagnosticFilters = RespectFilters; |
140 | } |
141 | |
142 | void LLVMContext::setDiagnosticHandler(std::unique_ptr<DiagnosticHandler> &&DH, |
143 | bool RespectFilters) { |
144 | pImpl->DiagHandler = std::move(DH); |
145 | pImpl->RespectDiagnosticFilters = RespectFilters; |
146 | } |
147 | |
148 | void LLVMContext::setDiagnosticsHotnessRequested(bool Requested) { |
149 | pImpl->DiagnosticsHotnessRequested = Requested; |
150 | } |
151 | bool LLVMContext::getDiagnosticsHotnessRequested() const { |
152 | return pImpl->DiagnosticsHotnessRequested; |
153 | } |
154 | |
155 | void LLVMContext::setDiagnosticsHotnessThreshold(std::optional<uint64_t> Threshold) { |
156 | pImpl->DiagnosticsHotnessThreshold = Threshold; |
157 | } |
158 | void LLVMContext::setMisExpectWarningRequested(bool Requested) { |
159 | pImpl->MisExpectWarningRequested = Requested; |
160 | } |
161 | bool LLVMContext::getMisExpectWarningRequested() const { |
162 | return pImpl->MisExpectWarningRequested; |
163 | } |
164 | uint64_t LLVMContext::getDiagnosticsHotnessThreshold() const { |
165 | return pImpl->DiagnosticsHotnessThreshold.value_or(UINT64_MAX); |
166 | } |
167 | void LLVMContext::setDiagnosticsMisExpectTolerance( |
168 | std::optional<uint32_t> Tolerance) { |
169 | pImpl->DiagnosticsMisExpectTolerance = Tolerance; |
170 | } |
171 | uint32_t LLVMContext::getDiagnosticsMisExpectTolerance() const { |
172 | return pImpl->DiagnosticsMisExpectTolerance.value_or(u: 0); |
173 | } |
174 | |
175 | bool LLVMContext::isDiagnosticsHotnessThresholdSetFromPSI() const { |
176 | return !pImpl->DiagnosticsHotnessThreshold.has_value(); |
177 | } |
178 | |
179 | remarks::RemarkStreamer *LLVMContext::getMainRemarkStreamer() { |
180 | return pImpl->MainRemarkStreamer.get(); |
181 | } |
182 | const remarks::RemarkStreamer *LLVMContext::getMainRemarkStreamer() const { |
183 | return const_cast<LLVMContext *>(this)->getMainRemarkStreamer(); |
184 | } |
185 | void LLVMContext::setMainRemarkStreamer( |
186 | std::unique_ptr<remarks::RemarkStreamer> ) { |
187 | pImpl->MainRemarkStreamer = std::move(RemarkStreamer); |
188 | } |
189 | |
190 | LLVMRemarkStreamer *LLVMContext::() { |
191 | return pImpl->LLVMRS.get(); |
192 | } |
193 | const LLVMRemarkStreamer *LLVMContext::() const { |
194 | return const_cast<LLVMContext *>(this)->getLLVMRemarkStreamer(); |
195 | } |
196 | void LLVMContext::( |
197 | std::unique_ptr<LLVMRemarkStreamer> ) { |
198 | pImpl->LLVMRS = std::move(RemarkStreamer); |
199 | } |
200 | |
201 | DiagnosticHandler::DiagnosticHandlerTy |
202 | LLVMContext::getDiagnosticHandlerCallBack() const { |
203 | return pImpl->DiagHandler->DiagHandlerCallback; |
204 | } |
205 | |
206 | void *LLVMContext::getDiagnosticContext() const { |
207 | return pImpl->DiagHandler->DiagnosticContext; |
208 | } |
209 | |
210 | void LLVMContext::setYieldCallback(YieldCallbackTy Callback, void *OpaqueHandle) |
211 | { |
212 | pImpl->YieldCallback = Callback; |
213 | pImpl->YieldOpaqueHandle = OpaqueHandle; |
214 | } |
215 | |
216 | void LLVMContext::yield() { |
217 | if (pImpl->YieldCallback) |
218 | pImpl->YieldCallback(this, pImpl->YieldOpaqueHandle); |
219 | } |
220 | |
221 | void LLVMContext::emitError(const Twine &ErrorStr) { |
222 | diagnose(DI: DiagnosticInfoInlineAsm(ErrorStr)); |
223 | } |
224 | |
225 | void LLVMContext::emitError(const Instruction *I, const Twine &ErrorStr) { |
226 | assert (I && "Invalid instruction" ); |
227 | diagnose(DI: DiagnosticInfoInlineAsm(*I, ErrorStr)); |
228 | } |
229 | |
230 | static bool isDiagnosticEnabled(const DiagnosticInfo &DI) { |
231 | // Optimization remarks are selective. They need to check whether the regexp |
232 | // pattern, passed via one of the -pass-remarks* flags, matches the name of |
233 | // the pass that is emitting the diagnostic. If there is no match, ignore the |
234 | // diagnostic and return. |
235 | // |
236 | // Also noisy remarks are only enabled if we have hotness information to sort |
237 | // them. |
238 | if (auto * = dyn_cast<DiagnosticInfoOptimizationBase>(Val: &DI)) |
239 | return Remark->isEnabled() && |
240 | (!Remark->isVerbose() || Remark->getHotness()); |
241 | |
242 | return true; |
243 | } |
244 | |
245 | const char * |
246 | LLVMContext::getDiagnosticMessagePrefix(DiagnosticSeverity Severity) { |
247 | switch (Severity) { |
248 | case DS_Error: |
249 | return "error" ; |
250 | case DS_Warning: |
251 | return "warning" ; |
252 | case DS_Remark: |
253 | return "remark" ; |
254 | case DS_Note: |
255 | return "note" ; |
256 | } |
257 | llvm_unreachable("Unknown DiagnosticSeverity" ); |
258 | } |
259 | |
260 | void LLVMContext::diagnose(const DiagnosticInfo &DI) { |
261 | if (auto *OptDiagBase = dyn_cast<DiagnosticInfoOptimizationBase>(Val: &DI)) |
262 | if (LLVMRemarkStreamer *RS = getLLVMRemarkStreamer()) |
263 | RS->emit(Diag: *OptDiagBase); |
264 | |
265 | // If there is a report handler, use it. |
266 | if (pImpl->DiagHandler) { |
267 | if (DI.getSeverity() == DS_Error) |
268 | pImpl->DiagHandler->HasErrors = true; |
269 | if ((!pImpl->RespectDiagnosticFilters || isDiagnosticEnabled(DI)) && |
270 | pImpl->DiagHandler->handleDiagnostics(DI)) |
271 | return; |
272 | } |
273 | |
274 | if (!isDiagnosticEnabled(DI)) |
275 | return; |
276 | |
277 | // Otherwise, print the message with a prefix based on the severity. |
278 | DiagnosticPrinterRawOStream DP(errs()); |
279 | errs() << getDiagnosticMessagePrefix(Severity: DI.getSeverity()) << ": " ; |
280 | DI.print(DP); |
281 | errs() << "\n" ; |
282 | if (DI.getSeverity() == DS_Error) |
283 | exit(status: 1); |
284 | } |
285 | |
286 | void LLVMContext::emitError(uint64_t LocCookie, const Twine &ErrorStr) { |
287 | diagnose(DI: DiagnosticInfoInlineAsm(LocCookie, ErrorStr)); |
288 | } |
289 | |
290 | //===----------------------------------------------------------------------===// |
291 | // Metadata Kind Uniquing |
292 | //===----------------------------------------------------------------------===// |
293 | |
294 | /// Return a unique non-zero ID for the specified metadata kind. |
295 | unsigned LLVMContext::getMDKindID(StringRef Name) const { |
296 | // If this is new, assign it its ID. |
297 | return pImpl->CustomMDKindNames.insert( |
298 | KV: std::make_pair( |
299 | x&: Name, y: pImpl->CustomMDKindNames.size())) |
300 | .first->second; |
301 | } |
302 | |
303 | /// getHandlerNames - Populate client-supplied smallvector using custom |
304 | /// metadata name and ID. |
305 | void LLVMContext::getMDKindNames(SmallVectorImpl<StringRef> &Names) const { |
306 | Names.resize(N: pImpl->CustomMDKindNames.size()); |
307 | for (StringMap<unsigned>::const_iterator I = pImpl->CustomMDKindNames.begin(), |
308 | E = pImpl->CustomMDKindNames.end(); I != E; ++I) |
309 | Names[I->second] = I->first(); |
310 | } |
311 | |
312 | void LLVMContext::getOperandBundleTags(SmallVectorImpl<StringRef> &Tags) const { |
313 | pImpl->getOperandBundleTags(Tags); |
314 | } |
315 | |
316 | StringMapEntry<uint32_t> * |
317 | LLVMContext::getOrInsertBundleTag(StringRef TagName) const { |
318 | return pImpl->getOrInsertBundleTag(Tag: TagName); |
319 | } |
320 | |
321 | uint32_t LLVMContext::getOperandBundleTagID(StringRef Tag) const { |
322 | return pImpl->getOperandBundleTagID(Tag); |
323 | } |
324 | |
325 | SyncScope::ID LLVMContext::getOrInsertSyncScopeID(StringRef SSN) { |
326 | return pImpl->getOrInsertSyncScopeID(SSN); |
327 | } |
328 | |
329 | void LLVMContext::getSyncScopeNames(SmallVectorImpl<StringRef> &SSNs) const { |
330 | pImpl->getSyncScopeNames(SSNs); |
331 | } |
332 | |
333 | void LLVMContext::setGC(const Function &Fn, std::string GCName) { |
334 | auto It = pImpl->GCNames.find(Val: &Fn); |
335 | |
336 | if (It == pImpl->GCNames.end()) { |
337 | pImpl->GCNames.insert(KV: std::make_pair(x: &Fn, y: std::move(GCName))); |
338 | return; |
339 | } |
340 | It->second = std::move(GCName); |
341 | } |
342 | |
343 | const std::string &LLVMContext::getGC(const Function &Fn) { |
344 | return pImpl->GCNames[&Fn]; |
345 | } |
346 | |
347 | void LLVMContext::deleteGC(const Function &Fn) { |
348 | pImpl->GCNames.erase(Val: &Fn); |
349 | } |
350 | |
351 | bool LLVMContext::shouldDiscardValueNames() const { |
352 | return pImpl->DiscardValueNames; |
353 | } |
354 | |
355 | bool LLVMContext::isODRUniquingDebugTypes() const { return !!pImpl->DITypeMap; } |
356 | |
357 | void LLVMContext::enableDebugTypeODRUniquing() { |
358 | if (pImpl->DITypeMap) |
359 | return; |
360 | |
361 | pImpl->DITypeMap.emplace(); |
362 | } |
363 | |
364 | void LLVMContext::disableDebugTypeODRUniquing() { pImpl->DITypeMap.reset(); } |
365 | |
366 | void LLVMContext::setDiscardValueNames(bool Discard) { |
367 | pImpl->DiscardValueNames = Discard; |
368 | } |
369 | |
370 | OptPassGate &LLVMContext::getOptPassGate() const { |
371 | return pImpl->getOptPassGate(); |
372 | } |
373 | |
374 | void LLVMContext::setOptPassGate(OptPassGate& OPG) { |
375 | pImpl->setOptPassGate(OPG); |
376 | } |
377 | |
378 | const DiagnosticHandler *LLVMContext::getDiagHandlerPtr() const { |
379 | return pImpl->DiagHandler.get(); |
380 | } |
381 | |
382 | std::unique_ptr<DiagnosticHandler> LLVMContext::getDiagnosticHandler() { |
383 | return std::move(pImpl->DiagHandler); |
384 | } |
385 | |
386 | void LLVMContext::setOpaquePointers(bool Enable) const { |
387 | assert(Enable && "Cannot disable opaque pointers" ); |
388 | } |
389 | |
390 | bool LLVMContext::supportsTypedPointers() const { |
391 | return false; |
392 | } |
393 | |
394 | StringRef LLVMContext::getDefaultTargetCPU() { |
395 | return pImpl->DefaultTargetCPU; |
396 | } |
397 | |
398 | void LLVMContext::setDefaultTargetCPU(StringRef CPU) { |
399 | pImpl->DefaultTargetCPU = CPU; |
400 | } |
401 | |
402 | StringRef LLVMContext::getDefaultTargetFeatures() { |
403 | return pImpl->DefaultTargetFeatures; |
404 | } |
405 | |
406 | void LLVMContext::setDefaultTargetFeatures(StringRef Features) { |
407 | pImpl->DefaultTargetFeatures = Features; |
408 | } |
409 | |