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