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