506 lines · cpp
1//===- llvm/IR/DiagnosticInfo.cpp - Diagnostic Definitions ------*- C++ -*-===//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 defines the different classes involved in low level diagnostics.10//11// Diagnostics reporting is still done as part of the LLVMContext.12//===----------------------------------------------------------------------===//13 14#include "llvm/IR/DiagnosticInfo.h"15#include "llvm/ADT/StringExtras.h"16#include "llvm/ADT/Twine.h"17#include "llvm/ADT/iterator_range.h"18#include "llvm/Demangle/Demangle.h"19#include "llvm/IR/BasicBlock.h"20#include "llvm/IR/Constants.h"21#include "llvm/IR/DebugInfoMetadata.h"22#include "llvm/IR/DerivedTypes.h"23#include "llvm/IR/DiagnosticPrinter.h"24#include "llvm/IR/Function.h"25#include "llvm/IR/GlobalValue.h"26#include "llvm/IR/Instruction.h"27#include "llvm/IR/Instructions.h"28#include "llvm/IR/IntrinsicInst.h"29#include "llvm/IR/LLVMContext.h"30#include "llvm/IR/Metadata.h"31#include "llvm/IR/Module.h"32#include "llvm/IR/Type.h"33#include "llvm/IR/Value.h"34#include "llvm/Support/Casting.h"35#include "llvm/Support/ErrorHandling.h"36#include "llvm/Support/InstructionCost.h"37#include "llvm/Support/Path.h"38#include "llvm/Support/ScopedPrinter.h"39#include "llvm/Support/raw_ostream.h"40#include <atomic>41#include <string>42 43using namespace llvm;44 45int llvm::getNextAvailablePluginDiagnosticKind() {46 static std::atomic<int> PluginKindID(DK_FirstPluginKind);47 return ++PluginKindID;48}49 50const char *OptimizationRemarkAnalysis::AlwaysPrint = "";51 52void DiagnosticInfoGeneric::print(DiagnosticPrinter &DP) const {53 DP << getMsgStr();54}55 56void DiagnosticInfoGenericWithLoc::print(DiagnosticPrinter &DP) const {57 DP << getLocationStr() << ": " << getMsgStr();58}59 60DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(uint64_t LocCookie,61 const Twine &MsgStr,62 DiagnosticSeverity Severity)63 : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(LocCookie),64 MsgStr(MsgStr) {}65 66DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(const Instruction &I,67 const Twine &MsgStr,68 DiagnosticSeverity Severity)69 : DiagnosticInfo(DK_InlineAsm, Severity), MsgStr(MsgStr), Instr(&I) {70 if (const MDNode *SrcLoc = I.getMetadata("srcloc")) {71 if (SrcLoc->getNumOperands() != 0)72 if (const auto *CI =73 mdconst::dyn_extract<ConstantInt>(SrcLoc->getOperand(0)))74 LocCookie = CI->getZExtValue();75 }76}77 78void DiagnosticInfoInlineAsm::print(DiagnosticPrinter &DP) const {79 DP << getMsgStr();80 if (getLocCookie())81 DP << " at line " << getLocCookie();82}83 84void DiagnosticInfoLegalizationFailure::print(DiagnosticPrinter &DP) const {85 DP << getLocationStr() << ": " << getMsgStr();86}87 88DiagnosticInfoRegAllocFailure::DiagnosticInfoRegAllocFailure(89 const Twine &MsgStr, const Function &Fn, const DiagnosticLocation &DL,90 DiagnosticSeverity Severity)91 : DiagnosticInfoWithLocationBase(DK_RegAllocFailure, Severity, Fn,92 DL.isValid() ? DL : Fn.getSubprogram()),93 MsgStr(MsgStr) {}94 95DiagnosticInfoRegAllocFailure::DiagnosticInfoRegAllocFailure(96 const Twine &MsgStr, const Function &Fn, DiagnosticSeverity Severity)97 : DiagnosticInfoWithLocationBase(DK_RegAllocFailure, Severity, Fn,98 Fn.getSubprogram()),99 MsgStr(MsgStr) {}100 101void DiagnosticInfoRegAllocFailure::print(DiagnosticPrinter &DP) const {102 DP << getLocationStr() << ": " << MsgStr << " in function '" << getFunction()103 << '\'';104}105 106DiagnosticInfoResourceLimit::DiagnosticInfoResourceLimit(107 const Function &Fn, const char *ResourceName, uint64_t ResourceSize,108 uint64_t ResourceLimit, DiagnosticSeverity Severity, DiagnosticKind Kind)109 : DiagnosticInfoWithLocationBase(Kind, Severity, Fn, Fn.getSubprogram()),110 Fn(Fn), ResourceName(ResourceName), ResourceSize(ResourceSize),111 ResourceLimit(ResourceLimit) {}112 113void DiagnosticInfoResourceLimit::print(DiagnosticPrinter &DP) const {114 DP << getLocationStr() << ": " << getResourceName() << " ("115 << getResourceSize() << ") exceeds limit (" << getResourceLimit()116 << ") in function '" << getFunction() << '\'';117}118 119void DiagnosticInfoDebugMetadataVersion::print(DiagnosticPrinter &DP) const {120 DP << "ignoring debug info with an invalid version (" << getMetadataVersion()121 << ") in " << getModule();122}123 124void DiagnosticInfoIgnoringInvalidDebugMetadata::print(125 DiagnosticPrinter &DP) const {126 DP << "ignoring invalid debug info in " << getModule().getModuleIdentifier();127}128 129void DiagnosticInfoSampleProfile::print(DiagnosticPrinter &DP) const {130 if (!FileName.empty()) {131 DP << getFileName();132 if (LineNum > 0)133 DP << ":" << getLineNum();134 DP << ": ";135 }136 DP << getMsg();137}138 139void DiagnosticInfoPGOProfile::print(DiagnosticPrinter &DP) const {140 if (getFileName())141 DP << getFileName() << ": ";142 DP << getMsg();143}144 145void DiagnosticInfo::anchor() {}146void DiagnosticInfoStackSize::anchor() {}147void DiagnosticInfoWithLocationBase::anchor() {}148void DiagnosticInfoIROptimization::anchor() {}149 150DiagnosticLocation::DiagnosticLocation(const DebugLoc &DL) {151 if (!DL)152 return;153 File = DL->getFile();154 Line = DL->getLine();155 Column = DL->getColumn();156}157 158DiagnosticLocation::DiagnosticLocation(const DISubprogram *SP) {159 if (!SP)160 return;161 162 File = SP->getFile();163 Line = SP->getScopeLine();164 Column = 0;165}166 167StringRef DiagnosticLocation::getRelativePath() const {168 return File->getFilename();169}170 171std::string DiagnosticLocation::getAbsolutePath() const {172 StringRef Name = File->getFilename();173 if (sys::path::is_absolute(Name))174 return std::string(Name);175 176 SmallString<128> Path;177 sys::path::append(Path, File->getDirectory(), Name);178 return sys::path::remove_leading_dotslash(Path).str();179}180 181std::string DiagnosticInfoWithLocationBase::getAbsolutePath() const {182 return Loc.getAbsolutePath();183}184 185void DiagnosticInfoWithLocationBase::getLocation(StringRef &RelativePath,186 unsigned &Line,187 unsigned &Column) const {188 RelativePath = Loc.getRelativePath();189 Line = Loc.getLine();190 Column = Loc.getColumn();191}192 193std::string DiagnosticInfoWithLocationBase::getLocationStr() const {194 StringRef Filename("<unknown>");195 unsigned Line = 0;196 unsigned Column = 0;197 if (isLocationAvailable())198 getLocation(Filename, Line, Column);199 return (Filename + ":" + Twine(Line) + ":" + Twine(Column)).str();200}201 202DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,203 const Value *V)204 : Key(std::string(Key)) {205 if (auto *F = dyn_cast<Function>(V)) {206 if (DISubprogram *SP = F->getSubprogram())207 Loc = SP;208 }209 else if (auto *I = dyn_cast<Instruction>(V))210 Loc = I->getDebugLoc();211 212 // Only include names that correspond to user variables. FIXME: We should use213 // debug info if available to get the name of the user variable.214 if (isa<llvm::Argument>(V) || isa<GlobalValue>(V))215 Val = std::string(GlobalValue::dropLLVMManglingEscape(V->getName()));216 else if (isa<Constant>(V)) {217 raw_string_ostream OS(Val);218 V->printAsOperand(OS, /*PrintType=*/false);219 } else if (auto *II = dyn_cast<IntrinsicInst>(V)) {220 raw_string_ostream OS(Val);221 OS << "call " << II->getCalledFunction()->getName();222 } else if (auto *I = dyn_cast<Instruction>(V)) {223 Val = I->getOpcodeName();224 } else if (auto *MD = dyn_cast<MetadataAsValue>(V)) {225 if (auto *S = dyn_cast<MDString>(MD->getMetadata()))226 Val = S->getString();227 }228}229 230DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, const Type *T)231 : Key(std::string(Key)) {232 raw_string_ostream OS(Val);233 OS << *T;234}235 236DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, StringRef S)237 : Key(std::string(Key)), Val(S.str()) {}238 239DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, int N)240 : Key(std::string(Key)), Val(itostr(N)) {}241 242DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, float N)243 : Key(std::string(Key)), Val(llvm::to_string(N)) {}244 245DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, long N)246 : Key(std::string(Key)), Val(itostr(N)) {}247 248DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, long long N)249 : Key(std::string(Key)), Val(itostr(N)) {}250 251DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, unsigned N)252 : Key(std::string(Key)), Val(utostr(N)) {}253 254DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,255 unsigned long N)256 : Key(std::string(Key)), Val(utostr(N)) {}257 258DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,259 unsigned long long N)260 : Key(std::string(Key)), Val(utostr(N)) {}261 262DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,263 ElementCount EC)264 : Key(std::string(Key)) {265 raw_string_ostream OS(Val);266 EC.print(OS);267}268 269DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,270 InstructionCost C)271 : Key(std::string(Key)) {272 raw_string_ostream OS(Val);273 C.print(OS);274}275 276DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,277 BranchProbability P)278 : Key(std::string(Key)) {279 raw_string_ostream OS(Val);280 P.print(OS);281}282 283DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, DebugLoc Loc)284 : Key(std::string(Key)), Loc(Loc) {285 if (Loc) {286 Val = (Loc->getFilename() + ":" + Twine(Loc.getLine()) + ":" +287 Twine(Loc.getCol())).str();288 } else {289 Val = "<UNKNOWN LOCATION>";290 }291}292 293void DiagnosticInfoOptimizationBase::print(DiagnosticPrinter &DP) const {294 DP << getLocationStr() << ": " << getMsg();295 if (Hotness)296 DP << " (hotness: " << *Hotness << ")";297}298 299OptimizationRemark::OptimizationRemark(const char *PassName,300 StringRef RemarkName,301 const DiagnosticLocation &Loc,302 const BasicBlock *CodeRegion)303 : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,304 RemarkName, *CodeRegion->getParent(), Loc,305 CodeRegion) {}306 307OptimizationRemark::OptimizationRemark(const char *PassName,308 StringRef RemarkName,309 const Instruction *Inst)310 : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,311 RemarkName, *Inst->getParent()->getParent(),312 Inst->getDebugLoc(), Inst->getParent()) {}313 314static const BasicBlock *getFirstFunctionBlock(const Function *Func) {315 return Func->empty() ? nullptr : &Func->front();316}317 318OptimizationRemark::OptimizationRemark(const char *PassName,319 StringRef RemarkName,320 const Function *Func)321 : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,322 RemarkName, *Func, Func->getSubprogram(),323 getFirstFunctionBlock(Func)) {}324 325bool OptimizationRemark::isEnabled() const {326 const Function &Fn = getFunction();327 LLVMContext &Ctx = Fn.getContext();328 return Ctx.getDiagHandlerPtr()->isPassedOptRemarkEnabled(getPassName());329}330 331OptimizationRemarkMissed::OptimizationRemarkMissed(332 const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,333 const BasicBlock *CodeRegion)334 : DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark,335 PassName, RemarkName,336 *CodeRegion->getParent(), Loc, CodeRegion) {}337 338OptimizationRemarkMissed::OptimizationRemarkMissed(const char *PassName,339 StringRef RemarkName,340 const Instruction *Inst)341 : DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark,342 PassName, RemarkName,343 *Inst->getParent()->getParent(),344 Inst->getDebugLoc(), Inst->getParent()) {}345 346OptimizationRemarkMissed::OptimizationRemarkMissed(const char *PassName,347 StringRef RemarkName,348 const Function *Func)349 : DiagnosticInfoIROptimization(350 DK_OptimizationRemarkMissed, DS_Remark, PassName, RemarkName, *Func,351 Func->getSubprogram(), getFirstFunctionBlock(Func)) {}352 353bool OptimizationRemarkMissed::isEnabled() const {354 const Function &Fn = getFunction();355 LLVMContext &Ctx = Fn.getContext();356 return Ctx.getDiagHandlerPtr()->isMissedOptRemarkEnabled(getPassName());357}358 359OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(360 const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,361 const BasicBlock *CodeRegion)362 : DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark,363 PassName, RemarkName,364 *CodeRegion->getParent(), Loc, CodeRegion) {}365 366OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(const char *PassName,367 StringRef RemarkName,368 const Instruction *Inst)369 : DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark,370 PassName, RemarkName,371 *Inst->getParent()->getParent(),372 Inst->getDebugLoc(), Inst->getParent()) {}373 374OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(375 enum DiagnosticKind Kind, const char *PassName, StringRef RemarkName,376 const DiagnosticLocation &Loc, const BasicBlock *CodeRegion)377 : DiagnosticInfoIROptimization(Kind, DS_Remark, PassName, RemarkName,378 *CodeRegion->getParent(), Loc, CodeRegion) {}379 380OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(const char *PassName,381 StringRef RemarkName,382 const Function *Func)383 : DiagnosticInfoIROptimization(384 DK_OptimizationRemarkAnalysis, DS_Remark, PassName, RemarkName, *Func,385 Func->getSubprogram(), getFirstFunctionBlock(Func)) {}386 387bool OptimizationRemarkAnalysis::isEnabled() const {388 const Function &Fn = getFunction();389 LLVMContext &Ctx = Fn.getContext();390 return Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(getPassName()) ||391 shouldAlwaysPrint();392}393 394void DiagnosticInfoMIRParser::print(DiagnosticPrinter &DP) const {395 DP << Diagnostic;396}397 398void DiagnosticInfoSrcMgr::print(DiagnosticPrinter &DP) const {399 DP << Diagnostic;400}401 402DiagnosticInfoOptimizationFailure::DiagnosticInfoOptimizationFailure(403 const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,404 const BasicBlock *CodeRegion)405 : DiagnosticInfoIROptimization(DK_OptimizationFailure, DS_Warning, PassName,406 RemarkName, *CodeRegion->getParent(), Loc,407 CodeRegion) {}408 409bool DiagnosticInfoOptimizationFailure::isEnabled() const {410 // Only print warnings.411 return getSeverity() == DS_Warning;412}413 414void DiagnosticInfoUnsupported::print(DiagnosticPrinter &DP) const {415 std::string Str;416 raw_string_ostream OS(Str);417 418 OS << getLocationStr() << ": in function " << getFunction().getName() << ' '419 << *getFunction().getFunctionType() << ": " << Msg << '\n';420 OS.flush();421 DP << Str;422}423 424void DiagnosticInfoInstrumentation::print(DiagnosticPrinter &DP) const {425 DP << Msg;426}427 428void DiagnosticInfoISelFallback::print(DiagnosticPrinter &DP) const {429 DP << "Instruction selection used fallback path for " << getFunction();430}431 432void DiagnosticInfoOptimizationBase::insert(StringRef S) {433 Args.emplace_back(S);434}435 436void DiagnosticInfoOptimizationBase::insert(Argument A) {437 Args.push_back(std::move(A));438}439 440void DiagnosticInfoOptimizationBase::insert(setIsVerbose V) {441 IsVerbose = true;442}443 444void DiagnosticInfoOptimizationBase::insert(setExtraArgs EA) {445 FirstExtraArgIndex = Args.size();446}447 448std::string DiagnosticInfoOptimizationBase::getMsg() const {449 std::string Str;450 raw_string_ostream OS(Str);451 for (const DiagnosticInfoOptimizationBase::Argument &Arg :452 make_range(Args.begin(), FirstExtraArgIndex == -1453 ? Args.end()454 : Args.begin() + FirstExtraArgIndex))455 OS << Arg.Val;456 return Str;457}458 459DiagnosticInfoMisExpect::DiagnosticInfoMisExpect(const Instruction *Inst,460 const Twine &Msg)461 : DiagnosticInfoWithLocationBase(DK_MisExpect, DS_Warning,462 *Inst->getParent()->getParent(),463 Inst->getDebugLoc()),464 Msg(Msg) {}465 466void DiagnosticInfoMisExpect::print(DiagnosticPrinter &DP) const {467 DP << getLocationStr() << ": " << getMsg();468}469 470void OptimizationRemarkAnalysisFPCommute::anchor() {}471void OptimizationRemarkAnalysisAliasing::anchor() {}472 473void llvm::diagnoseDontCall(const CallInst &CI) {474 const auto *F =475 dyn_cast<Function>(CI.getCalledOperand()->stripPointerCasts());476 477 if (!F)478 return;479 480 for (int i = 0; i != 2; ++i) {481 auto AttrName = i == 0 ? "dontcall-error" : "dontcall-warn";482 auto Sev = i == 0 ? DS_Error : DS_Warning;483 484 if (F->hasFnAttribute(AttrName)) {485 uint64_t LocCookie = 0;486 auto A = F->getFnAttribute(AttrName);487 if (MDNode *MD = CI.getMetadata("srcloc"))488 LocCookie =489 mdconst::extract<ConstantInt>(MD->getOperand(0))->getZExtValue();490 DiagnosticInfoDontCall D(F->getName(), A.getValueAsString(), Sev,491 LocCookie);492 F->getContext().diagnose(D);493 }494 }495}496 497void DiagnosticInfoDontCall::print(DiagnosticPrinter &DP) const {498 DP << "call to " << demangle(getFunctionName()) << " marked \"dontcall-";499 if (getSeverity() == DiagnosticSeverity::DS_Error)500 DP << "error\"";501 else502 DP << "warn\"";503 if (!getNote().empty())504 DP << ": " << getNote();505}506