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(MDKind.second); 45 assert(ID == MDKind.first && "metadata kind id drifted"); 46 (void)ID; 47 } 48 49 auto *DeoptEntry = pImpl->getOrInsertBundleTag("deopt"); 50 assert(DeoptEntry->second == LLVMContext::OB_deopt && 51 "deopt operand bundle id drifted!"); 52 (void)DeoptEntry; 53 54 auto *FuncletEntry = pImpl->getOrInsertBundleTag("funclet"); 55 assert(FuncletEntry->second == LLVMContext::OB_funclet && 56 "funclet operand bundle id drifted!"); 57 (void)FuncletEntry; 58 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; 63 64 auto *CFGuardTargetEntry = pImpl->getOrInsertBundleTag("cfguardtarget"); 65 assert(CFGuardTargetEntry->second == LLVMContext::OB_cfguardtarget && 66 "cfguardtarget operand bundle id drifted!"); 67 (void)CFGuardTargetEntry; 68 69 auto *PreallocatedEntry = pImpl->getOrInsertBundleTag("preallocated"); 70 assert(PreallocatedEntry->second == LLVMContext::OB_preallocated && 71 "preallocated operand bundle id drifted!"); 72 (void)PreallocatedEntry; 73 74 auto *GCLiveEntry = pImpl->getOrInsertBundleTag("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("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 SyncScope::ID SingleThreadSSID = 86 pImpl->getOrInsertSyncScopeID("singlethread"); 87 assert(SingleThreadSSID == SyncScope::SingleThread && 88 "singlethread synchronization scope ID drifted!"); 89 (void)SingleThreadSSID; 90 91 SyncScope::ID SystemSSID = 92 pImpl->getOrInsertSyncScopeID(""); 93 assert(SystemSSID == SyncScope::System && 94 "system synchronization scope ID drifted!"); 95 (void)SystemSSID; 96 } 97 98 LLVMContext::~LLVMContext() { delete pImpl; } 99 100 void LLVMContext::addModule(Module *M) { 101 pImpl->OwnedModules.insert(M); 102 } 103 104 void LLVMContext::removeModule(Module *M) { 105 pImpl->OwnedModules.erase(M); 106 } 107 108 //===----------------------------------------------------------------------===// 109 // Recoverable Backend Errors 110 //===----------------------------------------------------------------------===// 111 112 void LLVMContext::setDiagnosticHandlerCallBack( 113 DiagnosticHandler::DiagnosticHandlerTy DiagnosticHandler, 114 void *DiagnosticContext, bool RespectFilters) { 115 pImpl->DiagHandler->DiagHandlerCallback = DiagnosticHandler; 116 pImpl->DiagHandler->DiagnosticContext = DiagnosticContext; 117 pImpl->RespectDiagnosticFilters = RespectFilters; 118 } 119 120 void LLVMContext::setDiagnosticHandler(std::unique_ptr<DiagnosticHandler> &&DH, 121 bool RespectFilters) { 122 pImpl->DiagHandler = std::move(DH); 123 pImpl->RespectDiagnosticFilters = RespectFilters; 124 } 125 126 void LLVMContext::setDiagnosticsHotnessRequested(bool Requested) { 127 pImpl->DiagnosticsHotnessRequested = Requested; 128 } 129 bool LLVMContext::getDiagnosticsHotnessRequested() const { 130 return pImpl->DiagnosticsHotnessRequested; 131 } 132 133 void LLVMContext::setDiagnosticsHotnessThreshold(Optional<uint64_t> Threshold) { 134 pImpl->DiagnosticsHotnessThreshold = Threshold; 135 } 136 137 uint64_t LLVMContext::getDiagnosticsHotnessThreshold() const { 138 return pImpl->DiagnosticsHotnessThreshold.getValueOr(UINT64_MAX); 139 } 140 141 bool LLVMContext::isDiagnosticsHotnessThresholdSetFromPSI() const { 142 return !pImpl->DiagnosticsHotnessThreshold.hasValue(); 143 } 144 145 remarks::RemarkStreamer *LLVMContext::getMainRemarkStreamer() { 146 return pImpl->MainRemarkStreamer.get(); 147 } 148 const remarks::RemarkStreamer *LLVMContext::getMainRemarkStreamer() const { 149 return const_cast<LLVMContext *>(this)->getMainRemarkStreamer(); 150 } 151 void LLVMContext::setMainRemarkStreamer( 152 std::unique_ptr<remarks::RemarkStreamer> RemarkStreamer) { 153 pImpl->MainRemarkStreamer = std::move(RemarkStreamer); 154 } 155 156 LLVMRemarkStreamer *LLVMContext::getLLVMRemarkStreamer() { 157 return pImpl->LLVMRS.get(); 158 } 159 const LLVMRemarkStreamer *LLVMContext::getLLVMRemarkStreamer() const { 160 return const_cast<LLVMContext *>(this)->getLLVMRemarkStreamer(); 161 } 162 void LLVMContext::setLLVMRemarkStreamer( 163 std::unique_ptr<LLVMRemarkStreamer> RemarkStreamer) { 164 pImpl->LLVMRS = std::move(RemarkStreamer); 165 } 166 167 DiagnosticHandler::DiagnosticHandlerTy 168 LLVMContext::getDiagnosticHandlerCallBack() const { 169 return pImpl->DiagHandler->DiagHandlerCallback; 170 } 171 172 void *LLVMContext::getDiagnosticContext() const { 173 return pImpl->DiagHandler->DiagnosticContext; 174 } 175 176 void LLVMContext::setYieldCallback(YieldCallbackTy Callback, void *OpaqueHandle) 177 { 178 pImpl->YieldCallback = Callback; 179 pImpl->YieldOpaqueHandle = OpaqueHandle; 180 } 181 182 void LLVMContext::yield() { 183 if (pImpl->YieldCallback) 184 pImpl->YieldCallback(this, pImpl->YieldOpaqueHandle); 185 } 186 187 void LLVMContext::emitError(const Twine &ErrorStr) { 188 diagnose(DiagnosticInfoInlineAsm(ErrorStr)); 189 } 190 191 void LLVMContext::emitError(const Instruction *I, const Twine &ErrorStr) { 192 assert (I && "Invalid instruction"); 193 diagnose(DiagnosticInfoInlineAsm(*I, ErrorStr)); 194 } 195 196 static bool isDiagnosticEnabled(const DiagnosticInfo &DI) { 197 // Optimization remarks are selective. They need to check whether the regexp 198 // pattern, passed via one of the -pass-remarks* flags, matches the name of 199 // the pass that is emitting the diagnostic. If there is no match, ignore the 200 // diagnostic and return. 201 // 202 // Also noisy remarks are only enabled if we have hotness information to sort 203 // them. 204 if (auto *Remark = dyn_cast<DiagnosticInfoOptimizationBase>(&DI)) 205 return Remark->isEnabled() && 206 (!Remark->isVerbose() || Remark->getHotness()); 207 208 return true; 209 } 210 211 const char * 212 LLVMContext::getDiagnosticMessagePrefix(DiagnosticSeverity Severity) { 213 switch (Severity) { 214 case DS_Error: 215 return "error"; 216 case DS_Warning: 217 return "warning"; 218 case DS_Remark: 219 return "remark"; 220 case DS_Note: 221 return "note"; 222 } 223 llvm_unreachable("Unknown DiagnosticSeverity"); 224 } 225 226 void LLVMContext::diagnose(const DiagnosticInfo &DI) { 227 if (auto *OptDiagBase = dyn_cast<DiagnosticInfoOptimizationBase>(&DI)) 228 if (LLVMRemarkStreamer *RS = getLLVMRemarkStreamer()) 229 RS->emit(*OptDiagBase); 230 231 // If there is a report handler, use it. 232 if (pImpl->DiagHandler && 233 (!pImpl->RespectDiagnosticFilters || isDiagnosticEnabled(DI)) && 234 pImpl->DiagHandler->handleDiagnostics(DI)) 235 return; 236 237 if (!isDiagnosticEnabled(DI)) 238 return; 239 240 // Otherwise, print the message with a prefix based on the severity. 241 DiagnosticPrinterRawOStream DP(errs()); 242 errs() << getDiagnosticMessagePrefix(DI.getSeverity()) << ": "; 243 DI.print(DP); 244 errs() << "\n"; 245 if (DI.getSeverity() == DS_Error) 246 exit(1); 247 } 248 249 void LLVMContext::emitError(uint64_t LocCookie, const Twine &ErrorStr) { 250 diagnose(DiagnosticInfoInlineAsm(LocCookie, ErrorStr)); 251 } 252 253 //===----------------------------------------------------------------------===// 254 // Metadata Kind Uniquing 255 //===----------------------------------------------------------------------===// 256 257 /// Return a unique non-zero ID for the specified metadata kind. 258 unsigned LLVMContext::getMDKindID(StringRef Name) const { 259 // If this is new, assign it its ID. 260 return pImpl->CustomMDKindNames.insert( 261 std::make_pair( 262 Name, pImpl->CustomMDKindNames.size())) 263 .first->second; 264 } 265 266 /// getHandlerNames - Populate client-supplied smallvector using custom 267 /// metadata name and ID. 268 void LLVMContext::getMDKindNames(SmallVectorImpl<StringRef> &Names) const { 269 Names.resize(pImpl->CustomMDKindNames.size()); 270 for (StringMap<unsigned>::const_iterator I = pImpl->CustomMDKindNames.begin(), 271 E = pImpl->CustomMDKindNames.end(); I != E; ++I) 272 Names[I->second] = I->first(); 273 } 274 275 void LLVMContext::getOperandBundleTags(SmallVectorImpl<StringRef> &Tags) const { 276 pImpl->getOperandBundleTags(Tags); 277 } 278 279 StringMapEntry<uint32_t> * 280 LLVMContext::getOrInsertBundleTag(StringRef TagName) const { 281 return pImpl->getOrInsertBundleTag(TagName); 282 } 283 284 uint32_t LLVMContext::getOperandBundleTagID(StringRef Tag) const { 285 return pImpl->getOperandBundleTagID(Tag); 286 } 287 288 SyncScope::ID LLVMContext::getOrInsertSyncScopeID(StringRef SSN) { 289 return pImpl->getOrInsertSyncScopeID(SSN); 290 } 291 292 void LLVMContext::getSyncScopeNames(SmallVectorImpl<StringRef> &SSNs) const { 293 pImpl->getSyncScopeNames(SSNs); 294 } 295 296 void LLVMContext::setGC(const Function &Fn, std::string GCName) { 297 auto It = pImpl->GCNames.find(&Fn); 298 299 if (It == pImpl->GCNames.end()) { 300 pImpl->GCNames.insert(std::make_pair(&Fn, std::move(GCName))); 301 return; 302 } 303 It->second = std::move(GCName); 304 } 305 306 const std::string &LLVMContext::getGC(const Function &Fn) { 307 return pImpl->GCNames[&Fn]; 308 } 309 310 void LLVMContext::deleteGC(const Function &Fn) { 311 pImpl->GCNames.erase(&Fn); 312 } 313 314 bool LLVMContext::shouldDiscardValueNames() const { 315 return pImpl->DiscardValueNames; 316 } 317 318 bool LLVMContext::isODRUniquingDebugTypes() const { return !!pImpl->DITypeMap; } 319 320 void LLVMContext::enableDebugTypeODRUniquing() { 321 if (pImpl->DITypeMap) 322 return; 323 324 pImpl->DITypeMap.emplace(); 325 } 326 327 void LLVMContext::disableDebugTypeODRUniquing() { pImpl->DITypeMap.reset(); } 328 329 void LLVMContext::setDiscardValueNames(bool Discard) { 330 pImpl->DiscardValueNames = Discard; 331 } 332 333 OptPassGate &LLVMContext::getOptPassGate() const { 334 return pImpl->getOptPassGate(); 335 } 336 337 void LLVMContext::setOptPassGate(OptPassGate& OPG) { 338 pImpl->setOptPassGate(OPG); 339 } 340 341 const DiagnosticHandler *LLVMContext::getDiagHandlerPtr() const { 342 return pImpl->DiagHandler.get(); 343 } 344 345 std::unique_ptr<DiagnosticHandler> LLVMContext::getDiagnosticHandler() { 346 return std::move(pImpl->DiagHandler); 347 } 348 349 void LLVMContext::enableOpaquePointers() const { 350 assert(pImpl->PointerTypes.empty() && pImpl->ASPointerTypes.empty() && 351 "Must be called before creating any pointer types"); 352 pImpl->setOpaquePointers(true); 353 } 354 355 bool LLVMContext::supportsTypedPointers() const { 356 return !pImpl->getOpaquePointers(); 357 } 358