1 //===-- LLVMContext.cpp - Implement LLVMContext ---------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements LLVMContext, as a wrapper around the opaque
10 // class LLVMContextImpl.
12 //===----------------------------------------------------------------------===//
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"
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
43 for (auto &MDKind
: MDKinds
) {
44 unsigned ID
= getMDKindID(MDKind
.second
);
45 assert(ID
== MDKind
.first
&& "metadata kind id drifted");
49 auto *DeoptEntry
= pImpl
->getOrInsertBundleTag("deopt");
50 assert(DeoptEntry
->second
== LLVMContext::OB_deopt
&&
51 "deopt operand bundle id drifted!");
54 auto *FuncletEntry
= pImpl
->getOrInsertBundleTag("funclet");
55 assert(FuncletEntry
->second
== LLVMContext::OB_funclet
&&
56 "funclet operand bundle id drifted!");
59 auto *GCTransitionEntry
= pImpl
->getOrInsertBundleTag("gc-transition");
60 assert(GCTransitionEntry
->second
== LLVMContext::OB_gc_transition
&&
61 "gc-transition operand bundle id drifted!");
62 (void)GCTransitionEntry
;
64 auto *CFGuardTargetEntry
= pImpl
->getOrInsertBundleTag("cfguardtarget");
65 assert(CFGuardTargetEntry
->second
== LLVMContext::OB_cfguardtarget
&&
66 "cfguardtarget operand bundle id drifted!");
67 (void)CFGuardTargetEntry
;
69 auto *PreallocatedEntry
= pImpl
->getOrInsertBundleTag("preallocated");
70 assert(PreallocatedEntry
->second
== LLVMContext::OB_preallocated
&&
71 "preallocated operand bundle id drifted!");
72 (void)PreallocatedEntry
;
74 auto *GCLiveEntry
= pImpl
->getOrInsertBundleTag("gc-live");
75 assert(GCLiveEntry
->second
== LLVMContext::OB_gc_live
&&
76 "gc-transition operand bundle id drifted!");
79 auto *ClangAttachedCall
=
80 pImpl
->getOrInsertBundleTag("clang.arc.attachedcall");
81 assert(ClangAttachedCall
->second
== LLVMContext::OB_clang_arc_attachedcall
&&
82 "clang.arc.attachedcall operand bundle id drifted!");
83 (void)ClangAttachedCall
;
85 auto *PtrauthEntry
= pImpl
->getOrInsertBundleTag("ptrauth");
86 assert(PtrauthEntry
->second
== LLVMContext::OB_ptrauth
&&
87 "ptrauth operand bundle id drifted!");
90 auto *KCFIEntry
= pImpl
->getOrInsertBundleTag("kcfi");
91 assert(KCFIEntry
->second
== LLVMContext::OB_kcfi
&&
92 "kcfi operand bundle id drifted!");
95 auto *ConvergenceCtrlEntry
= pImpl
->getOrInsertBundleTag("convergencectrl");
96 assert(ConvergenceCtrlEntry
->second
== LLVMContext::OB_convergencectrl
&&
97 "convergencectrl operand bundle id drifted!");
98 (void)ConvergenceCtrlEntry
;
100 SyncScope::ID SingleThreadSSID
=
101 pImpl
->getOrInsertSyncScopeID("singlethread");
102 assert(SingleThreadSSID
== SyncScope::SingleThread
&&
103 "singlethread synchronization scope ID drifted!");
104 (void)SingleThreadSSID
;
106 SyncScope::ID SystemSSID
=
107 pImpl
->getOrInsertSyncScopeID("");
108 assert(SystemSSID
== SyncScope::System
&&
109 "system synchronization scope ID drifted!");
113 LLVMContext::~LLVMContext() { delete pImpl
; }
115 void LLVMContext::addModule(Module
*M
) {
116 pImpl
->OwnedModules
.insert(M
);
119 void LLVMContext::removeModule(Module
*M
) {
120 pImpl
->OwnedModules
.erase(M
);
123 //===----------------------------------------------------------------------===//
124 // Recoverable Backend Errors
125 //===----------------------------------------------------------------------===//
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
;
135 void LLVMContext::setDiagnosticHandler(std::unique_ptr
<DiagnosticHandler
> &&DH
,
136 bool RespectFilters
) {
137 pImpl
->DiagHandler
= std::move(DH
);
138 pImpl
->RespectDiagnosticFilters
= RespectFilters
;
141 void LLVMContext::setDiagnosticsHotnessRequested(bool Requested
) {
142 pImpl
->DiagnosticsHotnessRequested
= Requested
;
144 bool LLVMContext::getDiagnosticsHotnessRequested() const {
145 return pImpl
->DiagnosticsHotnessRequested
;
148 void LLVMContext::setDiagnosticsHotnessThreshold(std::optional
<uint64_t> Threshold
) {
149 pImpl
->DiagnosticsHotnessThreshold
= Threshold
;
151 void LLVMContext::setMisExpectWarningRequested(bool Requested
) {
152 pImpl
->MisExpectWarningRequested
= Requested
;
154 bool LLVMContext::getMisExpectWarningRequested() const {
155 return pImpl
->MisExpectWarningRequested
;
157 uint64_t LLVMContext::getDiagnosticsHotnessThreshold() const {
158 return pImpl
->DiagnosticsHotnessThreshold
.value_or(UINT64_MAX
);
160 void LLVMContext::setDiagnosticsMisExpectTolerance(
161 std::optional
<uint32_t> Tolerance
) {
162 pImpl
->DiagnosticsMisExpectTolerance
= Tolerance
;
164 uint32_t LLVMContext::getDiagnosticsMisExpectTolerance() const {
165 return pImpl
->DiagnosticsMisExpectTolerance
.value_or(0);
168 bool LLVMContext::isDiagnosticsHotnessThresholdSetFromPSI() const {
169 return !pImpl
->DiagnosticsHotnessThreshold
.has_value();
172 remarks::RemarkStreamer
*LLVMContext::getMainRemarkStreamer() {
173 return pImpl
->MainRemarkStreamer
.get();
175 const remarks::RemarkStreamer
*LLVMContext::getMainRemarkStreamer() const {
176 return const_cast<LLVMContext
*>(this)->getMainRemarkStreamer();
178 void LLVMContext::setMainRemarkStreamer(
179 std::unique_ptr
<remarks::RemarkStreamer
> RemarkStreamer
) {
180 pImpl
->MainRemarkStreamer
= std::move(RemarkStreamer
);
183 LLVMRemarkStreamer
*LLVMContext::getLLVMRemarkStreamer() {
184 return pImpl
->LLVMRS
.get();
186 const LLVMRemarkStreamer
*LLVMContext::getLLVMRemarkStreamer() const {
187 return const_cast<LLVMContext
*>(this)->getLLVMRemarkStreamer();
189 void LLVMContext::setLLVMRemarkStreamer(
190 std::unique_ptr
<LLVMRemarkStreamer
> RemarkStreamer
) {
191 pImpl
->LLVMRS
= std::move(RemarkStreamer
);
194 DiagnosticHandler::DiagnosticHandlerTy
195 LLVMContext::getDiagnosticHandlerCallBack() const {
196 return pImpl
->DiagHandler
->DiagHandlerCallback
;
199 void *LLVMContext::getDiagnosticContext() const {
200 return pImpl
->DiagHandler
->DiagnosticContext
;
203 void LLVMContext::setYieldCallback(YieldCallbackTy Callback
, void *OpaqueHandle
)
205 pImpl
->YieldCallback
= Callback
;
206 pImpl
->YieldOpaqueHandle
= OpaqueHandle
;
209 void LLVMContext::yield() {
210 if (pImpl
->YieldCallback
)
211 pImpl
->YieldCallback(this, pImpl
->YieldOpaqueHandle
);
214 void LLVMContext::emitError(const Twine
&ErrorStr
) {
215 diagnose(DiagnosticInfoInlineAsm(ErrorStr
));
218 void LLVMContext::emitError(const Instruction
*I
, const Twine
&ErrorStr
) {
219 assert (I
&& "Invalid instruction");
220 diagnose(DiagnosticInfoInlineAsm(*I
, ErrorStr
));
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.
229 // Also noisy remarks are only enabled if we have hotness information to sort
231 if (auto *Remark
= dyn_cast
<DiagnosticInfoOptimizationBase
>(&DI
))
232 return Remark
->isEnabled() &&
233 (!Remark
->isVerbose() || Remark
->getHotness());
239 LLVMContext::getDiagnosticMessagePrefix(DiagnosticSeverity Severity
) {
250 llvm_unreachable("Unknown DiagnosticSeverity");
253 void LLVMContext::diagnose(const DiagnosticInfo
&DI
) {
254 if (auto *OptDiagBase
= dyn_cast
<DiagnosticInfoOptimizationBase
>(&DI
))
255 if (LLVMRemarkStreamer
*RS
= getLLVMRemarkStreamer())
256 RS
->emit(*OptDiagBase
);
258 // If there is a report handler, use it.
259 if (pImpl
->DiagHandler
&&
260 (!pImpl
->RespectDiagnosticFilters
|| isDiagnosticEnabled(DI
)) &&
261 pImpl
->DiagHandler
->handleDiagnostics(DI
))
264 if (!isDiagnosticEnabled(DI
))
267 // Otherwise, print the message with a prefix based on the severity.
268 DiagnosticPrinterRawOStream
DP(errs());
269 errs() << getDiagnosticMessagePrefix(DI
.getSeverity()) << ": ";
272 if (DI
.getSeverity() == DS_Error
)
276 void LLVMContext::emitError(uint64_t LocCookie
, const Twine
&ErrorStr
) {
277 diagnose(DiagnosticInfoInlineAsm(LocCookie
, ErrorStr
));
280 //===----------------------------------------------------------------------===//
281 // Metadata Kind Uniquing
282 //===----------------------------------------------------------------------===//
284 /// Return a unique non-zero ID for the specified metadata kind.
285 unsigned LLVMContext::getMDKindID(StringRef Name
) const {
286 // If this is new, assign it its ID.
287 return pImpl
->CustomMDKindNames
.insert(
289 Name
, pImpl
->CustomMDKindNames
.size()))
293 /// getHandlerNames - Populate client-supplied smallvector using custom
294 /// metadata name and ID.
295 void LLVMContext::getMDKindNames(SmallVectorImpl
<StringRef
> &Names
) const {
296 Names
.resize(pImpl
->CustomMDKindNames
.size());
297 for (StringMap
<unsigned>::const_iterator I
= pImpl
->CustomMDKindNames
.begin(),
298 E
= pImpl
->CustomMDKindNames
.end(); I
!= E
; ++I
)
299 Names
[I
->second
] = I
->first();
302 void LLVMContext::getOperandBundleTags(SmallVectorImpl
<StringRef
> &Tags
) const {
303 pImpl
->getOperandBundleTags(Tags
);
306 StringMapEntry
<uint32_t> *
307 LLVMContext::getOrInsertBundleTag(StringRef TagName
) const {
308 return pImpl
->getOrInsertBundleTag(TagName
);
311 uint32_t LLVMContext::getOperandBundleTagID(StringRef Tag
) const {
312 return pImpl
->getOperandBundleTagID(Tag
);
315 SyncScope::ID
LLVMContext::getOrInsertSyncScopeID(StringRef SSN
) {
316 return pImpl
->getOrInsertSyncScopeID(SSN
);
319 void LLVMContext::getSyncScopeNames(SmallVectorImpl
<StringRef
> &SSNs
) const {
320 pImpl
->getSyncScopeNames(SSNs
);
323 void LLVMContext::setGC(const Function
&Fn
, std::string GCName
) {
324 auto It
= pImpl
->GCNames
.find(&Fn
);
326 if (It
== pImpl
->GCNames
.end()) {
327 pImpl
->GCNames
.insert(std::make_pair(&Fn
, std::move(GCName
)));
330 It
->second
= std::move(GCName
);
333 const std::string
&LLVMContext::getGC(const Function
&Fn
) {
334 return pImpl
->GCNames
[&Fn
];
337 void LLVMContext::deleteGC(const Function
&Fn
) {
338 pImpl
->GCNames
.erase(&Fn
);
341 bool LLVMContext::shouldDiscardValueNames() const {
342 return pImpl
->DiscardValueNames
;
345 bool LLVMContext::isODRUniquingDebugTypes() const { return !!pImpl
->DITypeMap
; }
347 void LLVMContext::enableDebugTypeODRUniquing() {
348 if (pImpl
->DITypeMap
)
351 pImpl
->DITypeMap
.emplace();
354 void LLVMContext::disableDebugTypeODRUniquing() { pImpl
->DITypeMap
.reset(); }
356 void LLVMContext::setDiscardValueNames(bool Discard
) {
357 pImpl
->DiscardValueNames
= Discard
;
360 OptPassGate
&LLVMContext::getOptPassGate() const {
361 return pImpl
->getOptPassGate();
364 void LLVMContext::setOptPassGate(OptPassGate
& OPG
) {
365 pImpl
->setOptPassGate(OPG
);
368 const DiagnosticHandler
*LLVMContext::getDiagHandlerPtr() const {
369 return pImpl
->DiagHandler
.get();
372 std::unique_ptr
<DiagnosticHandler
> LLVMContext::getDiagnosticHandler() {
373 return std::move(pImpl
->DiagHandler
);
376 void LLVMContext::setOpaquePointers(bool Enable
) const {
377 assert(Enable
&& "Cannot disable opaque pointers");
380 bool LLVMContext::supportsTypedPointers() const {