Path: blob/main/contrib/llvm-project/llvm/lib/IR/LLVMContext.cpp
35234 views
//===-- LLVMContext.cpp - Implement LLVMContext ---------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements LLVMContext, as a wrapper around the opaque9// class LLVMContextImpl.10//11//===----------------------------------------------------------------------===//1213#include "llvm/IR/LLVMContext.h"14#include "LLVMContextImpl.h"15#include "llvm/ADT/SmallVector.h"16#include "llvm/ADT/StringMap.h"17#include "llvm/ADT/StringRef.h"18#include "llvm/ADT/Twine.h"19#include "llvm/IR/DiagnosticInfo.h"20#include "llvm/IR/DiagnosticPrinter.h"21#include "llvm/IR/LLVMRemarkStreamer.h"22#include "llvm/Remarks/RemarkStreamer.h"23#include "llvm/Support/Casting.h"24#include "llvm/Support/ErrorHandling.h"25#include "llvm/Support/raw_ostream.h"26#include <cassert>27#include <cstdlib>28#include <string>29#include <utility>3031using namespace llvm;3233LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {34// Create the fixed metadata kinds. This is done in the same order as the35// MD_* enum values so that they correspond.36std::pair<unsigned, StringRef> MDKinds[] = {37#define LLVM_FIXED_MD_KIND(EnumID, Name, Value) {EnumID, Name},38#include "llvm/IR/FixedMetadataKinds.def"39#undef LLVM_FIXED_MD_KIND40};4142for (auto &MDKind : MDKinds) {43unsigned ID = getMDKindID(MDKind.second);44assert(ID == MDKind.first && "metadata kind id drifted");45(void)ID;46}4748auto *DeoptEntry = pImpl->getOrInsertBundleTag("deopt");49assert(DeoptEntry->second == LLVMContext::OB_deopt &&50"deopt operand bundle id drifted!");51(void)DeoptEntry;5253auto *FuncletEntry = pImpl->getOrInsertBundleTag("funclet");54assert(FuncletEntry->second == LLVMContext::OB_funclet &&55"funclet operand bundle id drifted!");56(void)FuncletEntry;5758auto *GCTransitionEntry = pImpl->getOrInsertBundleTag("gc-transition");59assert(GCTransitionEntry->second == LLVMContext::OB_gc_transition &&60"gc-transition operand bundle id drifted!");61(void)GCTransitionEntry;6263auto *CFGuardTargetEntry = pImpl->getOrInsertBundleTag("cfguardtarget");64assert(CFGuardTargetEntry->second == LLVMContext::OB_cfguardtarget &&65"cfguardtarget operand bundle id drifted!");66(void)CFGuardTargetEntry;6768auto *PreallocatedEntry = pImpl->getOrInsertBundleTag("preallocated");69assert(PreallocatedEntry->second == LLVMContext::OB_preallocated &&70"preallocated operand bundle id drifted!");71(void)PreallocatedEntry;7273auto *GCLiveEntry = pImpl->getOrInsertBundleTag("gc-live");74assert(GCLiveEntry->second == LLVMContext::OB_gc_live &&75"gc-transition operand bundle id drifted!");76(void)GCLiveEntry;7778auto *ClangAttachedCall =79pImpl->getOrInsertBundleTag("clang.arc.attachedcall");80assert(ClangAttachedCall->second == LLVMContext::OB_clang_arc_attachedcall &&81"clang.arc.attachedcall operand bundle id drifted!");82(void)ClangAttachedCall;8384auto *PtrauthEntry = pImpl->getOrInsertBundleTag("ptrauth");85assert(PtrauthEntry->second == LLVMContext::OB_ptrauth &&86"ptrauth operand bundle id drifted!");87(void)PtrauthEntry;8889auto *KCFIEntry = pImpl->getOrInsertBundleTag("kcfi");90assert(KCFIEntry->second == LLVMContext::OB_kcfi &&91"kcfi operand bundle id drifted!");92(void)KCFIEntry;9394auto *ConvergenceCtrlEntry = pImpl->getOrInsertBundleTag("convergencectrl");95assert(ConvergenceCtrlEntry->second == LLVMContext::OB_convergencectrl &&96"convergencectrl operand bundle id drifted!");97(void)ConvergenceCtrlEntry;9899SyncScope::ID SingleThreadSSID =100pImpl->getOrInsertSyncScopeID("singlethread");101assert(SingleThreadSSID == SyncScope::SingleThread &&102"singlethread synchronization scope ID drifted!");103(void)SingleThreadSSID;104105SyncScope::ID SystemSSID =106pImpl->getOrInsertSyncScopeID("");107assert(SystemSSID == SyncScope::System &&108"system synchronization scope ID drifted!");109(void)SystemSSID;110}111112LLVMContext::~LLVMContext() { delete pImpl; }113114void LLVMContext::addModule(Module *M) {115pImpl->OwnedModules.insert(M);116}117118void LLVMContext::removeModule(Module *M) {119pImpl->OwnedModules.erase(M);120pImpl->MachineFunctionNums.erase(M);121}122123unsigned LLVMContext::generateMachineFunctionNum(Function &F) {124Module *M = F.getParent();125assert(pImpl->OwnedModules.contains(M) && "Unexpected module!");126return pImpl->MachineFunctionNums[M]++;127}128129//===----------------------------------------------------------------------===//130// Recoverable Backend Errors131//===----------------------------------------------------------------------===//132133void LLVMContext::setDiagnosticHandlerCallBack(134DiagnosticHandler::DiagnosticHandlerTy DiagnosticHandler,135void *DiagnosticContext, bool RespectFilters) {136pImpl->DiagHandler->DiagHandlerCallback = DiagnosticHandler;137pImpl->DiagHandler->DiagnosticContext = DiagnosticContext;138pImpl->RespectDiagnosticFilters = RespectFilters;139}140141void LLVMContext::setDiagnosticHandler(std::unique_ptr<DiagnosticHandler> &&DH,142bool RespectFilters) {143pImpl->DiagHandler = std::move(DH);144pImpl->RespectDiagnosticFilters = RespectFilters;145}146147void LLVMContext::setDiagnosticsHotnessRequested(bool Requested) {148pImpl->DiagnosticsHotnessRequested = Requested;149}150bool LLVMContext::getDiagnosticsHotnessRequested() const {151return pImpl->DiagnosticsHotnessRequested;152}153154void LLVMContext::setDiagnosticsHotnessThreshold(std::optional<uint64_t> Threshold) {155pImpl->DiagnosticsHotnessThreshold = Threshold;156}157void LLVMContext::setMisExpectWarningRequested(bool Requested) {158pImpl->MisExpectWarningRequested = Requested;159}160bool LLVMContext::getMisExpectWarningRequested() const {161return pImpl->MisExpectWarningRequested;162}163uint64_t LLVMContext::getDiagnosticsHotnessThreshold() const {164return pImpl->DiagnosticsHotnessThreshold.value_or(UINT64_MAX);165}166void LLVMContext::setDiagnosticsMisExpectTolerance(167std::optional<uint32_t> Tolerance) {168pImpl->DiagnosticsMisExpectTolerance = Tolerance;169}170uint32_t LLVMContext::getDiagnosticsMisExpectTolerance() const {171return pImpl->DiagnosticsMisExpectTolerance.value_or(0);172}173174bool LLVMContext::isDiagnosticsHotnessThresholdSetFromPSI() const {175return !pImpl->DiagnosticsHotnessThreshold.has_value();176}177178remarks::RemarkStreamer *LLVMContext::getMainRemarkStreamer() {179return pImpl->MainRemarkStreamer.get();180}181const remarks::RemarkStreamer *LLVMContext::getMainRemarkStreamer() const {182return const_cast<LLVMContext *>(this)->getMainRemarkStreamer();183}184void LLVMContext::setMainRemarkStreamer(185std::unique_ptr<remarks::RemarkStreamer> RemarkStreamer) {186pImpl->MainRemarkStreamer = std::move(RemarkStreamer);187}188189LLVMRemarkStreamer *LLVMContext::getLLVMRemarkStreamer() {190return pImpl->LLVMRS.get();191}192const LLVMRemarkStreamer *LLVMContext::getLLVMRemarkStreamer() const {193return const_cast<LLVMContext *>(this)->getLLVMRemarkStreamer();194}195void LLVMContext::setLLVMRemarkStreamer(196std::unique_ptr<LLVMRemarkStreamer> RemarkStreamer) {197pImpl->LLVMRS = std::move(RemarkStreamer);198}199200DiagnosticHandler::DiagnosticHandlerTy201LLVMContext::getDiagnosticHandlerCallBack() const {202return pImpl->DiagHandler->DiagHandlerCallback;203}204205void *LLVMContext::getDiagnosticContext() const {206return pImpl->DiagHandler->DiagnosticContext;207}208209void LLVMContext::setYieldCallback(YieldCallbackTy Callback, void *OpaqueHandle)210{211pImpl->YieldCallback = Callback;212pImpl->YieldOpaqueHandle = OpaqueHandle;213}214215void LLVMContext::yield() {216if (pImpl->YieldCallback)217pImpl->YieldCallback(this, pImpl->YieldOpaqueHandle);218}219220void LLVMContext::emitError(const Twine &ErrorStr) {221diagnose(DiagnosticInfoInlineAsm(ErrorStr));222}223224void LLVMContext::emitError(const Instruction *I, const Twine &ErrorStr) {225assert (I && "Invalid instruction");226diagnose(DiagnosticInfoInlineAsm(*I, ErrorStr));227}228229static bool isDiagnosticEnabled(const DiagnosticInfo &DI) {230// Optimization remarks are selective. They need to check whether the regexp231// pattern, passed via one of the -pass-remarks* flags, matches the name of232// the pass that is emitting the diagnostic. If there is no match, ignore the233// diagnostic and return.234//235// Also noisy remarks are only enabled if we have hotness information to sort236// them.237if (auto *Remark = dyn_cast<DiagnosticInfoOptimizationBase>(&DI))238return Remark->isEnabled() &&239(!Remark->isVerbose() || Remark->getHotness());240241return true;242}243244const char *245LLVMContext::getDiagnosticMessagePrefix(DiagnosticSeverity Severity) {246switch (Severity) {247case DS_Error:248return "error";249case DS_Warning:250return "warning";251case DS_Remark:252return "remark";253case DS_Note:254return "note";255}256llvm_unreachable("Unknown DiagnosticSeverity");257}258259void LLVMContext::diagnose(const DiagnosticInfo &DI) {260if (auto *OptDiagBase = dyn_cast<DiagnosticInfoOptimizationBase>(&DI))261if (LLVMRemarkStreamer *RS = getLLVMRemarkStreamer())262RS->emit(*OptDiagBase);263264// If there is a report handler, use it.265if (pImpl->DiagHandler) {266if (DI.getSeverity() == DS_Error)267pImpl->DiagHandler->HasErrors = true;268if ((!pImpl->RespectDiagnosticFilters || isDiagnosticEnabled(DI)) &&269pImpl->DiagHandler->handleDiagnostics(DI))270return;271}272273if (!isDiagnosticEnabled(DI))274return;275276// Otherwise, print the message with a prefix based on the severity.277DiagnosticPrinterRawOStream DP(errs());278errs() << getDiagnosticMessagePrefix(DI.getSeverity()) << ": ";279DI.print(DP);280errs() << "\n";281if (DI.getSeverity() == DS_Error)282exit(1);283}284285void LLVMContext::emitError(uint64_t LocCookie, const Twine &ErrorStr) {286diagnose(DiagnosticInfoInlineAsm(LocCookie, ErrorStr));287}288289//===----------------------------------------------------------------------===//290// Metadata Kind Uniquing291//===----------------------------------------------------------------------===//292293/// Return a unique non-zero ID for the specified metadata kind.294unsigned LLVMContext::getMDKindID(StringRef Name) const {295// If this is new, assign it its ID.296return pImpl->CustomMDKindNames.insert(297std::make_pair(298Name, pImpl->CustomMDKindNames.size()))299.first->second;300}301302/// getHandlerNames - Populate client-supplied smallvector using custom303/// metadata name and ID.304void LLVMContext::getMDKindNames(SmallVectorImpl<StringRef> &Names) const {305Names.resize(pImpl->CustomMDKindNames.size());306for (StringMap<unsigned>::const_iterator I = pImpl->CustomMDKindNames.begin(),307E = pImpl->CustomMDKindNames.end(); I != E; ++I)308Names[I->second] = I->first();309}310311void LLVMContext::getOperandBundleTags(SmallVectorImpl<StringRef> &Tags) const {312pImpl->getOperandBundleTags(Tags);313}314315StringMapEntry<uint32_t> *316LLVMContext::getOrInsertBundleTag(StringRef TagName) const {317return pImpl->getOrInsertBundleTag(TagName);318}319320uint32_t LLVMContext::getOperandBundleTagID(StringRef Tag) const {321return pImpl->getOperandBundleTagID(Tag);322}323324SyncScope::ID LLVMContext::getOrInsertSyncScopeID(StringRef SSN) {325return pImpl->getOrInsertSyncScopeID(SSN);326}327328void LLVMContext::getSyncScopeNames(SmallVectorImpl<StringRef> &SSNs) const {329pImpl->getSyncScopeNames(SSNs);330}331332void LLVMContext::setGC(const Function &Fn, std::string GCName) {333auto It = pImpl->GCNames.find(&Fn);334335if (It == pImpl->GCNames.end()) {336pImpl->GCNames.insert(std::make_pair(&Fn, std::move(GCName)));337return;338}339It->second = std::move(GCName);340}341342const std::string &LLVMContext::getGC(const Function &Fn) {343return pImpl->GCNames[&Fn];344}345346void LLVMContext::deleteGC(const Function &Fn) {347pImpl->GCNames.erase(&Fn);348}349350bool LLVMContext::shouldDiscardValueNames() const {351return pImpl->DiscardValueNames;352}353354bool LLVMContext::isODRUniquingDebugTypes() const { return !!pImpl->DITypeMap; }355356void LLVMContext::enableDebugTypeODRUniquing() {357if (pImpl->DITypeMap)358return;359360pImpl->DITypeMap.emplace();361}362363void LLVMContext::disableDebugTypeODRUniquing() { pImpl->DITypeMap.reset(); }364365void LLVMContext::setDiscardValueNames(bool Discard) {366pImpl->DiscardValueNames = Discard;367}368369OptPassGate &LLVMContext::getOptPassGate() const {370return pImpl->getOptPassGate();371}372373void LLVMContext::setOptPassGate(OptPassGate& OPG) {374pImpl->setOptPassGate(OPG);375}376377const DiagnosticHandler *LLVMContext::getDiagHandlerPtr() const {378return pImpl->DiagHandler.get();379}380381std::unique_ptr<DiagnosticHandler> LLVMContext::getDiagnosticHandler() {382return std::move(pImpl->DiagHandler);383}384385void LLVMContext::setOpaquePointers(bool Enable) const {386assert(Enable && "Cannot disable opaque pointers");387}388389bool LLVMContext::supportsTypedPointers() const {390return false;391}392393StringRef LLVMContext::getDefaultTargetCPU() {394return pImpl->DefaultTargetCPU;395}396397void LLVMContext::setDefaultTargetCPU(StringRef CPU) {398pImpl->DefaultTargetCPU = CPU;399}400401StringRef LLVMContext::getDefaultTargetFeatures() {402return pImpl->DefaultTargetFeatures;403}404405void LLVMContext::setDefaultTargetFeatures(StringRef Features) {406pImpl->DefaultTargetFeatures = Features;407}408409410