//===-- LLVMContext.cpp - Implement LLVMContext ---------------------------===////// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.// See https://llvm.org/LICENSE.txt for license information.// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception////===----------------------------------------------------------------------===////// 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>usingnamespacellvm;LLVMContext::LLVMContext():pImpl(newLLVMContextImpl(*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"},{MD_callback,"callback"},};for(auto&MDKind:MDKinds){unsignedID=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::IDSingleThreadSSID=pImpl->getOrInsertSyncScopeID("singlethread");assert(SingleThreadSSID==SyncScope::SingleThread&&"singlethread synchronization scope ID drifted!");(void)SingleThreadSSID;SyncScope::IDSystemSSID=pImpl->getOrInsertSyncScopeID("");assert(SystemSSID==SyncScope::System&&"system synchronization scope ID drifted!");(void)SystemSSID;}LLVMContext::~LLVMContext(){deletepImpl;}voidLLVMContext::addModule(Module*M){pImpl->OwnedModules.insert(M);}voidLLVMContext::removeModule(Module*M){pImpl->OwnedModules.erase(M);}//===----------------------------------------------------------------------===//// Recoverable Backend Errors//===----------------------------------------------------------------------===//voidLLVMContext::setInlineAsmDiagnosticHandler(InlineAsmDiagHandlerTyDiagHandler,void*DiagContext){pImpl->InlineAsmDiagHandler=DiagHandler;pImpl->InlineAsmDiagContext=DiagContext;}/// getInlineAsmDiagnosticHandler - Return the diagnostic handler set by/// setInlineAsmDiagnosticHandler.LLVMContext::InlineAsmDiagHandlerTyLLVMContext::getInlineAsmDiagnosticHandler()const{returnpImpl->InlineAsmDiagHandler;}/// getInlineAsmDiagnosticContext - Return the diagnostic context set by/// setInlineAsmDiagnosticHandler.void*LLVMContext::getInlineAsmDiagnosticContext()const{returnpImpl->InlineAsmDiagContext;}voidLLVMContext::setDiagnosticHandlerCallBack(DiagnosticHandler::DiagnosticHandlerTyDiagnosticHandler,void*DiagnosticContext,boolRespectFilters){pImpl->DiagHandler->DiagHandlerCallback=DiagnosticHandler;pImpl->DiagHandler->DiagnosticContext=DiagnosticContext;pImpl->RespectDiagnosticFilters=RespectFilters;}voidLLVMContext::setDiagnosticHandler(std::unique_ptr<DiagnosticHandler>&&DH,boolRespectFilters){pImpl->DiagHandler=std::move(DH);pImpl->RespectDiagnosticFilters=RespectFilters;}voidLLVMContext::setDiagnosticsHotnessRequested(boolRequested){pImpl->DiagnosticsHotnessRequested=Requested;}boolLLVMContext::getDiagnosticsHotnessRequested()const{returnpImpl->DiagnosticsHotnessRequested;}voidLLVMContext::setDiagnosticsHotnessThreshold(uint64_tThreshold){pImpl->DiagnosticsHotnessThreshold=Threshold;}uint64_tLLVMContext::getDiagnosticsHotnessThreshold()const{returnpImpl->DiagnosticsHotnessThreshold;}yaml::Output*LLVMContext::getDiagnosticsOutputFile(){returnpImpl->DiagnosticsOutputFile.get();}voidLLVMContext::setDiagnosticsOutputFile(std::unique_ptr<yaml::Output>F){pImpl->DiagnosticsOutputFile=std::move(F);}DiagnosticHandler::DiagnosticHandlerTyLLVMContext::getDiagnosticHandlerCallBack()const{returnpImpl->DiagHandler->DiagHandlerCallback;}void*LLVMContext::getDiagnosticContext()const{returnpImpl->DiagHandler->DiagnosticContext;}voidLLVMContext::setYieldCallback(YieldCallbackTyCallback,void*OpaqueHandle){pImpl->YieldCallback=Callback;pImpl->YieldOpaqueHandle=OpaqueHandle;}voidLLVMContext::yield(){if(pImpl->YieldCallback)pImpl->YieldCallback(this,pImpl->YieldOpaqueHandle);}voidLLVMContext::emitError(constTwine&ErrorStr){diagnose(DiagnosticInfoInlineAsm(ErrorStr));}voidLLVMContext::emitError(constInstruction*I,constTwine&ErrorStr){assert(I&&"Invalid instruction");diagnose(DiagnosticInfoInlineAsm(*I,ErrorStr));}staticboolisDiagnosticEnabled(constDiagnosticInfo&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))returnRemark->isEnabled()&&(!Remark->isVerbose()||Remark->getHotness());returntrue;}constchar*LLVMContext::getDiagnosticMessagePrefix(DiagnosticSeveritySeverity){switch(Severity){caseDS_Error:return"error";caseDS_Warning:return"warning";caseDS_Remark:return"remark";caseDS_Note:return"note";}llvm_unreachable("Unknown DiagnosticSeverity");}voidLLVMContext::diagnose(constDiagnosticInfo&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.DiagnosticPrinterRawOStreamDP(errs());errs()<<getDiagnosticMessagePrefix(DI.getSeverity())<<": ";DI.print(DP);errs()<<"\n";if(DI.getSeverity()==DS_Error)exit(1);}voidLLVMContext::emitError(unsignedLocCookie,constTwine&ErrorStr){diagnose(DiagnosticInfoInlineAsm(LocCookie,ErrorStr));}//===----------------------------------------------------------------------===//// Metadata Kind Uniquing//===----------------------------------------------------------------------===///// Return a unique non-zero ID for the specified metadata kind.unsignedLLVMContext::getMDKindID(StringRefName)const{// If this is new, assign it its ID.returnpImpl->CustomMDKindNames.insert(std::make_pair(Name,pImpl->CustomMDKindNames.size())).first->second;}/// getHandlerNames - Populate client-supplied smallvector using custom/// metadata name and ID.voidLLVMContext::getMDKindNames(SmallVectorImpl<StringRef>&Names)const{Names.resize(pImpl->CustomMDKindNames.size());for(StringMap<unsigned>::const_iteratorI=pImpl->CustomMDKindNames.begin(),E=pImpl->CustomMDKindNames.end();I!=E;++I)Names[I->second]=I->first();}voidLLVMContext::getOperandBundleTags(SmallVectorImpl<StringRef>&Tags)const{pImpl->getOperandBundleTags(Tags);}uint32_tLLVMContext::getOperandBundleTagID(StringRefTag)const{returnpImpl->getOperandBundleTagID(Tag);}SyncScope::IDLLVMContext::getOrInsertSyncScopeID(StringRefSSN){returnpImpl->getOrInsertSyncScopeID(SSN);}voidLLVMContext::getSyncScopeNames(SmallVectorImpl<StringRef>&SSNs)const{pImpl->getSyncScopeNames(SSNs);}voidLLVMContext::setGC(constFunction&Fn,std::stringGCName){autoIt=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);}conststd::string&LLVMContext::getGC(constFunction&Fn){returnpImpl->GCNames[&Fn];}voidLLVMContext::deleteGC(constFunction&Fn){pImpl->GCNames.erase(&Fn);}boolLLVMContext::shouldDiscardValueNames()const{returnpImpl->DiscardValueNames;}boolLLVMContext::isODRUniquingDebugTypes()const{return!!pImpl->DITypeMap;}voidLLVMContext::enableDebugTypeODRUniquing(){if(pImpl->DITypeMap)return;pImpl->DITypeMap.emplace();}voidLLVMContext::disableDebugTypeODRUniquing(){pImpl->DITypeMap.reset();}voidLLVMContext::setDiscardValueNames(boolDiscard){pImpl->DiscardValueNames=Discard;}OptPassGate&LLVMContext::getOptPassGate()const{returnpImpl->getOptPassGate();}voidLLVMContext::setOptPassGate(OptPassGate&OPG){pImpl->setOptPassGate(OPG);}constDiagnosticHandler*LLVMContext::getDiagHandlerPtr()const{returnpImpl->DiagHandler.get();}std::unique_ptr<DiagnosticHandler>LLVMContext::getDiagnosticHandler(){returnstd::move(pImpl->DiagHandler);}