392 lines · cpp
1//===-- LLVMContext.cpp - Implement LLVMContext ---------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements LLVMContext, as a wrapper around the opaque10// class LLVMContextImpl.11//12//===----------------------------------------------------------------------===//13 14#include "llvm/IR/LLVMContext.h"15#include "LLVMContextImpl.h"16#include "llvm/ADT/SmallVector.h"17#include "llvm/ADT/StringMap.h"18#include "llvm/ADT/StringRef.h"19#include "llvm/ADT/Twine.h"20#include "llvm/IR/DiagnosticInfo.h"21#include "llvm/IR/DiagnosticPrinter.h"22#include "llvm/IR/LLVMRemarkStreamer.h"23#include "llvm/Remarks/RemarkStreamer.h"24#include "llvm/Support/Casting.h"25#include "llvm/Support/ErrorHandling.h"26#include "llvm/Support/raw_ostream.h"27#include <cassert>28#include <cstdlib>29#include <string>30#include <utility>31 32using namespace llvm;33 34static StringRef knownBundleName(unsigned BundleTagID) {35 switch (BundleTagID) {36 case LLVMContext::OB_deopt:37 return "deopt";38 case LLVMContext::OB_funclet:39 return "funclet";40 case LLVMContext::OB_gc_transition:41 return "gc-transition";42 case LLVMContext::OB_cfguardtarget:43 return "cfguardtarget";44 case LLVMContext::OB_preallocated:45 return "preallocated";46 case LLVMContext::OB_gc_live:47 return "gc-live";48 case LLVMContext::OB_clang_arc_attachedcall:49 return "clang.arc.attachedcall";50 case LLVMContext::OB_ptrauth:51 return "ptrauth";52 case LLVMContext::OB_kcfi:53 return "kcfi";54 case LLVMContext::OB_convergencectrl:55 return "convergencectrl";56 case LLVMContext::OB_align:57 return "align";58 case LLVMContext::OB_deactivation_symbol:59 return "deactivation-symbol";60 default:61 llvm_unreachable("unknown bundle id");62 }63 64 llvm_unreachable("covered switch");65}66 67LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {68 // Create the fixed metadata kinds. This is done in the same order as the69 // MD_* enum values so that they correspond.70 std::pair<unsigned, StringRef> MDKinds[] = {71#define LLVM_FIXED_MD_KIND(EnumID, Name, Value) {EnumID, Name},72#include "llvm/IR/FixedMetadataKinds.def"73#undef LLVM_FIXED_MD_KIND74 };75 76 for (auto &MDKind : MDKinds) {77 unsigned ID = getMDKindID(MDKind.second);78 assert(ID == MDKind.first && "metadata kind id drifted");79 (void)ID;80 }81 82 for (unsigned BundleTagID = LLVMContext::OB_deopt;83 BundleTagID <= LLVMContext::OB_LastBundleID; ++BundleTagID) {84 [[maybe_unused]] const auto *Entry =85 pImpl->getOrInsertBundleTag(knownBundleName(BundleTagID));86 assert(Entry->second == BundleTagID && "operand bundle id drifted!");87 }88 89 SyncScope::ID SingleThreadSSID =90 pImpl->getOrInsertSyncScopeID("singlethread");91 assert(SingleThreadSSID == SyncScope::SingleThread &&92 "singlethread synchronization scope ID drifted!");93 (void)SingleThreadSSID;94 95 SyncScope::ID SystemSSID =96 pImpl->getOrInsertSyncScopeID("");97 assert(SystemSSID == SyncScope::System &&98 "system synchronization scope ID drifted!");99 (void)SystemSSID;100}101 102LLVMContext::~LLVMContext() { delete pImpl; }103 104void LLVMContext::addModule(Module *M) {105 pImpl->OwnedModules.insert(M);106}107 108void LLVMContext::removeModule(Module *M) {109 pImpl->OwnedModules.erase(M);110 pImpl->MachineFunctionNums.erase(M);111}112 113unsigned LLVMContext::generateMachineFunctionNum(Function &F) {114 Module *M = F.getParent();115 assert(pImpl->OwnedModules.contains(M) && "Unexpected module!");116 return pImpl->MachineFunctionNums[M]++;117}118 119//===----------------------------------------------------------------------===//120// Recoverable Backend Errors121//===----------------------------------------------------------------------===//122 123void LLVMContext::setDiagnosticHandlerCallBack(124 DiagnosticHandler::DiagnosticHandlerTy DiagnosticHandler,125 void *DiagnosticContext, bool RespectFilters) {126 pImpl->DiagHandler->DiagHandlerCallback = DiagnosticHandler;127 pImpl->DiagHandler->DiagnosticContext = DiagnosticContext;128 pImpl->RespectDiagnosticFilters = RespectFilters;129}130 131void LLVMContext::setDiagnosticHandler(std::unique_ptr<DiagnosticHandler> &&DH,132 bool RespectFilters) {133 pImpl->DiagHandler = std::move(DH);134 pImpl->RespectDiagnosticFilters = RespectFilters;135}136 137void LLVMContext::setDiagnosticsHotnessRequested(bool Requested) {138 pImpl->DiagnosticsHotnessRequested = Requested;139}140bool LLVMContext::getDiagnosticsHotnessRequested() const {141 return pImpl->DiagnosticsHotnessRequested;142}143 144void LLVMContext::setDiagnosticsHotnessThreshold(std::optional<uint64_t> Threshold) {145 pImpl->DiagnosticsHotnessThreshold = Threshold;146}147void LLVMContext::setMisExpectWarningRequested(bool Requested) {148 pImpl->MisExpectWarningRequested = Requested;149}150bool LLVMContext::getMisExpectWarningRequested() const {151 return pImpl->MisExpectWarningRequested;152}153uint64_t LLVMContext::getDiagnosticsHotnessThreshold() const {154 return pImpl->DiagnosticsHotnessThreshold.value_or(UINT64_MAX);155}156void LLVMContext::setDiagnosticsMisExpectTolerance(157 std::optional<uint32_t> Tolerance) {158 pImpl->DiagnosticsMisExpectTolerance = Tolerance;159}160uint32_t LLVMContext::getDiagnosticsMisExpectTolerance() const {161 return pImpl->DiagnosticsMisExpectTolerance.value_or(0);162}163 164bool LLVMContext::isDiagnosticsHotnessThresholdSetFromPSI() const {165 return !pImpl->DiagnosticsHotnessThreshold.has_value();166}167 168remarks::RemarkStreamer *LLVMContext::getMainRemarkStreamer() {169 return pImpl->MainRemarkStreamer.get();170}171const remarks::RemarkStreamer *LLVMContext::getMainRemarkStreamer() const {172 return const_cast<LLVMContext *>(this)->getMainRemarkStreamer();173}174void LLVMContext::setMainRemarkStreamer(175 std::unique_ptr<remarks::RemarkStreamer> RemarkStreamer) {176 pImpl->MainRemarkStreamer = std::move(RemarkStreamer);177}178 179LLVMRemarkStreamer *LLVMContext::getLLVMRemarkStreamer() {180 return pImpl->LLVMRS.get();181}182const LLVMRemarkStreamer *LLVMContext::getLLVMRemarkStreamer() const {183 return const_cast<LLVMContext *>(this)->getLLVMRemarkStreamer();184}185void LLVMContext::setLLVMRemarkStreamer(186 std::unique_ptr<LLVMRemarkStreamer> RemarkStreamer) {187 pImpl->LLVMRS = std::move(RemarkStreamer);188}189 190DiagnosticHandler::DiagnosticHandlerTy191LLVMContext::getDiagnosticHandlerCallBack() const {192 return pImpl->DiagHandler->DiagHandlerCallback;193}194 195void *LLVMContext::getDiagnosticContext() const {196 return pImpl->DiagHandler->DiagnosticContext;197}198 199void LLVMContext::setYieldCallback(YieldCallbackTy Callback, void *OpaqueHandle)200{201 pImpl->YieldCallback = Callback;202 pImpl->YieldOpaqueHandle = OpaqueHandle;203}204 205void LLVMContext::yield() {206 if (pImpl->YieldCallback)207 pImpl->YieldCallback(this, pImpl->YieldOpaqueHandle);208}209 210void LLVMContext::emitError(const Twine &ErrorStr) {211 diagnose(DiagnosticInfoGeneric(ErrorStr));212}213 214void LLVMContext::emitError(const Instruction *I, const Twine &ErrorStr) {215 assert(I && "Invalid instruction");216 diagnose(DiagnosticInfoGeneric(I, ErrorStr));217}218 219static bool isDiagnosticEnabled(const DiagnosticInfo &DI) {220 // Optimization remarks are selective. They need to check whether the regexp221 // pattern, passed via one of the -pass-remarks* flags, matches the name of222 // the pass that is emitting the diagnostic. If there is no match, ignore the223 // diagnostic and return.224 //225 // Also noisy remarks are only enabled if we have hotness information to sort226 // them.227 if (auto *Remark = dyn_cast<DiagnosticInfoOptimizationBase>(&DI))228 return Remark->isEnabled() &&229 (!Remark->isVerbose() || Remark->getHotness());230 231 return true;232}233 234const char *235LLVMContext::getDiagnosticMessagePrefix(DiagnosticSeverity Severity) {236 switch (Severity) {237 case DS_Error:238 return "error";239 case DS_Warning:240 return "warning";241 case DS_Remark:242 return "remark";243 case DS_Note:244 return "note";245 }246 llvm_unreachable("Unknown DiagnosticSeverity");247}248 249void LLVMContext::diagnose(const DiagnosticInfo &DI) {250 if (auto *OptDiagBase = dyn_cast<DiagnosticInfoOptimizationBase>(&DI))251 if (LLVMRemarkStreamer *RS = getLLVMRemarkStreamer())252 RS->emit(*OptDiagBase);253 254 // If there is a report handler, use it.255 if (pImpl->DiagHandler) {256 if (DI.getSeverity() == DS_Error)257 pImpl->DiagHandler->HasErrors = true;258 if ((!pImpl->RespectDiagnosticFilters || isDiagnosticEnabled(DI)) &&259 pImpl->DiagHandler->handleDiagnostics(DI))260 return;261 }262 263 if (!isDiagnosticEnabled(DI))264 return;265 266 // Otherwise, print the message with a prefix based on the severity.267 DiagnosticPrinterRawOStream DP(errs());268 errs() << getDiagnosticMessagePrefix(DI.getSeverity()) << ": ";269 DI.print(DP);270 errs() << "\n";271 if (DI.getSeverity() == DS_Error)272 exit(1);273}274 275//===----------------------------------------------------------------------===//276// Metadata Kind Uniquing277//===----------------------------------------------------------------------===//278 279/// Return a unique non-zero ID for the specified metadata kind.280unsigned LLVMContext::getMDKindID(StringRef Name) const {281 // If this is new, assign it its ID.282 return pImpl->CustomMDKindNames.insert(283 std::make_pair(284 Name, pImpl->CustomMDKindNames.size()))285 .first->second;286}287 288/// getHandlerNames - Populate client-supplied smallvector using custom289/// metadata name and ID.290void LLVMContext::getMDKindNames(SmallVectorImpl<StringRef> &Names) const {291 Names.resize(pImpl->CustomMDKindNames.size());292 for (StringMap<unsigned>::const_iterator I = pImpl->CustomMDKindNames.begin(),293 E = pImpl->CustomMDKindNames.end(); I != E; ++I)294 Names[I->second] = I->first();295}296 297void LLVMContext::getOperandBundleTags(SmallVectorImpl<StringRef> &Tags) const {298 pImpl->getOperandBundleTags(Tags);299}300 301StringMapEntry<uint32_t> *302LLVMContext::getOrInsertBundleTag(StringRef TagName) const {303 return pImpl->getOrInsertBundleTag(TagName);304}305 306uint32_t LLVMContext::getOperandBundleTagID(StringRef Tag) const {307 return pImpl->getOperandBundleTagID(Tag);308}309 310SyncScope::ID LLVMContext::getOrInsertSyncScopeID(StringRef SSN) {311 return pImpl->getOrInsertSyncScopeID(SSN);312}313 314void LLVMContext::getSyncScopeNames(SmallVectorImpl<StringRef> &SSNs) const {315 pImpl->getSyncScopeNames(SSNs);316}317 318std::optional<StringRef> LLVMContext::getSyncScopeName(SyncScope::ID Id) const {319 return pImpl->getSyncScopeName(Id);320}321 322void LLVMContext::setGC(const Function &Fn, std::string GCName) {323 pImpl->GCNames[&Fn] = std::move(GCName);324}325 326const std::string &LLVMContext::getGC(const Function &Fn) {327 return pImpl->GCNames[&Fn];328}329 330void LLVMContext::deleteGC(const Function &Fn) {331 pImpl->GCNames.erase(&Fn);332}333 334bool LLVMContext::shouldDiscardValueNames() const {335 return pImpl->DiscardValueNames;336}337 338bool LLVMContext::isODRUniquingDebugTypes() const { return !!pImpl->DITypeMap; }339 340void LLVMContext::enableDebugTypeODRUniquing() {341 if (pImpl->DITypeMap)342 return;343 344 pImpl->DITypeMap.emplace();345}346 347void LLVMContext::disableDebugTypeODRUniquing() { pImpl->DITypeMap.reset(); }348 349void LLVMContext::setDiscardValueNames(bool Discard) {350 pImpl->DiscardValueNames = Discard;351}352 353OptPassGate &LLVMContext::getOptPassGate() const {354 return pImpl->getOptPassGate();355}356 357void LLVMContext::setOptPassGate(OptPassGate& OPG) {358 pImpl->setOptPassGate(OPG);359}360 361const DiagnosticHandler *LLVMContext::getDiagHandlerPtr() const {362 return pImpl->DiagHandler.get();363}364 365std::unique_ptr<DiagnosticHandler> LLVMContext::getDiagnosticHandler() {366 return std::move(pImpl->DiagHandler);367}368 369StringRef LLVMContext::getDefaultTargetCPU() {370 return pImpl->DefaultTargetCPU;371}372 373void LLVMContext::setDefaultTargetCPU(StringRef CPU) {374 pImpl->DefaultTargetCPU = CPU;375}376 377StringRef LLVMContext::getDefaultTargetFeatures() {378 return pImpl->DefaultTargetFeatures;379}380 381void LLVMContext::setDefaultTargetFeatures(StringRef Features) {382 pImpl->DefaultTargetFeatures = Features;383}384 385void LLVMContext::updateDILocationAtomGroupWaterline(uint64_t V) {386 pImpl->NextAtomGroup = std::max(pImpl->NextAtomGroup, V);387}388 389uint64_t LLVMContext::incNextDILocationAtomGroup() {390 return pImpl->NextAtomGroup++;391}392