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