| //===-- 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"}, | |
| }; | |
| 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); | |
| } |