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