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