Home | History | Annotate | Line # | Download | only in IR
      1 //===- llvm/Support/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-exception
      6 //
      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 "LLVMContextImpl.h"
     16 #include "llvm/ADT/StringExtras.h"
     17 #include "llvm/ADT/Twine.h"
     18 #include "llvm/ADT/iterator_range.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/LLVMContext.h"
     28 #include "llvm/IR/Metadata.h"
     29 #include "llvm/IR/Module.h"
     30 #include "llvm/IR/Type.h"
     31 #include "llvm/IR/Value.h"
     32 #include "llvm/Support/Casting.h"
     33 #include "llvm/Support/CommandLine.h"
     34 #include "llvm/Support/ErrorHandling.h"
     35 #include "llvm/Support/InstructionCost.h"
     36 #include "llvm/Support/Path.h"
     37 #include "llvm/Support/Regex.h"
     38 #include "llvm/Support/ScopedPrinter.h"
     39 #include "llvm/Support/raw_ostream.h"
     40 #include <atomic>
     41 #include <cassert>
     42 #include <memory>
     43 #include <string>
     44 
     45 using namespace llvm;
     46 
     47 int llvm::getNextAvailablePluginDiagnosticKind() {
     48   static std::atomic<int> PluginKindID(DK_FirstPluginKind);
     49   return ++PluginKindID;
     50 }
     51 
     52 const char *OptimizationRemarkAnalysis::AlwaysPrint = "";
     53 
     54 DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(const Instruction &I,
     55                                                  const Twine &MsgStr,
     56                                                  DiagnosticSeverity Severity)
     57     : DiagnosticInfo(DK_InlineAsm, Severity), MsgStr(MsgStr), Instr(&I) {
     58   if (const MDNode *SrcLoc = I.getMetadata("srcloc")) {
     59     if (SrcLoc->getNumOperands() != 0)
     60       if (const auto *CI =
     61               mdconst::dyn_extract<ConstantInt>(SrcLoc->getOperand(0)))
     62         LocCookie = CI->getZExtValue();
     63   }
     64 }
     65 
     66 void DiagnosticInfoInlineAsm::print(DiagnosticPrinter &DP) const {
     67   DP << getMsgStr();
     68   if (getLocCookie())
     69     DP << " at line " << getLocCookie();
     70 }
     71 
     72 void DiagnosticInfoResourceLimit::print(DiagnosticPrinter &DP) const {
     73   DP << getResourceName() << " limit";
     74 
     75   if (getResourceLimit() != 0)
     76     DP << " of " << getResourceLimit();
     77 
     78   DP << " exceeded (" <<  getResourceSize() << ") in " << getFunction();
     79 }
     80 
     81 void DiagnosticInfoDebugMetadataVersion::print(DiagnosticPrinter &DP) const {
     82   DP << "ignoring debug info with an invalid version (" << getMetadataVersion()
     83      << ") in " << getModule();
     84 }
     85 
     86 void DiagnosticInfoIgnoringInvalidDebugMetadata::print(
     87     DiagnosticPrinter &DP) const {
     88   DP << "ignoring invalid debug info in " << getModule().getModuleIdentifier();
     89 }
     90 
     91 void DiagnosticInfoSampleProfile::print(DiagnosticPrinter &DP) const {
     92   if (!FileName.empty()) {
     93     DP << getFileName();
     94     if (LineNum > 0)
     95       DP << ":" << getLineNum();
     96     DP << ": ";
     97   }
     98   DP << getMsg();
     99 }
    100 
    101 void DiagnosticInfoPGOProfile::print(DiagnosticPrinter &DP) const {
    102   if (getFileName())
    103     DP << getFileName() << ": ";
    104   DP << getMsg();
    105 }
    106 
    107 void DiagnosticInfo::anchor() {}
    108 void DiagnosticInfoStackSize::anchor() {}
    109 void DiagnosticInfoWithLocationBase::anchor() {}
    110 void DiagnosticInfoIROptimization::anchor() {}
    111 
    112 DiagnosticLocation::DiagnosticLocation(const DebugLoc &DL) {
    113   if (!DL)
    114     return;
    115   File = DL->getFile();
    116   Line = DL->getLine();
    117   Column = DL->getColumn();
    118 }
    119 
    120 DiagnosticLocation::DiagnosticLocation(const DISubprogram *SP) {
    121   if (!SP)
    122     return;
    123 
    124   File = SP->getFile();
    125   Line = SP->getScopeLine();
    126   Column = 0;
    127 }
    128 
    129 StringRef DiagnosticLocation::getRelativePath() const {
    130   return File->getFilename();
    131 }
    132 
    133 std::string DiagnosticLocation::getAbsolutePath() const {
    134   StringRef Name = File->getFilename();
    135   if (sys::path::is_absolute(Name))
    136     return std::string(Name);
    137 
    138   SmallString<128> Path;
    139   sys::path::append(Path, File->getDirectory(), Name);
    140   return sys::path::remove_leading_dotslash(Path).str();
    141 }
    142 
    143 std::string DiagnosticInfoWithLocationBase::getAbsolutePath() const {
    144   return Loc.getAbsolutePath();
    145 }
    146 
    147 void DiagnosticInfoWithLocationBase::getLocation(StringRef &RelativePath,
    148                                                  unsigned &Line,
    149                                                  unsigned &Column) const {
    150   RelativePath = Loc.getRelativePath();
    151   Line = Loc.getLine();
    152   Column = Loc.getColumn();
    153 }
    154 
    155 std::string DiagnosticInfoWithLocationBase::getLocationStr() const {
    156   StringRef Filename("<unknown>");
    157   unsigned Line = 0;
    158   unsigned Column = 0;
    159   if (isLocationAvailable())
    160     getLocation(Filename, Line, Column);
    161   return (Filename + ":" + Twine(Line) + ":" + Twine(Column)).str();
    162 }
    163 
    164 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
    165                                                    const Value *V)
    166     : Key(std::string(Key)) {
    167   if (auto *F = dyn_cast<Function>(V)) {
    168     if (DISubprogram *SP = F->getSubprogram())
    169       Loc = SP;
    170   }
    171   else if (auto *I = dyn_cast<Instruction>(V))
    172     Loc = I->getDebugLoc();
    173 
    174   // Only include names that correspond to user variables.  FIXME: We should use
    175   // debug info if available to get the name of the user variable.
    176   if (isa<llvm::Argument>(V) || isa<GlobalValue>(V))
    177     Val = std::string(GlobalValue::dropLLVMManglingEscape(V->getName()));
    178   else if (isa<Constant>(V)) {
    179     raw_string_ostream OS(Val);
    180     V->printAsOperand(OS, /*PrintType=*/false);
    181   } else if (auto *I = dyn_cast<Instruction>(V))
    182     Val = I->getOpcodeName();
    183 }
    184 
    185 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, const Type *T)
    186     : Key(std::string(Key)) {
    187   raw_string_ostream OS(Val);
    188   OS << *T;
    189 }
    190 
    191 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, StringRef S)
    192     : Key(std::string(Key)), Val(S.str()) {}
    193 
    194 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, int N)
    195     : Key(std::string(Key)), Val(itostr(N)) {}
    196 
    197 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, float N)
    198     : Key(std::string(Key)), Val(llvm::to_string(N)) {}
    199 
    200 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, long N)
    201     : Key(std::string(Key)), Val(itostr(N)) {}
    202 
    203 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, long long N)
    204     : Key(std::string(Key)), Val(itostr(N)) {}
    205 
    206 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, unsigned N)
    207     : Key(std::string(Key)), Val(utostr(N)) {}
    208 
    209 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
    210                                                    unsigned long N)
    211     : Key(std::string(Key)), Val(utostr(N)) {}
    212 
    213 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
    214                                                    unsigned long long N)
    215     : Key(std::string(Key)), Val(utostr(N)) {}
    216 
    217 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
    218                                                    ElementCount EC)
    219     : Key(std::string(Key)) {
    220   raw_string_ostream OS(Val);
    221   EC.print(OS);
    222 }
    223 
    224 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
    225                                                    InstructionCost C)
    226     : Key(std::string(Key)) {
    227   raw_string_ostream OS(Val);
    228   C.print(OS);
    229 }
    230 
    231 DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, DebugLoc Loc)
    232     : Key(std::string(Key)), Loc(Loc) {
    233   if (Loc) {
    234     Val = (Loc->getFilename() + ":" + Twine(Loc.getLine()) + ":" +
    235            Twine(Loc.getCol())).str();
    236   } else {
    237     Val = "<UNKNOWN LOCATION>";
    238   }
    239 }
    240 
    241 void DiagnosticInfoOptimizationBase::print(DiagnosticPrinter &DP) const {
    242   DP << getLocationStr() << ": " << getMsg();
    243   if (Hotness)
    244     DP << " (hotness: " << *Hotness << ")";
    245 }
    246 
    247 OptimizationRemark::OptimizationRemark(const char *PassName,
    248                                        StringRef RemarkName,
    249                                        const DiagnosticLocation &Loc,
    250                                        const Value *CodeRegion)
    251     : DiagnosticInfoIROptimization(
    252           DK_OptimizationRemark, DS_Remark, PassName, RemarkName,
    253           *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {}
    254 
    255 OptimizationRemark::OptimizationRemark(const char *PassName,
    256                                        StringRef RemarkName,
    257                                        const Instruction *Inst)
    258     : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,
    259                                    RemarkName, *Inst->getParent()->getParent(),
    260                                    Inst->getDebugLoc(), Inst->getParent()) {}
    261 
    262 static const BasicBlock *getFirstFunctionBlock(const Function *Func) {
    263   return Func->empty() ? nullptr : &Func->front();
    264 }
    265 
    266 OptimizationRemark::OptimizationRemark(const char *PassName,
    267                                        StringRef RemarkName,
    268                                        const Function *Func)
    269     : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName,
    270                                    RemarkName, *Func, Func->getSubprogram(),
    271                                    getFirstFunctionBlock(Func)) {}
    272 
    273 bool OptimizationRemark::isEnabled() const {
    274   const Function &Fn = getFunction();
    275   LLVMContext &Ctx = Fn.getContext();
    276   return Ctx.getDiagHandlerPtr()->isPassedOptRemarkEnabled(getPassName());
    277 }
    278 
    279 OptimizationRemarkMissed::OptimizationRemarkMissed(
    280     const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,
    281     const Value *CodeRegion)
    282     : DiagnosticInfoIROptimization(
    283           DK_OptimizationRemarkMissed, DS_Remark, PassName, RemarkName,
    284           *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {}
    285 
    286 OptimizationRemarkMissed::OptimizationRemarkMissed(const char *PassName,
    287                                                    StringRef RemarkName,
    288                                                    const Instruction *Inst)
    289     : DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark,
    290                                    PassName, RemarkName,
    291                                    *Inst->getParent()->getParent(),
    292                                    Inst->getDebugLoc(), Inst->getParent()) {}
    293 
    294 OptimizationRemarkMissed::OptimizationRemarkMissed(const char *PassName,
    295                                                    StringRef RemarkName,
    296                                                    const Function *Func)
    297     : DiagnosticInfoIROptimization(
    298           DK_OptimizationRemarkMissed, DS_Remark, PassName, RemarkName, *Func,
    299           Func->getSubprogram(), getFirstFunctionBlock(Func)) {}
    300 
    301 bool OptimizationRemarkMissed::isEnabled() const {
    302   const Function &Fn = getFunction();
    303   LLVMContext &Ctx = Fn.getContext();
    304   return Ctx.getDiagHandlerPtr()->isMissedOptRemarkEnabled(getPassName());
    305 }
    306 
    307 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(
    308     const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,
    309     const Value *CodeRegion)
    310     : DiagnosticInfoIROptimization(
    311           DK_OptimizationRemarkAnalysis, DS_Remark, PassName, RemarkName,
    312           *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {}
    313 
    314 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(const char *PassName,
    315                                                        StringRef RemarkName,
    316                                                        const Instruction *Inst)
    317     : DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark,
    318                                    PassName, RemarkName,
    319                                    *Inst->getParent()->getParent(),
    320                                    Inst->getDebugLoc(), Inst->getParent()) {}
    321 
    322 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(
    323     enum DiagnosticKind Kind, const char *PassName, StringRef RemarkName,
    324     const DiagnosticLocation &Loc, const Value *CodeRegion)
    325     : DiagnosticInfoIROptimization(Kind, DS_Remark, PassName, RemarkName,
    326                                    *cast<BasicBlock>(CodeRegion)->getParent(),
    327                                    Loc, CodeRegion) {}
    328 
    329 OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(const char *PassName,
    330                                                        StringRef RemarkName,
    331                                                        const Function *Func)
    332     : DiagnosticInfoIROptimization(
    333           DK_OptimizationRemarkAnalysis, DS_Remark, PassName, RemarkName, *Func,
    334           Func->getSubprogram(), getFirstFunctionBlock(Func)) {}
    335 
    336 bool OptimizationRemarkAnalysis::isEnabled() const {
    337   const Function &Fn = getFunction();
    338   LLVMContext &Ctx = Fn.getContext();
    339   return Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(getPassName()) ||
    340          shouldAlwaysPrint();
    341 }
    342 
    343 void DiagnosticInfoMIRParser::print(DiagnosticPrinter &DP) const {
    344   DP << Diagnostic;
    345 }
    346 
    347 void DiagnosticInfoSrcMgr::print(DiagnosticPrinter &DP) const {
    348   DP << Diagnostic;
    349 }
    350 
    351 DiagnosticInfoOptimizationFailure::DiagnosticInfoOptimizationFailure(
    352     const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,
    353     const Value *CodeRegion)
    354     : DiagnosticInfoIROptimization(
    355           DK_OptimizationFailure, DS_Warning, PassName, RemarkName,
    356           *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {}
    357 
    358 bool DiagnosticInfoOptimizationFailure::isEnabled() const {
    359   // Only print warnings.
    360   return getSeverity() == DS_Warning;
    361 }
    362 
    363 void DiagnosticInfoUnsupported::print(DiagnosticPrinter &DP) const {
    364   std::string Str;
    365   raw_string_ostream OS(Str);
    366 
    367   OS << getLocationStr() << ": in function " << getFunction().getName() << ' '
    368      << *getFunction().getFunctionType() << ": " << Msg << '\n';
    369   OS.flush();
    370   DP << Str;
    371 }
    372 
    373 void DiagnosticInfoISelFallback::print(DiagnosticPrinter &DP) const {
    374   DP << "Instruction selection used fallback path for " << getFunction();
    375 }
    376 
    377 void DiagnosticInfoOptimizationBase::insert(StringRef S) {
    378   Args.emplace_back(S);
    379 }
    380 
    381 void DiagnosticInfoOptimizationBase::insert(Argument A) {
    382   Args.push_back(std::move(A));
    383 }
    384 
    385 void DiagnosticInfoOptimizationBase::insert(setIsVerbose V) {
    386   IsVerbose = true;
    387 }
    388 
    389 void DiagnosticInfoOptimizationBase::insert(setExtraArgs EA) {
    390   FirstExtraArgIndex = Args.size();
    391 }
    392 
    393 std::string DiagnosticInfoOptimizationBase::getMsg() const {
    394   std::string Str;
    395   raw_string_ostream OS(Str);
    396   for (const DiagnosticInfoOptimizationBase::Argument &Arg :
    397        make_range(Args.begin(), FirstExtraArgIndex == -1
    398                                     ? Args.end()
    399                                     : Args.begin() + FirstExtraArgIndex))
    400     OS << Arg.Val;
    401   return OS.str();
    402 }
    403 
    404 void OptimizationRemarkAnalysisFPCommute::anchor() {}
    405 void OptimizationRemarkAnalysisAliasing::anchor() {}
    406