| //===-- LLVMContext.cpp - Implement LLVMContext ---------------------------===// | 
 | // | 
 | //                     The LLVM Compiler Infrastructure | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 | // | 
 | //  This file implements LLVMContext, as a wrapper around the opaque | 
 | //  class LLVMContextImpl. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #include "llvm/IR/LLVMContext.h" | 
 | #include "LLVMContextImpl.h" | 
 | #include "llvm/ADT/SmallVector.h" | 
 | #include "llvm/ADT/StringMap.h" | 
 | #include "llvm/ADT/StringRef.h" | 
 | #include "llvm/ADT/Twine.h" | 
 | #include "llvm/IR/DiagnosticInfo.h" | 
 | #include "llvm/IR/DiagnosticPrinter.h" | 
 | #include "llvm/IR/Metadata.h" | 
 | #include "llvm/IR/Module.h" | 
 | #include "llvm/Support/Casting.h" | 
 | #include "llvm/Support/ErrorHandling.h" | 
 | #include "llvm/Support/raw_ostream.h" | 
 | #include <cassert> | 
 | #include <cstdlib> | 
 | #include <string> | 
 | #include <utility> | 
 |  | 
 | using namespace llvm; | 
 |  | 
 | LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) { | 
 |   // Create the fixed metadata kinds. This is done in the same order as the | 
 |   // MD_* enum values so that they correspond. | 
 |   std::pair<unsigned, StringRef> MDKinds[] = { | 
 |     {MD_dbg, "dbg"}, | 
 |     {MD_tbaa, "tbaa"}, | 
 |     {MD_prof, "prof"}, | 
 |     {MD_fpmath, "fpmath"}, | 
 |     {MD_range, "range"}, | 
 |     {MD_tbaa_struct, "tbaa.struct"}, | 
 |     {MD_invariant_load, "invariant.load"}, | 
 |     {MD_alias_scope, "alias.scope"}, | 
 |     {MD_noalias, "noalias"}, | 
 |     {MD_nontemporal, "nontemporal"}, | 
 |     {MD_mem_parallel_loop_access, "llvm.mem.parallel_loop_access"}, | 
 |     {MD_nonnull, "nonnull"}, | 
 |     {MD_dereferenceable, "dereferenceable"}, | 
 |     {MD_dereferenceable_or_null, "dereferenceable_or_null"}, | 
 |     {MD_make_implicit, "make.implicit"}, | 
 |     {MD_unpredictable, "unpredictable"}, | 
 |     {MD_invariant_group, "invariant.group"}, | 
 |     {MD_align, "align"}, | 
 |     {MD_loop, "llvm.loop"}, | 
 |     {MD_type, "type"}, | 
 |     {MD_section_prefix, "section_prefix"}, | 
 |     {MD_absolute_symbol, "absolute_symbol"}, | 
 |     {MD_associated, "associated"}, | 
 |     {MD_callees, "callees"}, | 
 |     {MD_irr_loop, "irr_loop"}, | 
 |     {MD_access_group, "llvm.access.group"}, | 
 |   }; | 
 |  | 
 |   for (auto &MDKind : MDKinds) { | 
 |     unsigned ID = getMDKindID(MDKind.second); | 
 |     assert(ID == MDKind.first && "metadata kind id drifted"); | 
 |     (void)ID; | 
 |   } | 
 |  | 
 |   auto *DeoptEntry = pImpl->getOrInsertBundleTag("deopt"); | 
 |   assert(DeoptEntry->second == LLVMContext::OB_deopt && | 
 |          "deopt operand bundle id drifted!"); | 
 |   (void)DeoptEntry; | 
 |  | 
 |   auto *FuncletEntry = pImpl->getOrInsertBundleTag("funclet"); | 
 |   assert(FuncletEntry->second == LLVMContext::OB_funclet && | 
 |          "funclet operand bundle id drifted!"); | 
 |   (void)FuncletEntry; | 
 |  | 
 |   auto *GCTransitionEntry = pImpl->getOrInsertBundleTag("gc-transition"); | 
 |   assert(GCTransitionEntry->second == LLVMContext::OB_gc_transition && | 
 |          "gc-transition operand bundle id drifted!"); | 
 |   (void)GCTransitionEntry; | 
 |  | 
 |   SyncScope::ID SingleThreadSSID = | 
 |       pImpl->getOrInsertSyncScopeID("singlethread"); | 
 |   assert(SingleThreadSSID == SyncScope::SingleThread && | 
 |          "singlethread synchronization scope ID drifted!"); | 
 |   (void)SingleThreadSSID; | 
 |  | 
 |   SyncScope::ID SystemSSID = | 
 |       pImpl->getOrInsertSyncScopeID(""); | 
 |   assert(SystemSSID == SyncScope::System && | 
 |          "system synchronization scope ID drifted!"); | 
 |   (void)SystemSSID; | 
 | } | 
 |  | 
 | LLVMContext::~LLVMContext() { delete pImpl; } | 
 |  | 
 | void LLVMContext::addModule(Module *M) { | 
 |   pImpl->OwnedModules.insert(M); | 
 | } | 
 |  | 
 | void LLVMContext::removeModule(Module *M) { | 
 |   pImpl->OwnedModules.erase(M); | 
 | } | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | // Recoverable Backend Errors | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | void LLVMContext:: | 
 | setInlineAsmDiagnosticHandler(InlineAsmDiagHandlerTy DiagHandler, | 
 |                               void *DiagContext) { | 
 |   pImpl->InlineAsmDiagHandler = DiagHandler; | 
 |   pImpl->InlineAsmDiagContext = DiagContext; | 
 | } | 
 |  | 
 | /// getInlineAsmDiagnosticHandler - Return the diagnostic handler set by | 
 | /// setInlineAsmDiagnosticHandler. | 
 | LLVMContext::InlineAsmDiagHandlerTy | 
 | LLVMContext::getInlineAsmDiagnosticHandler() const { | 
 |   return pImpl->InlineAsmDiagHandler; | 
 | } | 
 |  | 
 | /// getInlineAsmDiagnosticContext - Return the diagnostic context set by | 
 | /// setInlineAsmDiagnosticHandler. | 
 | void *LLVMContext::getInlineAsmDiagnosticContext() const { | 
 |   return pImpl->InlineAsmDiagContext; | 
 | } | 
 |  | 
 | void LLVMContext::setDiagnosticHandlerCallBack( | 
 |     DiagnosticHandler::DiagnosticHandlerTy DiagnosticHandler, | 
 |     void *DiagnosticContext, bool RespectFilters) { | 
 |   pImpl->DiagHandler->DiagHandlerCallback = DiagnosticHandler; | 
 |   pImpl->DiagHandler->DiagnosticContext = DiagnosticContext; | 
 |   pImpl->RespectDiagnosticFilters = RespectFilters; | 
 | } | 
 |  | 
 | void LLVMContext::setDiagnosticHandler(std::unique_ptr<DiagnosticHandler> &&DH, | 
 |                                       bool RespectFilters) { | 
 |   pImpl->DiagHandler = std::move(DH); | 
 |   pImpl->RespectDiagnosticFilters = RespectFilters; | 
 | } | 
 |  | 
 | void LLVMContext::setDiagnosticsHotnessRequested(bool Requested) { | 
 |   pImpl->DiagnosticsHotnessRequested = Requested; | 
 | } | 
 | bool LLVMContext::getDiagnosticsHotnessRequested() const { | 
 |   return pImpl->DiagnosticsHotnessRequested; | 
 | } | 
 |  | 
 | void LLVMContext::setDiagnosticsHotnessThreshold(uint64_t Threshold) { | 
 |   pImpl->DiagnosticsHotnessThreshold = Threshold; | 
 | } | 
 | uint64_t LLVMContext::getDiagnosticsHotnessThreshold() const { | 
 |   return pImpl->DiagnosticsHotnessThreshold; | 
 | } | 
 |  | 
 | yaml::Output *LLVMContext::getDiagnosticsOutputFile() { | 
 |   return pImpl->DiagnosticsOutputFile.get(); | 
 | } | 
 |  | 
 | void LLVMContext::setDiagnosticsOutputFile(std::unique_ptr<yaml::Output> F) { | 
 |   pImpl->DiagnosticsOutputFile = std::move(F); | 
 | } | 
 |  | 
 | DiagnosticHandler::DiagnosticHandlerTy | 
 | LLVMContext::getDiagnosticHandlerCallBack() const { | 
 |   return pImpl->DiagHandler->DiagHandlerCallback; | 
 | } | 
 |  | 
 | void *LLVMContext::getDiagnosticContext() const { | 
 |   return pImpl->DiagHandler->DiagnosticContext; | 
 | } | 
 |  | 
 | void LLVMContext::setYieldCallback(YieldCallbackTy Callback, void *OpaqueHandle) | 
 | { | 
 |   pImpl->YieldCallback = Callback; | 
 |   pImpl->YieldOpaqueHandle = OpaqueHandle; | 
 | } | 
 |  | 
 | void LLVMContext::yield() { | 
 |   if (pImpl->YieldCallback) | 
 |     pImpl->YieldCallback(this, pImpl->YieldOpaqueHandle); | 
 | } | 
 |  | 
 | void LLVMContext::emitError(const Twine &ErrorStr) { | 
 |   diagnose(DiagnosticInfoInlineAsm(ErrorStr)); | 
 | } | 
 |  | 
 | void LLVMContext::emitError(const Instruction *I, const Twine &ErrorStr) { | 
 |   assert (I && "Invalid instruction"); | 
 |   diagnose(DiagnosticInfoInlineAsm(*I, ErrorStr)); | 
 | } | 
 |  | 
 | static bool isDiagnosticEnabled(const DiagnosticInfo &DI) { | 
 |   // Optimization remarks are selective. They need to check whether the regexp | 
 |   // pattern, passed via one of the -pass-remarks* flags, matches the name of | 
 |   // the pass that is emitting the diagnostic. If there is no match, ignore the | 
 |   // diagnostic and return. | 
 |   // | 
 |   // Also noisy remarks are only enabled if we have hotness information to sort | 
 |   // them. | 
 |   if (auto *Remark = dyn_cast<DiagnosticInfoOptimizationBase>(&DI)) | 
 |     return Remark->isEnabled() && | 
 |            (!Remark->isVerbose() || Remark->getHotness()); | 
 |  | 
 |   return true; | 
 | } | 
 |  | 
 | const char * | 
 | LLVMContext::getDiagnosticMessagePrefix(DiagnosticSeverity Severity) { | 
 |   switch (Severity) { | 
 |   case DS_Error: | 
 |     return "error"; | 
 |   case DS_Warning: | 
 |     return "warning"; | 
 |   case DS_Remark: | 
 |     return "remark"; | 
 |   case DS_Note: | 
 |     return "note"; | 
 |   } | 
 |   llvm_unreachable("Unknown DiagnosticSeverity"); | 
 | } | 
 |  | 
 | void LLVMContext::diagnose(const DiagnosticInfo &DI) { | 
 |   if (auto *OptDiagBase = dyn_cast<DiagnosticInfoOptimizationBase>(&DI)) { | 
 |     yaml::Output *Out = getDiagnosticsOutputFile(); | 
 |     if (Out) { | 
 |       // For remarks the << operator takes a reference to a pointer. | 
 |       auto *P = const_cast<DiagnosticInfoOptimizationBase *>(OptDiagBase); | 
 |       *Out << P; | 
 |     } | 
 |   } | 
 |   // If there is a report handler, use it. | 
 |   if (pImpl->DiagHandler && | 
 |       (!pImpl->RespectDiagnosticFilters || isDiagnosticEnabled(DI)) && | 
 |       pImpl->DiagHandler->handleDiagnostics(DI)) | 
 |     return; | 
 |  | 
 |   if (!isDiagnosticEnabled(DI)) | 
 |     return; | 
 |  | 
 |   // Otherwise, print the message with a prefix based on the severity. | 
 |   DiagnosticPrinterRawOStream DP(errs()); | 
 |   errs() << getDiagnosticMessagePrefix(DI.getSeverity()) << ": "; | 
 |   DI.print(DP); | 
 |   errs() << "\n"; | 
 |   if (DI.getSeverity() == DS_Error) | 
 |     exit(1); | 
 | } | 
 |  | 
 | void LLVMContext::emitError(unsigned LocCookie, const Twine &ErrorStr) { | 
 |   diagnose(DiagnosticInfoInlineAsm(LocCookie, ErrorStr)); | 
 | } | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | // Metadata Kind Uniquing | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | /// Return a unique non-zero ID for the specified metadata kind. | 
 | unsigned LLVMContext::getMDKindID(StringRef Name) const { | 
 |   // If this is new, assign it its ID. | 
 |   return pImpl->CustomMDKindNames.insert( | 
 |                                      std::make_pair( | 
 |                                          Name, pImpl->CustomMDKindNames.size())) | 
 |       .first->second; | 
 | } | 
 |  | 
 | /// getHandlerNames - Populate client-supplied smallvector using custom | 
 | /// metadata name and ID. | 
 | void LLVMContext::getMDKindNames(SmallVectorImpl<StringRef> &Names) const { | 
 |   Names.resize(pImpl->CustomMDKindNames.size()); | 
 |   for (StringMap<unsigned>::const_iterator I = pImpl->CustomMDKindNames.begin(), | 
 |        E = pImpl->CustomMDKindNames.end(); I != E; ++I) | 
 |     Names[I->second] = I->first(); | 
 | } | 
 |  | 
 | void LLVMContext::getOperandBundleTags(SmallVectorImpl<StringRef> &Tags) const { | 
 |   pImpl->getOperandBundleTags(Tags); | 
 | } | 
 |  | 
 | uint32_t LLVMContext::getOperandBundleTagID(StringRef Tag) const { | 
 |   return pImpl->getOperandBundleTagID(Tag); | 
 | } | 
 |  | 
 | SyncScope::ID LLVMContext::getOrInsertSyncScopeID(StringRef SSN) { | 
 |   return pImpl->getOrInsertSyncScopeID(SSN); | 
 | } | 
 |  | 
 | void LLVMContext::getSyncScopeNames(SmallVectorImpl<StringRef> &SSNs) const { | 
 |   pImpl->getSyncScopeNames(SSNs); | 
 | } | 
 |  | 
 | void LLVMContext::setGC(const Function &Fn, std::string GCName) { | 
 |   auto It = pImpl->GCNames.find(&Fn); | 
 |  | 
 |   if (It == pImpl->GCNames.end()) { | 
 |     pImpl->GCNames.insert(std::make_pair(&Fn, std::move(GCName))); | 
 |     return; | 
 |   } | 
 |   It->second = std::move(GCName); | 
 | } | 
 |  | 
 | const std::string &LLVMContext::getGC(const Function &Fn) { | 
 |   return pImpl->GCNames[&Fn]; | 
 | } | 
 |  | 
 | void LLVMContext::deleteGC(const Function &Fn) { | 
 |   pImpl->GCNames.erase(&Fn); | 
 | } | 
 |  | 
 | bool LLVMContext::shouldDiscardValueNames() const { | 
 |   return pImpl->DiscardValueNames; | 
 | } | 
 |  | 
 | bool LLVMContext::isODRUniquingDebugTypes() const { return !!pImpl->DITypeMap; } | 
 |  | 
 | void LLVMContext::enableDebugTypeODRUniquing() { | 
 |   if (pImpl->DITypeMap) | 
 |     return; | 
 |  | 
 |   pImpl->DITypeMap.emplace(); | 
 | } | 
 |  | 
 | void LLVMContext::disableDebugTypeODRUniquing() { pImpl->DITypeMap.reset(); } | 
 |  | 
 | void LLVMContext::setDiscardValueNames(bool Discard) { | 
 |   pImpl->DiscardValueNames = Discard; | 
 | } | 
 |  | 
 | OptPassGate &LLVMContext::getOptPassGate() const { | 
 |   return pImpl->getOptPassGate(); | 
 | } | 
 |  | 
 | void LLVMContext::setOptPassGate(OptPassGate& OPG) { | 
 |   pImpl->setOptPassGate(OPG); | 
 | } | 
 |  | 
 | const DiagnosticHandler *LLVMContext::getDiagHandlerPtr() const { | 
 |   return pImpl->DiagHandler.get(); | 
 | } | 
 |  | 
 | std::unique_ptr<DiagnosticHandler> LLVMContext::getDiagnosticHandler() { | 
 |   return std::move(pImpl->DiagHandler); | 
 | } |