1 //===-- LLVMContext.cpp - Implement LLVMContext ---------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements LLVMContext, as a wrapper around the opaque 11 // class LLVMContextImpl. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/IR/LLVMContext.h" 16 #include "LLVMContextImpl.h" 17 #include "llvm/ADT/SmallVector.h" 18 #include "llvm/ADT/StringMap.h" 19 #include "llvm/ADT/StringRef.h" 20 #include "llvm/ADT/Twine.h" 21 #include "llvm/IR/DiagnosticInfo.h" 22 #include "llvm/IR/DiagnosticPrinter.h" 23 #include "llvm/IR/Metadata.h" 24 #include "llvm/IR/Module.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 }; 63 64 for (auto &MDKind : MDKinds) { 65 unsigned ID = getMDKindID(MDKind.second); 66 assert(ID == MDKind.first && "metadata kind id drifted"); 67 (void)ID; 68 } 69 70 auto *DeoptEntry = pImpl->getOrInsertBundleTag("deopt"); 71 assert(DeoptEntry->second == LLVMContext::OB_deopt && 72 "deopt operand bundle id drifted!"); 73 (void)DeoptEntry; 74 75 auto *FuncletEntry = pImpl->getOrInsertBundleTag("funclet"); 76 assert(FuncletEntry->second == LLVMContext::OB_funclet && 77 "funclet operand bundle id drifted!"); 78 (void)FuncletEntry; 79 80 auto *GCTransitionEntry = pImpl->getOrInsertBundleTag("gc-transition"); 81 assert(GCTransitionEntry->second == LLVMContext::OB_gc_transition && 82 "gc-transition operand bundle id drifted!"); 83 (void)GCTransitionEntry; 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 } 107 108 //===----------------------------------------------------------------------===// 109 // Recoverable Backend Errors 110 //===----------------------------------------------------------------------===// 111 112 void LLVMContext:: 113 setInlineAsmDiagnosticHandler(InlineAsmDiagHandlerTy DiagHandler, 114 void *DiagContext) { 115 pImpl->InlineAsmDiagHandler = DiagHandler; 116 pImpl->InlineAsmDiagContext = DiagContext; 117 } 118 119 /// getInlineAsmDiagnosticHandler - Return the diagnostic handler set by 120 /// setInlineAsmDiagnosticHandler. 121 LLVMContext::InlineAsmDiagHandlerTy 122 LLVMContext::getInlineAsmDiagnosticHandler() const { 123 return pImpl->InlineAsmDiagHandler; 124 } 125 126 /// getInlineAsmDiagnosticContext - Return the diagnostic context set by 127 /// setInlineAsmDiagnosticHandler. 128 void *LLVMContext::getInlineAsmDiagnosticContext() const { 129 return pImpl->InlineAsmDiagContext; 130 } 131 132 void LLVMContext::setDiagnosticHandlerCallBack( 133 DiagnosticHandler::DiagnosticHandlerTy DiagnosticHandler, 134 void *DiagnosticContext, bool RespectFilters) { 135 pImpl->DiagHandler->DiagHandlerCallback = DiagnosticHandler; 136 pImpl->DiagHandler->DiagnosticContext = DiagnosticContext; 137 pImpl->RespectDiagnosticFilters = RespectFilters; 138 } 139 140 void LLVMContext::setDiagnosticHandler(std::unique_ptr<DiagnosticHandler> &&DH, 141 bool RespectFilters) { 142 pImpl->DiagHandler = std::move(DH); 143 pImpl->RespectDiagnosticFilters = RespectFilters; 144 } 145 146 void LLVMContext::setDiagnosticsHotnessRequested(bool Requested) { 147 pImpl->DiagnosticsHotnessRequested = Requested; 148 } 149 bool LLVMContext::getDiagnosticsHotnessRequested() const { 150 return pImpl->DiagnosticsHotnessRequested; 151 } 152 153 void LLVMContext::setDiagnosticsHotnessThreshold(uint64_t Threshold) { 154 pImpl->DiagnosticsHotnessThreshold = Threshold; 155 } 156 uint64_t LLVMContext::getDiagnosticsHotnessThreshold() const { 157 return pImpl->DiagnosticsHotnessThreshold; 158 } 159 160 yaml::Output *LLVMContext::getDiagnosticsOutputFile() { 161 return pImpl->DiagnosticsOutputFile.get(); 162 } 163 164 void LLVMContext::setDiagnosticsOutputFile(std::unique_ptr<yaml::Output> F) { 165 pImpl->DiagnosticsOutputFile = std::move(F); 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 if (auto *Remark = dyn_cast<DiagnosticInfoOptimizationBase>(&DI)) 203 return Remark->isEnabled(); 204 205 return true; 206 } 207 208 const char * 209 LLVMContext::getDiagnosticMessagePrefix(DiagnosticSeverity Severity) { 210 switch (Severity) { 211 case DS_Error: 212 return "error"; 213 case DS_Warning: 214 return "warning"; 215 case DS_Remark: 216 return "remark"; 217 case DS_Note: 218 return "note"; 219 } 220 llvm_unreachable("Unknown DiagnosticSeverity"); 221 } 222 223 void LLVMContext::diagnose(const DiagnosticInfo &DI) { 224 // If there is a report handler, use it. 225 if (pImpl->DiagHandler && 226 (!pImpl->RespectDiagnosticFilters || isDiagnosticEnabled(DI)) && 227 pImpl->DiagHandler->handleDiagnostics(DI)) 228 return; 229 230 if (!isDiagnosticEnabled(DI)) 231 return; 232 233 // Otherwise, print the message with a prefix based on the severity. 234 DiagnosticPrinterRawOStream DP(errs()); 235 errs() << getDiagnosticMessagePrefix(DI.getSeverity()) << ": "; 236 DI.print(DP); 237 errs() << "\n"; 238 if (DI.getSeverity() == DS_Error) 239 exit(1); 240 } 241 242 void LLVMContext::emitError(unsigned LocCookie, const Twine &ErrorStr) { 243 diagnose(DiagnosticInfoInlineAsm(LocCookie, ErrorStr)); 244 } 245 246 //===----------------------------------------------------------------------===// 247 // Metadata Kind Uniquing 248 //===----------------------------------------------------------------------===// 249 250 /// Return a unique non-zero ID for the specified metadata kind. 251 unsigned LLVMContext::getMDKindID(StringRef Name) const { 252 // If this is new, assign it its ID. 253 return pImpl->CustomMDKindNames.insert( 254 std::make_pair( 255 Name, pImpl->CustomMDKindNames.size())) 256 .first->second; 257 } 258 259 /// getHandlerNames - Populate client-supplied smallvector using custom 260 /// metadata name and ID. 261 void LLVMContext::getMDKindNames(SmallVectorImpl<StringRef> &Names) const { 262 Names.resize(pImpl->CustomMDKindNames.size()); 263 for (StringMap<unsigned>::const_iterator I = pImpl->CustomMDKindNames.begin(), 264 E = pImpl->CustomMDKindNames.end(); I != E; ++I) 265 Names[I->second] = I->first(); 266 } 267 268 void LLVMContext::getOperandBundleTags(SmallVectorImpl<StringRef> &Tags) const { 269 pImpl->getOperandBundleTags(Tags); 270 } 271 272 uint32_t LLVMContext::getOperandBundleTagID(StringRef Tag) const { 273 return pImpl->getOperandBundleTagID(Tag); 274 } 275 276 SyncScope::ID LLVMContext::getOrInsertSyncScopeID(StringRef SSN) { 277 return pImpl->getOrInsertSyncScopeID(SSN); 278 } 279 280 void LLVMContext::getSyncScopeNames(SmallVectorImpl<StringRef> &SSNs) const { 281 pImpl->getSyncScopeNames(SSNs); 282 } 283 284 void LLVMContext::setGC(const Function &Fn, std::string GCName) { 285 auto It = pImpl->GCNames.find(&Fn); 286 287 if (It == pImpl->GCNames.end()) { 288 pImpl->GCNames.insert(std::make_pair(&Fn, std::move(GCName))); 289 return; 290 } 291 It->second = std::move(GCName); 292 } 293 294 const std::string &LLVMContext::getGC(const Function &Fn) { 295 return pImpl->GCNames[&Fn]; 296 } 297 298 void LLVMContext::deleteGC(const Function &Fn) { 299 pImpl->GCNames.erase(&Fn); 300 } 301 302 bool LLVMContext::shouldDiscardValueNames() const { 303 return pImpl->DiscardValueNames; 304 } 305 306 bool LLVMContext::isODRUniquingDebugTypes() const { return !!pImpl->DITypeMap; } 307 308 void LLVMContext::enableDebugTypeODRUniquing() { 309 if (pImpl->DITypeMap) 310 return; 311 312 pImpl->DITypeMap.emplace(); 313 } 314 315 void LLVMContext::disableDebugTypeODRUniquing() { pImpl->DITypeMap.reset(); } 316 317 void LLVMContext::setDiscardValueNames(bool Discard) { 318 pImpl->DiscardValueNames = Discard; 319 } 320 321 OptBisect &LLVMContext::getOptBisect() { 322 return pImpl->getOptBisect(); 323 } 324 325 const DiagnosticHandler *LLVMContext::getDiagHandlerPtr() const { 326 return pImpl->DiagHandler.get(); 327 } 328 329 std::unique_ptr<DiagnosticHandler> LLVMContext::getDiagnosticHandler() { 330 return std::move(pImpl->DiagHandler); 331 } 332