diff options
Diffstat (limited to 'llvm/lib/IR/DiagnosticInfo.cpp')
| -rw-r--r-- | llvm/lib/IR/DiagnosticInfo.cpp | 385 | 
1 files changed, 385 insertions, 0 deletions
diff --git a/llvm/lib/IR/DiagnosticInfo.cpp b/llvm/lib/IR/DiagnosticInfo.cpp new file mode 100644 index 0000000000000..99d5aec3f043e --- /dev/null +++ b/llvm/lib/IR/DiagnosticInfo.cpp @@ -0,0 +1,385 @@ +//===- llvm/Support/DiagnosticInfo.cpp - Diagnostic Definitions -*- C++ -*-===// +// +// 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 defines the different classes involved in low level diagnostics. +// +// Diagnostics reporting is still done as part of the LLVMContext. +//===----------------------------------------------------------------------===// + +#include "llvm/IR/DiagnosticInfo.h" +#include "LLVMContextImpl.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/Twine.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/DiagnosticPrinter.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Metadata.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/Value.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Regex.h" +#include "llvm/Support/ScopedPrinter.h" +#include "llvm/Support/raw_ostream.h" +#include <atomic> +#include <cassert> +#include <memory> +#include <string> + +using namespace llvm; + +int llvm::getNextAvailablePluginDiagnosticKind() { +  static std::atomic<int> PluginKindID(DK_FirstPluginKind); +  return ++PluginKindID; +} + +const char *OptimizationRemarkAnalysis::AlwaysPrint = ""; + +DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(const Instruction &I, +                                                 const Twine &MsgStr, +                                                 DiagnosticSeverity Severity) +    : DiagnosticInfo(DK_InlineAsm, Severity), MsgStr(MsgStr), Instr(&I) { +  if (const MDNode *SrcLoc = I.getMetadata("srcloc")) { +    if (SrcLoc->getNumOperands() != 0) +      if (const auto *CI = +              mdconst::dyn_extract<ConstantInt>(SrcLoc->getOperand(0))) +        LocCookie = CI->getZExtValue(); +  } +} + +void DiagnosticInfoInlineAsm::print(DiagnosticPrinter &DP) const { +  DP << getMsgStr(); +  if (getLocCookie()) +    DP << " at line " << getLocCookie(); +} + +void DiagnosticInfoResourceLimit::print(DiagnosticPrinter &DP) const { +  DP << getResourceName() << " limit"; + +  if (getResourceLimit() != 0) +    DP << " of " << getResourceLimit(); + +  DP << " exceeded (" <<  getResourceSize() << ") in " << getFunction(); +} + +void DiagnosticInfoDebugMetadataVersion::print(DiagnosticPrinter &DP) const { +  DP << "ignoring debug info with an invalid version (" << getMetadataVersion() +     << ") in " << getModule(); +} + +void DiagnosticInfoIgnoringInvalidDebugMetadata::print( +    DiagnosticPrinter &DP) const { +  DP << "ignoring invalid debug info in " << getModule().getModuleIdentifier(); +} + +void DiagnosticInfoSampleProfile::print(DiagnosticPrinter &DP) const { +  if (!FileName.empty()) { +    DP << getFileName(); +    if (LineNum > 0) +      DP << ":" << getLineNum(); +    DP << ": "; +  } +  DP << getMsg(); +} + +void DiagnosticInfoPGOProfile::print(DiagnosticPrinter &DP) const { +  if (getFileName()) +    DP << getFileName() << ": "; +  DP << getMsg(); +} + +void DiagnosticInfo::anchor() {} +void DiagnosticInfoStackSize::anchor() {} +void DiagnosticInfoWithLocationBase::anchor() {} +void DiagnosticInfoIROptimization::anchor() {} + +DiagnosticLocation::DiagnosticLocation(const DebugLoc &DL) { +  if (!DL) +    return; +  File = DL->getFile(); +  Line = DL->getLine(); +  Column = DL->getColumn(); +} + +DiagnosticLocation::DiagnosticLocation(const DISubprogram *SP) { +  if (!SP) +    return; +   +  File = SP->getFile(); +  Line = SP->getScopeLine(); +  Column = 0; +} + +StringRef DiagnosticLocation::getRelativePath() const { +  return File->getFilename(); +} + +std::string DiagnosticLocation::getAbsolutePath() const { +  StringRef Name = File->getFilename(); +  if (sys::path::is_absolute(Name)) +    return Name; + +  SmallString<128> Path; +  sys::path::append(Path, File->getDirectory(), Name); +  return sys::path::remove_leading_dotslash(Path).str(); +} + +std::string DiagnosticInfoWithLocationBase::getAbsolutePath() const { +  return Loc.getAbsolutePath(); +} + +void DiagnosticInfoWithLocationBase::getLocation(StringRef &RelativePath, +                                                 unsigned &Line, +                                                 unsigned &Column) const { +  RelativePath = Loc.getRelativePath(); +  Line = Loc.getLine(); +  Column = Loc.getColumn(); +} + +const std::string DiagnosticInfoWithLocationBase::getLocationStr() const { +  StringRef Filename("<unknown>"); +  unsigned Line = 0; +  unsigned Column = 0; +  if (isLocationAvailable()) +    getLocation(Filename, Line, Column); +  return (Filename + ":" + Twine(Line) + ":" + Twine(Column)).str(); +} + +DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, const Value *V) +    : Key(Key) { +  if (auto *F = dyn_cast<Function>(V)) { +    if (DISubprogram *SP = F->getSubprogram()) +      Loc = SP; +  } +  else if (auto *I = dyn_cast<Instruction>(V)) +    Loc = I->getDebugLoc(); + +  // Only include names that correspond to user variables.  FIXME: We should use +  // debug info if available to get the name of the user variable. +  if (isa<llvm::Argument>(V) || isa<GlobalValue>(V)) +    Val = GlobalValue::dropLLVMManglingEscape(V->getName()); +  else if (isa<Constant>(V)) { +    raw_string_ostream OS(Val); +    V->printAsOperand(OS, /*PrintType=*/false); +  } else if (auto *I = dyn_cast<Instruction>(V)) +    Val = I->getOpcodeName(); +} + +DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, const Type *T) +    : Key(Key) { +  raw_string_ostream OS(Val); +  OS << *T; +} + +DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, StringRef S) +    : Key(Key), Val(S.str()) {} + +DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, int N) +    : Key(Key), Val(itostr(N)) {} + +DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, float N) +    : Key(Key), Val(llvm::to_string(N)) {} + +DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, long N) +    : Key(Key), Val(itostr(N)) {} + +DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, long long N) +    : Key(Key), Val(itostr(N)) {} + +DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, unsigned N) +    : Key(Key), Val(utostr(N)) {} + +DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, +                                                   unsigned long N) +    : Key(Key), Val(utostr(N)) {} + +DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, +                                                   unsigned long long N) +    : Key(Key), Val(utostr(N)) {} + +DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, DebugLoc Loc) +    : Key(Key), Loc(Loc) { +  if (Loc) { +    Val = (Loc->getFilename() + ":" + Twine(Loc.getLine()) + ":" + +           Twine(Loc.getCol())).str(); +  } else { +    Val = "<UNKNOWN LOCATION>"; +  } +} + +void DiagnosticInfoOptimizationBase::print(DiagnosticPrinter &DP) const { +  DP << getLocationStr() << ": " << getMsg(); +  if (Hotness) +    DP << " (hotness: " << *Hotness << ")"; +} + +OptimizationRemark::OptimizationRemark(const char *PassName, +                                       StringRef RemarkName, +                                       const DiagnosticLocation &Loc, +                                       const Value *CodeRegion) +    : DiagnosticInfoIROptimization( +          DK_OptimizationRemark, DS_Remark, PassName, RemarkName, +          *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {} + +OptimizationRemark::OptimizationRemark(const char *PassName, +                                       StringRef RemarkName, +                                       const Instruction *Inst) +    : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName, +                                   RemarkName, *Inst->getParent()->getParent(), +                                   Inst->getDebugLoc(), Inst->getParent()) {} + +// Helper to allow for an assert before attempting to return an invalid +// reference. +static const BasicBlock &getFirstFunctionBlock(const Function *Func) { +  assert(!Func->empty() && "Function does not have a body"); +  return Func->front(); +} + +OptimizationRemark::OptimizationRemark(const char *PassName, +                                       StringRef RemarkName, +                                       const Function *Func) +    : DiagnosticInfoIROptimization(DK_OptimizationRemark, DS_Remark, PassName, +                                   RemarkName, *Func, Func->getSubprogram(), +                                   &getFirstFunctionBlock(Func)) {} + +bool OptimizationRemark::isEnabled() const { +  const Function &Fn = getFunction(); +  LLVMContext &Ctx = Fn.getContext(); +  return Ctx.getDiagHandlerPtr()->isPassedOptRemarkEnabled(getPassName()); +} + +OptimizationRemarkMissed::OptimizationRemarkMissed( +    const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc, +    const Value *CodeRegion) +    : DiagnosticInfoIROptimization( +          DK_OptimizationRemarkMissed, DS_Remark, PassName, RemarkName, +          *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {} + +OptimizationRemarkMissed::OptimizationRemarkMissed(const char *PassName, +                                                   StringRef RemarkName, +                                                   const Instruction *Inst) +    : DiagnosticInfoIROptimization(DK_OptimizationRemarkMissed, DS_Remark, +                                   PassName, RemarkName, +                                   *Inst->getParent()->getParent(), +                                   Inst->getDebugLoc(), Inst->getParent()) {} + +bool OptimizationRemarkMissed::isEnabled() const { +  const Function &Fn = getFunction(); +  LLVMContext &Ctx = Fn.getContext(); +  return Ctx.getDiagHandlerPtr()->isMissedOptRemarkEnabled(getPassName()); +} + +OptimizationRemarkAnalysis::OptimizationRemarkAnalysis( +    const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc, +    const Value *CodeRegion) +    : DiagnosticInfoIROptimization( +          DK_OptimizationRemarkAnalysis, DS_Remark, PassName, RemarkName, +          *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {} + +OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(const char *PassName, +                                                       StringRef RemarkName, +                                                       const Instruction *Inst) +    : DiagnosticInfoIROptimization(DK_OptimizationRemarkAnalysis, DS_Remark, +                                   PassName, RemarkName, +                                   *Inst->getParent()->getParent(), +                                   Inst->getDebugLoc(), Inst->getParent()) {} + +OptimizationRemarkAnalysis::OptimizationRemarkAnalysis( +    enum DiagnosticKind Kind, const char *PassName, StringRef RemarkName, +    const DiagnosticLocation &Loc, const Value *CodeRegion) +    : DiagnosticInfoIROptimization(Kind, DS_Remark, PassName, RemarkName, +                                   *cast<BasicBlock>(CodeRegion)->getParent(), +                                   Loc, CodeRegion) {} + +bool OptimizationRemarkAnalysis::isEnabled() const { +  const Function &Fn = getFunction(); +  LLVMContext &Ctx = Fn.getContext(); +  return Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(getPassName()) || +         shouldAlwaysPrint(); +} + +void DiagnosticInfoMIRParser::print(DiagnosticPrinter &DP) const { +  DP << Diagnostic; +} + +DiagnosticInfoOptimizationFailure::DiagnosticInfoOptimizationFailure( +    const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc, +    const Value *CodeRegion) +    : DiagnosticInfoIROptimization( +          DK_OptimizationFailure, DS_Warning, PassName, RemarkName, +          *cast<BasicBlock>(CodeRegion)->getParent(), Loc, CodeRegion) {} + +bool DiagnosticInfoOptimizationFailure::isEnabled() const { +  // Only print warnings. +  return getSeverity() == DS_Warning; +} + +void DiagnosticInfoUnsupported::print(DiagnosticPrinter &DP) const { +  std::string Str; +  raw_string_ostream OS(Str); + +  OS << getLocationStr() << ": in function " << getFunction().getName() << ' ' +     << *getFunction().getFunctionType() << ": " << Msg << '\n'; +  OS.flush(); +  DP << Str; +} + +void DiagnosticInfoISelFallback::print(DiagnosticPrinter &DP) const { +  DP << "Instruction selection used fallback path for " << getFunction(); +} + +void DiagnosticInfoOptimizationBase::insert(StringRef S) { +  Args.emplace_back(S); +} + +void DiagnosticInfoOptimizationBase::insert(Argument A) { +  Args.push_back(std::move(A)); +} + +void DiagnosticInfoOptimizationBase::insert(setIsVerbose V) { +  IsVerbose = true; +} + +void DiagnosticInfoOptimizationBase::insert(setExtraArgs EA) { +  FirstExtraArgIndex = Args.size(); +} + +std::string DiagnosticInfoOptimizationBase::getMsg() const { +  std::string Str; +  raw_string_ostream OS(Str); +  for (const DiagnosticInfoOptimizationBase::Argument &Arg : +       make_range(Args.begin(), FirstExtraArgIndex == -1 +                                    ? Args.end() +                                    : Args.begin() + FirstExtraArgIndex)) +    OS << Arg.Val; +  return OS.str(); +} + +DiagnosticInfoMisExpect::DiagnosticInfoMisExpect(const Instruction *Inst, +                                                 Twine &Msg) +    : DiagnosticInfoWithLocationBase(DK_MisExpect, DS_Warning, +                                     *Inst->getParent()->getParent(), +                                     Inst->getDebugLoc()), +      Msg(Msg) {} + +void DiagnosticInfoMisExpect::print(DiagnosticPrinter &DP) const { +  DP << getLocationStr() << ": " << getMsg(); +} + +void OptimizationRemarkAnalysisFPCommute::anchor() {} +void OptimizationRemarkAnalysisAliasing::anchor() {}  | 
