From 91061aa9b9e56c23fc7ec717050fc84b7e658bb1 Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Mon, 29 Jul 2024 14:54:42 +0100 Subject: [PATCH 01/15] Add CMake-controlled DebugLoc coverage info for use with Debugify --- clang/lib/CodeGen/BackendUtil.cpp | 16 +++ llvm/CMakeLists.txt | 2 + llvm/include/llvm/Config/config.h.cmake | 4 + llvm/include/llvm/IR/DebugLoc.h | 82 ++++++++++++++- llvm/include/llvm/Support/Signals.h | 25 +++++ llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 5 + llvm/lib/IR/DebugInfo.cpp | 4 +- llvm/lib/IR/DebugLoc.cpp | 34 ++++++ llvm/lib/Support/Signals.cpp | 111 ++++++++++++++++++++ llvm/lib/Support/Unix/Signals.inc | 13 +++ llvm/lib/Support/Windows/Signals.inc | 62 +++++++++++ llvm/lib/Transforms/IPO/IROutliner.cpp | 4 +- llvm/lib/Transforms/Scalar/LICM.cpp | 2 +- llvm/lib/Transforms/Utils/Debugify.cpp | 99 ++++++++++++++--- llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 4 +- llvm/utils/llvm-original-di-preservation.py | 10 +- 16 files changed, 449 insertions(+), 28 deletions(-) diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index e765bbf637a66..ec5cbcc669341 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -911,6 +911,22 @@ void EmitAssemblyHelper::RunOptimizationPipeline( Debugify.setOrigDIVerifyBugsReportFilePath( CodeGenOpts.DIBugsReportFilePath); Debugify.registerCallbacks(PIC, MAM); + +#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING + // If we're using debug location coverage tracking, mark all the + // instructions coming out of the frontend without a DebugLoc as being + // intentional line-zero locations, to prevent both those instructions and + // new instructions that inherit their location from being treated as + // incorrectly empty locations. + for (Function &F : *TheModule) { + if (!F.getSubprogram()) + continue; + for (BasicBlock &BB : F) + for (Instruction &I : BB) + if (!I.getDebugLoc()) + I.setDebugLoc(DebugLoc::getLineZero()); + } +#endif } // Attempt to load pass plugins and register their callbacks with PB. for (auto &PluginFN : CodeGenOpts.PassPlugins) { diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index 12618966c4adf..ee0d566de442f 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -524,6 +524,8 @@ endif() option(LLVM_ENABLE_CRASH_DUMPS "Turn on memory dumps on crashes. Currently only implemented on Windows." OFF) +option(LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING "Enhance debugify's line number tracking at the cost of performance; abi-breaking." ON) + set(WINDOWS_PREFER_FORWARD_SLASH_DEFAULT OFF) if (MINGW) # Cygwin doesn't identify itself as Windows, and thus gets path::Style::posix diff --git a/llvm/include/llvm/Config/config.h.cmake b/llvm/include/llvm/Config/config.h.cmake index ff30741c8f360..58db63acfeb07 100644 --- a/llvm/include/llvm/Config/config.h.cmake +++ b/llvm/include/llvm/Config/config.h.cmake @@ -19,6 +19,10 @@ /* Define to 1 to enable crash memory dumps, and to 0 otherwise. */ #cmakedefine01 LLVM_ENABLE_CRASH_DUMPS +/* Define to 1 to enable expensive checks for debug location coverage checking, + and to 0 otherwise. */ +#cmakedefine01 LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING + /* Define to 1 to prefer forward slashes on Windows, and to 0 prefer backslashes. */ #cmakedefine01 LLVM_WINDOWS_PREFER_FORWARD_SLASH diff --git a/llvm/include/llvm/IR/DebugLoc.h b/llvm/include/llvm/IR/DebugLoc.h index c22d3e9b10d27..1494e53c5df35 100644 --- a/llvm/include/llvm/IR/DebugLoc.h +++ b/llvm/include/llvm/IR/DebugLoc.h @@ -14,6 +14,7 @@ #ifndef LLVM_IR_DEBUGLOC_H #define LLVM_IR_DEBUGLOC_H +#include "llvm/Config/config.h" #include "llvm/IR/TrackingMDRef.h" #include "llvm/Support/DataTypes.h" @@ -22,6 +23,74 @@ namespace llvm { class LLVMContext; class raw_ostream; class DILocation; + class Function; + +#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING + struct DbgLocOriginBacktrace { + static constexpr unsigned long MaxDepth = 8; + std::array Stacktrace; + int Depth = 0; + DbgLocOriginBacktrace(bool ShouldCollectTrace); + }; + + // Used to represent different "kinds" of DebugLoc, expressing that a DebugLoc + // is either ordinary, containing a valid DILocation, or otherwise describing + // the reason why the DebugLoc does not contain a valid DILocation. + enum class DebugLocKind : uint8_t { + // DebugLoc should contain a valid DILocation. + Normal, + // DebugLoc intentionally does not have a valid DILocation; may be for a + // compiler-generated instruction, or an explicitly dropped location. + LineZero, + // DebugLoc does not have a known or currently knowable source location. + Unknown, + // Used for instructions that we don't expect to be emitted, and so can omit + // a valid DILocation. It is an error to try and emit a Temporary DebugLoc + // into the line table. + Temporary + }; + + // Extends TrackingMDNodeRef to also store a DebugLocKind and Backtrace, + // allowing Debugify to ignore intentionally-empty DebugLocs and display the + // code responsible for generating unintentionally-empty DebugLocs. + class DILocAndCoverageTracking : public TrackingMDNodeRef { + public: + DebugLocKind Kind; + // Currently we only need to track the Origin of this DILoc when using a + // normal empty DebugLoc, so only collect the stack trace in those cases. + DbgLocOriginBacktrace Origin; + DILocAndCoverageTracking(bool NeedsStacktrace = true) + : TrackingMDNodeRef(nullptr), Kind(DebugLocKind::Normal), Origin(NeedsStacktrace) { + } + // Valid or nullptr MDNode*, normal DebugLocKind + DILocAndCoverageTracking(const MDNode *Loc) + : TrackingMDNodeRef(const_cast(Loc)), + Kind(DebugLocKind::Normal), Origin(!Loc) {} + DILocAndCoverageTracking(const DILocation *Loc); + // Always nullptr MDNode*, any DebugLocKind + DILocAndCoverageTracking(DebugLocKind Kind) + : TrackingMDNodeRef(nullptr), Kind(Kind), + Origin(Kind == DebugLocKind::Normal) {} + }; + template <> struct simplify_type { + using SimpleType = MDNode *; + + static MDNode *getSimplifiedValue(DILocAndCoverageTracking &MD) { + return MD.get(); + } + }; + template <> struct simplify_type { + using SimpleType = MDNode *; + + static MDNode *getSimplifiedValue(const DILocAndCoverageTracking &MD) { + return MD.get(); + } + }; + + using DebugLocTrackingRef = DILocAndCoverageTracking; +#else + using DebugLocTrackingRef = TrackingMDNodeRef; +#endif // LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING /// A debug info location. /// @@ -31,7 +100,8 @@ namespace llvm { /// To avoid extra includes, \a DebugLoc doubles the \a DILocation API with a /// one based on relatively opaque \a MDNode pointers. class DebugLoc { - TrackingMDNodeRef Loc; + + DebugLocTrackingRef Loc; public: DebugLoc() = default; @@ -47,6 +117,16 @@ namespace llvm { /// IR. explicit DebugLoc(const MDNode *N); +#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING + DebugLoc(DebugLocKind Kind) : Loc(Kind) {} + DebugLocKind getKind() const { return Loc.Kind; } + DbgLocOriginBacktrace getOrigin() const { return Loc.Origin; } +#endif + + static DebugLoc getTemporary(); + static DebugLoc getUnknown(); + static DebugLoc getLineZero(); + /// Get the underlying \a DILocation. /// /// \pre !*this or \c isa(getAsMDNode()). diff --git a/llvm/include/llvm/Support/Signals.h b/llvm/include/llvm/Support/Signals.h index 70749ce30184a..8281274f2ef06 100644 --- a/llvm/include/llvm/Support/Signals.h +++ b/llvm/include/llvm/Support/Signals.h @@ -14,6 +14,8 @@ #ifndef LLVM_SUPPORT_SIGNALS_H #define LLVM_SUPPORT_SIGNALS_H +#include "llvm/Config/config.h" +#include #include #include @@ -21,6 +23,20 @@ namespace llvm { class StringRef; class raw_ostream; +#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING +template struct DenseMapInfo; +template class DenseSet; +namespace detail { +template struct DenseMapPair; +} +template +class DenseMap; +using AddressSet = DenseSet>; +using SymbolizedAddressMap = + DenseMap, + detail::DenseMapPair>; +#endif + namespace sys { /// This function runs all the registered interrupt handlers, including the @@ -55,6 +71,15 @@ namespace sys { /// specified, the entire frame is printed. void PrintStackTrace(raw_ostream &OS, int Depth = 0); +#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING + template int getStackTrace(std::array &StackTrace); + + /// Takes a set of \p Addresses, symbolizes them and stores the result in the + /// provided \p SymbolizedAddresses map. + void symbolizeAddresses(AddressSet &Addresses, + SymbolizedAddressMap &SymbolizedAddresses); +#endif + // Run all registered signal handlers. void RunSignalHandlers(); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index f88653146cc6f..374c35fd53957 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -31,6 +31,7 @@ #include "llvm/CodeGen/TargetLowering.h" #include "llvm/CodeGen/TargetRegisterInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" +#include "llvm/Config/config.h" #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" #include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/IR/Constants.h" @@ -2080,6 +2081,10 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) { } if (!DL) { +#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING + assert(DL.getKind() != DebugLocKind::Temporary && + "Temporary DebugLocs should never be considered for emission!"); +#endif // We have an unspecified location, which might want to be line 0. // If we have already emitted a line-0 record, don't repeat it. if (LastAsmLine == 0) diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp index 7fa1f9696d43b..86ac46540c5ef 100644 --- a/llvm/lib/IR/DebugInfo.cpp +++ b/llvm/lib/IR/DebugInfo.cpp @@ -979,7 +979,7 @@ void Instruction::dropLocation() { } if (!MayLowerToCall) { - setDebugLoc(DebugLoc()); + setDebugLoc(DebugLoc::getLineZero()); return; } @@ -998,7 +998,7 @@ void Instruction::dropLocation() { // // One alternative is to set a line 0 location with the existing scope and // inlinedAt info. The location might be sensitive to when inlining occurs. - setDebugLoc(DebugLoc()); + setDebugLoc(DebugLoc::getLineZero()); } //===----------------------------------------------------------------------===// diff --git a/llvm/lib/IR/DebugLoc.cpp b/llvm/lib/IR/DebugLoc.cpp index bdea52180f74a..3a6cb00c4dda6 100644 --- a/llvm/lib/IR/DebugLoc.cpp +++ b/llvm/lib/IR/DebugLoc.cpp @@ -9,8 +9,42 @@ #include "llvm/IR/DebugLoc.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/DebugInfo.h" +#include "llvm/IR/Function.h" + +#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING +#include "llvm/Support/Signals.h" + using namespace llvm; +DILocAndCoverageTracking::DILocAndCoverageTracking(const DILocation *L) + : TrackingMDNodeRef(const_cast(L)), + Kind(DebugLocKind::Normal), Origin(!L) {} + +DbgLocOriginBacktrace::DbgLocOriginBacktrace(bool ShouldCollectTrace) + : Depth(0) { + if (ShouldCollectTrace) + Depth = sys::getStackTrace(Stacktrace); +} + +DebugLoc DebugLoc::getTemporary() { + return DebugLoc(DebugLocKind::Temporary); +} +DebugLoc DebugLoc::getUnknown() { + return DebugLoc(DebugLocKind::Unknown); +} +DebugLoc DebugLoc::getLineZero() { + return DebugLoc(DebugLocKind::LineZero); +} + +#else + +using namespace llvm; + +DebugLoc DebugLoc::getTemporary() { return DebugLoc(); } +DebugLoc DebugLoc::getUnknown() { return DebugLoc(); } +DebugLoc DebugLoc::getLineZero() { return DebugLoc(); } +#endif // LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING + //===----------------------------------------------------------------------===// // DebugLoc Implementation //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Support/Signals.cpp b/llvm/lib/Support/Signals.cpp index 9f9030e79d104..598b3c916c6d4 100644 --- a/llvm/lib/Support/Signals.cpp +++ b/llvm/lib/Support/Signals.cpp @@ -253,6 +253,117 @@ static bool printSymbolizedStackTrace(StringRef Argv0, void **StackTrace, return true; } +#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING +void sys::symbolizeAddresses(AddressSet &Addresses, + SymbolizedAddressMap &SymbolizedAddresses) { + if (DisableSymbolicationFlag || getenv(DisableSymbolizationEnv)) + return; + + // Convert Set of Addresses to ordered list. + SmallVector AddressList(Addresses.begin(), Addresses.end()); + if (AddressList.empty()) + return; + int NumAddresses = AddressList.size(); + llvm::sort(AddressList); + + // Use llvm-symbolizer tool to symbolize the stack traces. First look for it + // alongside our binary, then in $PATH. + ErrorOr LLVMSymbolizerPathOrErr = std::error_code(); + if (const char *Path = getenv(LLVMSymbolizerPathEnv)) { + LLVMSymbolizerPathOrErr = sys::findProgramByName(Path); + } + if (!LLVMSymbolizerPathOrErr) + LLVMSymbolizerPathOrErr = sys::findProgramByName("llvm-symbolizer"); + if (!LLVMSymbolizerPathOrErr) + return; + const std::string &LLVMSymbolizerPath = *LLVMSymbolizerPathOrErr; + + // Try to guess the main executable name, since we don't have argv0 available + // here. + std::string MainExecutableName = sys::fs::getMainExecutable(nullptr, nullptr); + + BumpPtrAllocator Allocator; + StringSaver StrPool(Allocator); + std::vector Modules(NumAddresses, nullptr); + std::vector Offsets(NumAddresses, 0); + if (!findModulesAndOffsets(AddressList.data(), NumAddresses, Modules.data(), + Offsets.data(), MainExecutableName.c_str(), + StrPool)) + return; + int InputFD; + SmallString<32> InputFile, OutputFile; + sys::fs::createTemporaryFile("symbolizer-input", "", InputFD, InputFile); + sys::fs::createTemporaryFile("symbolizer-output", "", OutputFile); + FileRemover InputRemover(InputFile.c_str()); + FileRemover OutputRemover(OutputFile.c_str()); + + { + raw_fd_ostream Input(InputFD, true); + for (int i = 0; i < NumAddresses; i++) { + if (Modules[i]) + Input << Modules[i] << " " << (void *)Offsets[i] << "\n"; + } + } + + std::optional Redirects[] = {InputFile.str(), OutputFile.str(), + StringRef("")}; + StringRef Args[] = {"llvm-symbolizer", "--functions=linkage", "--inlining", +#ifdef _WIN32 + // Pass --relative-address on Windows so that we don't + // have to add ImageBase from PE file. + // FIXME: Make this the default for llvm-symbolizer. + "--relative-address", +#endif + "--demangle"}; + int RunResult = + sys::ExecuteAndWait(LLVMSymbolizerPath, Args, std::nullopt, Redirects); + if (RunResult != 0) + return; + + // This report format is based on the sanitizer stack trace printer. See + // sanitizer_stacktrace_printer.cc in compiler-rt. + auto OutputBuf = MemoryBuffer::getFile(OutputFile.c_str()); + if (!OutputBuf) + return; + StringRef Output = OutputBuf.get()->getBuffer(); + SmallVector Lines; + Output.split(Lines, "\n"); + auto CurLine = Lines.begin(); + for (int i = 0; i < NumAddresses; i++) { + assert(!SymbolizedAddresses.contains(AddressList[i])); + std::string &SymbolizedAddr = SymbolizedAddresses[AddressList[i]]; + raw_string_ostream OS(SymbolizedAddr); + auto PrintLineHeader = [&]() { OS << format_ptr(AddressList[i]) << ' '; }; + if (!Modules[i]) { + PrintLineHeader(); + OS << '\n'; + continue; + } + // Read pairs of lines (function name and file/line info) until we + // encounter empty line. + for (;;) { + if (CurLine == Lines.end()) + return; + StringRef FunctionName = *CurLine++; + if (FunctionName.empty()) + break; + PrintLineHeader(); + if (!FunctionName.starts_with("??")) + OS << FunctionName << ' '; + if (CurLine == Lines.end()) + return; + StringRef FileLineInfo = *CurLine++; + if (!FileLineInfo.starts_with("??")) + OS << FileLineInfo; + else + OS << "(" << Modules[i] << '+' << format_hex(Offsets[i], 0) << ")"; + OS << "\n"; + } + } + return; +} +#endif + static bool printMarkupContext(raw_ostream &OS, const char *MainExecutableName); LLVM_ATTRIBUTE_USED diff --git a/llvm/lib/Support/Unix/Signals.inc b/llvm/lib/Support/Unix/Signals.inc index 298fde1a387cc..fc8e5d2cd4c15 100644 --- a/llvm/lib/Support/Unix/Signals.inc +++ b/llvm/lib/Support/Unix/Signals.inc @@ -499,6 +499,19 @@ static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) { return 0; } + +#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING +namespace llvm { +namespace sys { +template +int getStackTrace(std::array &StackTrace) { + return backtrace(StackTrace.data(), MaxDepth); +} +template int getStackTrace<8ul>(std::array &); +} +} +#endif + /// If this is an ELF platform, we can find all loaded modules and their virtual /// addresses with dl_iterate_phdr. static bool findModulesAndOffsets(void **StackTrace, int Depth, diff --git a/llvm/lib/Support/Windows/Signals.inc b/llvm/lib/Support/Windows/Signals.inc index 29ebf7c696e04..dbfa141059531 100644 --- a/llvm/lib/Support/Windows/Signals.inc +++ b/llvm/lib/Support/Windows/Signals.inc @@ -9,6 +9,7 @@ // This file provides the Win32 specific implementation of the Signals class. // //===----------------------------------------------------------------------===// +#include "llvm/Config/config.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/ExitCodes.h" #include "llvm/Support/FileSystem.h" @@ -538,6 +539,67 @@ void sys::PrintStackTraceOnErrorSignal(StringRef Argv0, extern "C" VOID WINAPI RtlCaptureContext(PCONTEXT ContextRecord); #endif +#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING +namespace llvm { +namespace sys { +template +int getStackTrace(std::array &StackTrace) { + STACKFRAME64 StackFrame{}; + CONTEXT Context{}; + if (!C) { + ::RtlCaptureContext(&Context); + C = &Context; + } +#if defined(_M_X64) + StackFrame.AddrPC.Offset = Context.Rip; + StackFrame.AddrStack.Offset = Context.Rsp; + StackFrame.AddrFrame.Offset = Context.Rbp; +#elif defined(_M_IX86) + StackFrame.AddrPC.Offset = Context.Eip; + StackFrame.AddrStack.Offset = Context.Esp; + StackFrame.AddrFrame.Offset = Context.Ebp; +#elif defined(_M_ARM64) + StackFrame.AddrPC.Offset = Context.Pc; + StackFrame.AddrStack.Offset = Context.Sp; + StackFrame.AddrFrame.Offset = Context.Fp; +#elif defined(_M_ARM) + StackFrame.AddrPC.Offset = Context.Pc; + StackFrame.AddrStack.Offset = Context.Sp; + StackFrame.AddrFrame.Offset = Context.R11; +#endif + StackFrame.AddrPC.Mode = AddrModeFlat; + StackFrame.AddrStack.Mode = AddrModeFlat; + StackFrame.AddrFrame.Mode = AddrModeFlat; + + HANDLE hProcess = GetCurrentProcess(); + HANDLE hThread = GetCurrentThread(); + + // It's possible that DbgHelp.dll hasn't been loaded yet (e.g. if this + // function is called before the main program called `llvm::InitLLVM`). + // In this case just return, not stacktrace will be printed. + assert(isDebugHelpInitialized() && "getStackTrace must not be called before DbgHelp.dll has been loaded."); + + // Initialize the symbol handler. + fSymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES); + fSymInitialize(hProcess, NULL, TRUE); + Context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; + + size_t WalkDepth = 0; + while (WalkDepth < MaxDepth && + fStackWalk64(NativeMachineType, hProcess, hThread, &StackFrame, + &Context, 0, fSymFunctionTableAccess64, + fSymGetModuleBase64, 0)) { + if (StackFrame.AddrFrame.Offset == 0) + break; + StackTrace[WalkDepth++] = (void *)(uintptr_t)StackFrame.AddrPC.Offset; + } + return WalkDepth; +} +template int llvm::sys::getStackTrace<8ul>(std::array &); +} +} +#endif + static void LocalPrintStackTrace(raw_ostream &OS, PCONTEXT C) { STACKFRAME64 StackFrame{}; CONTEXT Context{}; diff --git a/llvm/lib/Transforms/IPO/IROutliner.cpp b/llvm/lib/Transforms/IPO/IROutliner.cpp index 96c803c0186ef..94e05871a184e 100644 --- a/llvm/lib/Transforms/IPO/IROutliner.cpp +++ b/llvm/lib/Transforms/IPO/IROutliner.cpp @@ -731,7 +731,7 @@ static void moveFunctionData(Function &Old, Function &New, // other outlined instructions. if (!isa(&Val)) { // Remove the debug information for outlined functions. - Val.setDebugLoc(DebugLoc()); + Val.setDebugLoc(DebugLoc::getLineZero()); // Loop info metadata may contain line locations. Update them to have no // value in the new subprogram since the outlined code could be from @@ -1868,7 +1868,7 @@ replaceArgumentUses(OutlinableRegion &Region, Value *ValueOperand = SI->getValueOperand(); StoreInst *NewI = cast(I->clone()); - NewI->setDebugLoc(DebugLoc()); + NewI->setDebugLoc(DebugLoc::getLineZero()); BasicBlock *OutputBB = VBBIt->second; NewI->insertInto(OutputBB, OutputBB->end()); LLVM_DEBUG(dbgs() << "Move store for instruction " << *I << " to " diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp index fe264503dee9e..1d236c018bab6 100644 --- a/llvm/lib/Transforms/Scalar/LICM.cpp +++ b/llvm/lib/Transforms/Scalar/LICM.cpp @@ -2243,7 +2243,7 @@ bool llvm::promoteLoopAccessesToScalars( if (SawUnorderedAtomic) PreheaderLoad->setOrdering(AtomicOrdering::Unordered); PreheaderLoad->setAlignment(Alignment); - PreheaderLoad->setDebugLoc(DebugLoc()); + PreheaderLoad->dropLocation(); if (AATags) PreheaderLoad->setAAMetadata(AATags); diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp b/llvm/lib/Transforms/Utils/Debugify.cpp index fcc82eadac36c..7c50f2ab0021b 100644 --- a/llvm/lib/Transforms/Utils/Debugify.cpp +++ b/llvm/lib/Transforms/Utils/Debugify.cpp @@ -15,7 +15,10 @@ #include "llvm/Transforms/Utils/Debugify.h" #include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Config/config.h" #include "llvm/IR/DIBuilder.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/InstIterator.h" @@ -28,6 +31,11 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/JSON.h" #include +#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING +// We need the Signals header to operate on stacktraces if we're using enhanced +// coverage tracking. +#include "llvm/Support/Signals.h" +#endif #define DEBUG_TYPE "debugify" @@ -57,6 +65,43 @@ cl::opt DebugifyLevel( raw_ostream &dbg() { return Quiet ? nulls() : errs(); } +#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING +// These maps refer to addresses in this instance of LLVM, so we can reuse them +// everywhere - therefore, we store them at file scope. +static DenseMap SymbolizedAddrs; +static DenseSet UnsymbolizedAddrs; + +std::string symbolizeStacktrace(const Instruction *I) { + // We flush the set of unsymbolized addresses at the latest possible moment, + // i.e. now. + if (!UnsymbolizedAddrs.empty()) { + sys::symbolizeAddresses(UnsymbolizedAddrs, SymbolizedAddrs); + UnsymbolizedAddrs.clear(); + } + DbgLocOriginBacktrace ST = I->getDebugLoc().getOrigin(); + std::string Result; + raw_string_ostream OS(Result); + for (int Frame = 0; Frame < ST.Depth; ++Frame) { + assert(SymbolizedAddrs.contains(ST.Stacktrace[Frame]) && + "Expected each address to have been symbolized."); + OS << right_justify(formatv("#{0}", Frame).str(), std::log10(ST.Depth) + 2) + << ' ' << SymbolizedAddrs[ST.Stacktrace[Frame]]; + } + return Result; +} +void collectStackAddresses(Instruction &I) { + DbgLocOriginBacktrace ST = I.getDebugLoc().getOrigin(); + for (int Frame = 0; Frame < ST.Depth; ++Frame) { + void *Addr = ST.Stacktrace[Frame]; + if (!SymbolizedAddrs.contains(Addr)) + UnsymbolizedAddrs.insert(Addr); + } +} +#else +std::string symbolizeStacktrace(const Instruction *I) { return ""; } +void collectStackAddresses(Instruction &I) {} +#endif + uint64_t getAllocSizeInBits(Module &M, Type *Ty) { return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0; } @@ -292,6 +337,16 @@ bool llvm::stripDebugifyMetadata(Module &M) { return Changed; } +bool hasLoc(const Instruction &I) { + const DILocation *Loc = I.getDebugLoc().get(); +#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING + DebugLocKind Kind = I.getDebugLoc().getKind(); + return Loc || Kind != DebugLocKind::Normal; +#else + return Loc; +#endif +} + bool llvm::collectDebugInfoMetadata(Module &M, iterator_range Functions, DebugInfoPerPass &DebugInfoBeforePass, @@ -364,9 +419,9 @@ bool llvm::collectDebugInfoMetadata(Module &M, LLVM_DEBUG(dbgs() << " Collecting info for inst: " << I << '\n'); DebugInfoBeforePass.InstToDelete.insert({&I, &I}); - const DILocation *Loc = I.getDebugLoc().get(); - bool HasLoc = Loc != nullptr; - DebugInfoBeforePass.DILocations.insert({&I, HasLoc}); + // Track the addresses to symbolize, if the feature is enabled. + collectStackAddresses(I); + DebugInfoBeforePass.DILocations.insert({&I, hasLoc(I)}); } } } @@ -444,11 +499,13 @@ static bool checkInstructions(const DebugInstMap &DILocsBefore, auto InstrIt = DILocsBefore.find(Instr); if (InstrIt == DILocsBefore.end()) { if (ShouldWriteIntoJSON) - Bugs.push_back(llvm::json::Object({{"metadata", "DILocation"}, - {"fn-name", FnName.str()}, - {"bb-name", BBName.str()}, - {"instr", InstName}, - {"action", "not-generate"}})); + Bugs.push_back( + llvm::json::Object({{"metadata", "DILocation"}, + {"fn-name", FnName.str()}, + {"bb-name", BBName.str()}, + {"instr", InstName}, + {"action", "not-generate"}, + {"origin", symbolizeStacktrace(Instr)}})); else dbg() << "WARNING: " << NameOfWrappedPass << " did not generate DILocation for " << *Instr @@ -461,11 +518,13 @@ static bool checkInstructions(const DebugInstMap &DILocsBefore, // If the instr had the !dbg attached before the pass, consider it as // a debug info issue. if (ShouldWriteIntoJSON) - Bugs.push_back(llvm::json::Object({{"metadata", "DILocation"}, - {"fn-name", FnName.str()}, - {"bb-name", BBName.str()}, - {"instr", InstName}, - {"action", "drop"}})); + Bugs.push_back( + llvm::json::Object({{"metadata", "DILocation"}, + {"fn-name", FnName.str()}, + {"bb-name", BBName.str()}, + {"instr", InstName}, + {"action", "drop"}, + {"origin", symbolizeStacktrace(Instr)}})); else dbg() << "WARNING: " << NameOfWrappedPass << " dropped DILocation of " << *Instr << " (BB: " << BBName << ", Fn: " << FnName @@ -609,10 +668,9 @@ bool llvm::checkDebugInfoMetadata(Module &M, LLVM_DEBUG(dbgs() << " Collecting info for inst: " << I << '\n'); - const DILocation *Loc = I.getDebugLoc().get(); - bool HasLoc = Loc != nullptr; - - DebugInfoAfterPass.DILocations.insert({&I, HasLoc}); + // Track the addresses to symbolize, if the feature is enabled. + collectStackAddresses(I); + DebugInfoAfterPass.DILocations.insert({&I, hasLoc(I)}); } } } @@ -662,6 +720,13 @@ bool llvm::checkDebugInfoMetadata(Module &M, // again in the collectDebugInfoMetadata(), since as an input we can use // the debugging information from the previous pass. DebugInfoBeforePass = DebugInfoAfterPass; + // We should make this conditional on debugify-each, but this has to be done + // if we're reusing DebugInfoAfterPass. + for (const auto &L : DebugInfoBeforePass.DILocations) { + auto Instr = L.first; + DebugInfoBeforePass.InstToDelete.insert( + {const_cast(Instr), const_cast(Instr)}); + } LLVM_DEBUG(dbgs() << "\n\n"); return Result; diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index f23e28888931d..910b9dbeed444 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -1111,7 +1111,7 @@ static void CloneInstructionsIntoPredecessorBlockAndUpdateSSAUses( // branch, drop it. When we fold the bonus instructions we want to make // sure we reset their debug locations in order to avoid stepping on // dead code caused by folding dead branches. - NewBonusInst->setDebugLoc(DebugLoc()); + NewBonusInst->dropLocation(); } RemapInstruction(NewBonusInst, VMap, @@ -3183,7 +3183,7 @@ bool SimplifyCFGOpt::SpeculativelyExecuteBB(BranchInst *BI, if (!SpeculatedStoreValue || &I != SpeculatedStore) { // Don't update the DILocation of dbg.assign intrinsics. if (!isa(&I)) - I.setDebugLoc(DebugLoc()); + I.dropLocation(); } I.dropUBImplyingAttrsAndMetadata(); diff --git a/llvm/utils/llvm-original-di-preservation.py b/llvm/utils/llvm-original-di-preservation.py index dc1fa518ca8e6..d4b7a7b9bcf60 100755 --- a/llvm/utils/llvm-original-di-preservation.py +++ b/llvm/utils/llvm-original-di-preservation.py @@ -13,14 +13,15 @@ class DILocBug: - def __init__(self, action, bb_name, fn_name, instr): + def __init__(self, origin, action, bb_name, fn_name, instr): + self.origin = origin self.action = action self.bb_name = bb_name self.fn_name = fn_name self.instr = instr def __str__(self): - return self.action + self.bb_name + self.fn_name + self.instr + return self.action + self.bb_name + self.fn_name + self.instr + self.origin class DISPBug: @@ -86,6 +87,7 @@ def generate_html_report( "Function Name", "Basic Block Name", "Action", + "Origin", ] for column in header_di_loc: @@ -112,6 +114,7 @@ def generate_html_report( row.append(x.fn_name) row.append(x.bb_name) row.append(x.action) + row.append(f"
{x.origin}
") row.append(" \n") # Dump the bugs info into the table. for column in row: @@ -487,6 +490,7 @@ def Main(): if bugs_metadata == "DILocation": try: + origin = bug["origin"] action = bug["action"] bb_name = bug["bb-name"] fn_name = bug["fn-name"] @@ -494,7 +498,7 @@ def Main(): except: skipped_bugs += 1 continue - di_loc_bug = DILocBug(action, bb_name, fn_name, instr) + di_loc_bug = DILocBug(origin, action, bb_name, fn_name, instr) if not str(di_loc_bug) in di_loc_set: di_loc_set.add(str(di_loc_bug)) if opts.compress: From 3068f5b4be0156da6ebbbf7fd2efd161a7e5687a Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Tue, 30 Jul 2024 17:23:40 +0100 Subject: [PATCH 02/15] Fix builds on windows --- llvm/lib/Support/Signals.cpp | 8 ++++---- llvm/lib/Support/Windows/Signals.inc | 5 +---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Support/Signals.cpp b/llvm/lib/Support/Signals.cpp index 598b3c916c6d4..2fed1ae99eb0d 100644 --- a/llvm/lib/Support/Signals.cpp +++ b/llvm/lib/Support/Signals.cpp @@ -256,8 +256,8 @@ static bool printSymbolizedStackTrace(StringRef Argv0, void **StackTrace, #ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING void sys::symbolizeAddresses(AddressSet &Addresses, SymbolizedAddressMap &SymbolizedAddresses) { - if (DisableSymbolicationFlag || getenv(DisableSymbolizationEnv)) - return; + assert(!DisableSymbolicationFlag && !getenv(DisableSymbolizationEnv) && + "Debugify origin stacktraces require symbolization to be enabled."); // Convert Set of Addresses to ordered list. SmallVector AddressList(Addresses.begin(), Addresses.end()); @@ -274,8 +274,8 @@ void sys::symbolizeAddresses(AddressSet &Addresses, } if (!LLVMSymbolizerPathOrErr) LLVMSymbolizerPathOrErr = sys::findProgramByName("llvm-symbolizer"); - if (!LLVMSymbolizerPathOrErr) - return; + assert(!!LLVMSymbolizerPathOrErr + && "Debugify origin stacktraces require llvm-symbolizer."); const std::string &LLVMSymbolizerPath = *LLVMSymbolizerPathOrErr; // Try to guess the main executable name, since we don't have argv0 available diff --git a/llvm/lib/Support/Windows/Signals.inc b/llvm/lib/Support/Windows/Signals.inc index dbfa141059531..85e778bc74536 100644 --- a/llvm/lib/Support/Windows/Signals.inc +++ b/llvm/lib/Support/Windows/Signals.inc @@ -546,10 +546,7 @@ template int getStackTrace(std::array &StackTrace) { STACKFRAME64 StackFrame{}; CONTEXT Context{}; - if (!C) { - ::RtlCaptureContext(&Context); - C = &Context; - } + ::RtlCaptureContext(&Context); #if defined(_M_X64) StackFrame.AddrPC.Offset = Context.Rip; StackFrame.AddrStack.Offset = Context.Rsp; From 604afebdbe23cbb2ebae9af170289bd88de11a3c Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Wed, 14 Aug 2024 15:13:11 +0100 Subject: [PATCH 03/15] Add File Args table to OriginalDIDebugify report --- clang/include/clang/Basic/CodeGenOptions.h | 1 + clang/lib/CodeGen/BackendUtil.cpp | 16 ++++++++- clang/lib/Frontend/CompilerInvocation.cpp | 10 ++++++ llvm/utils/llvm-original-di-preservation.py | 36 ++++++++++++++++++++- 4 files changed, 61 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index f2a707a8ba8d7..29654eb5774ac 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -221,6 +221,7 @@ class CodeGenOptions : public CodeGenOptionsBase { /// The file to use for dumping bug report by `Debugify` for original /// debug info. std::string DIBugsReportFilePath; + std::string DIBugsReportArgString; /// The floating-point denormal mode to use. llvm::DenormalMode FPDenormalMode = llvm::DenormalMode::getIEEE(); diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index ec5cbcc669341..abdf43a97d739 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -904,12 +904,26 @@ void EmitAssemblyHelper::RunOptimizationPipeline( DebugifyEachInstrumentation Debugify; DebugInfoPerPass DebugInfoBeforePass; if (CodeGenOpts.EnableDIPreservationVerify) { + Debugify.setDebugifyMode(DebugifyMode::OriginalDebugInfo); Debugify.setDebugInfoBeforePass(DebugInfoBeforePass); - if (!CodeGenOpts.DIBugsReportFilePath.empty()) + if (!CodeGenOpts.DIBugsReportFilePath.empty()) { Debugify.setOrigDIVerifyBugsReportFilePath( CodeGenOpts.DIBugsReportFilePath); + std::error_code EC; + raw_fd_ostream OS_FILE{CodeGenOpts.DIBugsReportFilePath, EC, + sys::fs::OF_Append | sys::fs::OF_TextWithCRLF}; + if (EC) { + errs() << "Could not open file: " << EC.message() << ", " + << CodeGenOpts.DIBugsReportFilePath << '\n'; + } else { + if (auto L = OS_FILE.lock()) { + OS_FILE << CodeGenOpts.DIBugsReportArgString; + } + OS_FILE.close(); + } + } Debugify.registerCallbacks(PIC, MAM); #ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index f6b6c44a4cab6..16c9a71a0020f 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1876,6 +1876,16 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, << Opts.DIBugsReportFilePath; Opts.DIBugsReportFilePath = ""; } + if (Opts.EnableDIPreservationVerify && Opts.DIBugsReportFilePath.size()) { + std::string ArgString; + llvm::raw_string_ostream OS(ArgString); + OS << "{\"file\":\"" << OutputFile << "\", \"args\":\""; + for (Arg *A : Args) { + OS << A->getAsString(Args) << " "; + } + OS << "\"}\n"; + Opts.DIBugsReportArgString = ArgString; + } Opts.NewStructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa) && Args.hasArg(OPT_new_struct_path_tbaa); diff --git a/llvm/utils/llvm-original-di-preservation.py b/llvm/utils/llvm-original-di-preservation.py index d4b7a7b9bcf60..5c6cb23264e7a 100755 --- a/llvm/utils/llvm-original-di-preservation.py +++ b/llvm/utils/llvm-original-di-preservation.py @@ -51,6 +51,7 @@ def generate_html_report( di_location_bugs_summary, di_sp_bugs_summary, di_var_bugs_summary, + di_file_args, html_file, ): fileout = open(html_file, "w") @@ -341,6 +342,29 @@ def generate_html_report( """ table_di_var_sum += "\n" + # Create the table for the compiler args for each file. + table_title_file_args = "Compiler arguments per file" + table_file_args = """ + + + """.format( + table_title_file_args + ) + header_file_args = ["File", "Args"] + + for column in header_file_args: + table_file_args += " \n".format(column.strip()) + table_file_args += " \n" + row = [] + for file, args in di_file_args.items(): + row.append(" \n") + row.append(" \n".format(file.strip())) + row.append(" \n".format(args.strip())) + row.append(" \n") + for column in row: + table_file_args += column + table_file_args += " \n" + # Finish the html page. html_footer = """""" @@ -361,6 +385,8 @@ def generate_html_report( fileout.writelines(table_di_var) fileout.writelines(new_line) fileout.writelines(table_di_var_sum) + fileout.writelines(new_line) + fileout.writelines(table_file_args) fileout.writelines(html_footer) fileout.close() @@ -430,6 +456,8 @@ def Main(): print("error: The output file must be '.html'.") sys.exit(1) + di_file_args = OrderedDict() + # Use the defaultdict in order to make multidim dicts. di_location_bugs = defaultdict(lambda: defaultdict(dict)) di_subprogram_bugs = defaultdict(lambda: defaultdict(dict)) @@ -470,7 +498,12 @@ def Main(): bugs_pass = bugs_per_pass["pass"] bugs = bugs_per_pass["bugs"][0] except: - skipped_lines += 1 + try: + file = bugs_per_pass["file"] + args = bugs_per_pass["args"] + di_file_args[file] = args + except: + skipped_lines += 1 continue di_loc_bugs = [] @@ -577,6 +610,7 @@ def Main(): di_location_bugs_summary, di_sp_bugs_summary, di_var_bugs_summary, + di_file_args, opts.html_file, ) From 9475fa6e6d1020b4db803bfe5e96bbdefc746830 Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Wed, 14 Aug 2024 15:14:51 +0100 Subject: [PATCH 04/15] Add InstructionNames to OriginalDIDebugify report --- llvm/lib/Transforms/Utils/Debugify.cpp | 3 +++ llvm/utils/llvm-original-di-preservation.py | 8 ++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp b/llvm/lib/Transforms/Utils/Debugify.cpp index 7c50f2ab0021b..e20ec86dd3c08 100644 --- a/llvm/lib/Transforms/Utils/Debugify.cpp +++ b/llvm/lib/Transforms/Utils/Debugify.cpp @@ -495,6 +495,7 @@ static bool checkInstructions(const DebugInstMap &DILocsBefore, auto BB = Instr->getParent(); auto BBName = BB->hasName() ? BB->getName() : "no-name"; auto InstName = Instruction::getOpcodeName(Instr->getOpcode()); + auto InstLabel = Instr->getNameOrAsOperand(); auto InstrIt = DILocsBefore.find(Instr); if (InstrIt == DILocsBefore.end()) { @@ -503,6 +504,7 @@ static bool checkInstructions(const DebugInstMap &DILocsBefore, llvm::json::Object({{"metadata", "DILocation"}, {"fn-name", FnName.str()}, {"bb-name", BBName.str()}, + {"instr-name", InstLabel}, {"instr", InstName}, {"action", "not-generate"}, {"origin", symbolizeStacktrace(Instr)}})); @@ -522,6 +524,7 @@ static bool checkInstructions(const DebugInstMap &DILocsBefore, llvm::json::Object({{"metadata", "DILocation"}, {"fn-name", FnName.str()}, {"bb-name", BBName.str()}, + {"instr-name", InstLabel}, {"instr", InstName}, {"action", "drop"}, {"origin", symbolizeStacktrace(Instr)}})); diff --git a/llvm/utils/llvm-original-di-preservation.py b/llvm/utils/llvm-original-di-preservation.py index 5c6cb23264e7a..9d51ca23b8196 100755 --- a/llvm/utils/llvm-original-di-preservation.py +++ b/llvm/utils/llvm-original-di-preservation.py @@ -13,9 +13,10 @@ class DILocBug: - def __init__(self, origin, action, bb_name, fn_name, instr): + def __init__(self, origin, action, instr_name, bb_name, fn_name, instr): self.origin = origin self.action = action + self.instr_name = instr_name self.bb_name = bb_name self.fn_name = fn_name self.instr = instr @@ -87,6 +88,7 @@ def generate_html_report( "LLVM IR Instruction", "Function Name", "Basic Block Name", + "Instruction Name", "Action", "Origin", ] @@ -114,6 +116,7 @@ def generate_html_report( row.append(x.instr) row.append(x.fn_name) row.append(x.bb_name) + row.append(x.instr_name) row.append(x.action) row.append(f"
{x.origin}
") row.append("
\n") @@ -525,13 +528,14 @@ def Main(): try: origin = bug["origin"] action = bug["action"] + instr_name = bug["instr-name"] bb_name = bug["bb-name"] fn_name = bug["fn-name"] instr = bug["instr"] except: skipped_bugs += 1 continue - di_loc_bug = DILocBug(origin, action, bb_name, fn_name, instr) + di_loc_bug = DILocBug(origin, action, instr_name, bb_name, fn_name, instr) if not str(di_loc_bug) in di_loc_set: di_loc_set.add(str(di_loc_bug)) if opts.compress: From 9b8189ca4a84015ad89df9095469212da57e546b Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Wed, 14 Aug 2024 15:15:20 +0100 Subject: [PATCH 05/15] Make Origin Stacktrace in debugify report collapsible --- llvm/utils/llvm-original-di-preservation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/utils/llvm-original-di-preservation.py b/llvm/utils/llvm-original-di-preservation.py index 9d51ca23b8196..a3da233ae30dc 100755 --- a/llvm/utils/llvm-original-di-preservation.py +++ b/llvm/utils/llvm-original-di-preservation.py @@ -118,7 +118,7 @@ def generate_html_report( row.append(x.bb_name) row.append(x.instr_name) row.append(x.action) - row.append(f"
{x.origin}
") + row.append(f"
View Origin Stacktrace
{x.origin}
") row.append(" \n") # Dump the bugs info into the table. for column in row: From 0818d38e03e8dec3741bebb666f79346a900dd9c Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Wed, 14 Aug 2024 17:11:03 +0100 Subject: [PATCH 06/15] Track multiple backtraces in debugify origin tracking --- llvm/include/llvm/IR/DebugLoc.h | 18 +++++++++++--- llvm/include/llvm/IR/IRBuilder.h | 30 +++++++++++++++++++++-- llvm/include/llvm/IR/Instruction.h | 1 + llvm/lib/CodeGen/BranchFolding.cpp | 4 ++-- llvm/lib/CodeGen/BranchFolding.h | 8 +++---- llvm/lib/IR/DebugInfo.cpp | 3 +++ llvm/lib/IR/DebugLoc.cpp | 33 +++++++++++++++++++++++--- llvm/lib/IR/IRBuilder.cpp | 13 +++++----- llvm/lib/IR/Instruction.cpp | 6 +++-- llvm/lib/Support/Unix/Signals.inc | 1 + llvm/lib/Support/Windows/Signals.inc | 1 + llvm/lib/Transforms/Utils/Debugify.cpp | 25 ++++++++++++------- 12 files changed, 112 insertions(+), 31 deletions(-) diff --git a/llvm/include/llvm/IR/DebugLoc.h b/llvm/include/llvm/IR/DebugLoc.h index 1494e53c5df35..dc4329c15787c 100644 --- a/llvm/include/llvm/IR/DebugLoc.h +++ b/llvm/include/llvm/IR/DebugLoc.h @@ -27,10 +27,10 @@ namespace llvm { #ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING struct DbgLocOriginBacktrace { - static constexpr unsigned long MaxDepth = 8; - std::array Stacktrace; - int Depth = 0; + static constexpr unsigned long MaxDepth = 16; + SmallVector>, 0> Stacktraces; DbgLocOriginBacktrace(bool ShouldCollectTrace); + void addTrace(); }; // Used to represent different "kinds" of DebugLoc, expressing that a DebugLoc @@ -121,12 +121,24 @@ namespace llvm { DebugLoc(DebugLocKind Kind) : Loc(Kind) {} DebugLocKind getKind() const { return Loc.Kind; } DbgLocOriginBacktrace getOrigin() const { return Loc.Origin; } + DebugLoc getCopied() const { + DebugLoc NewDL = *this; + NewDL.Loc.Origin.addTrace(); + return NewDL; + } +#else + DebugLoc getCopied() const { + return *this; + } #endif static DebugLoc getTemporary(); static DebugLoc getUnknown(); static DebugLoc getLineZero(); + static DebugLoc getMergedLocations(ArrayRef Locs); + static DebugLoc getMergedLocation(DebugLoc LocA, DebugLoc LocB); + /// Get the underlying \a DILocation. /// /// \pre !*this or \c isa(getAsMDNode()). diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h index 31a1fef321995..92ff0327b272b 100644 --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -93,9 +93,15 @@ class IRBuilderBase { /// created instructions, like !dbg metadata. SmallVector, 2> MetadataToCopy; + DebugLoc StoredDL; + /// Add or update the an entry (Kind, MD) to MetadataToCopy, if \p MD is not /// null. If \p MD is null, remove the entry with \p Kind. void AddOrRemoveMetadataToCopy(unsigned Kind, MDNode *MD) { + if (Kind == LLVMContext::MD_dbg) { + StoredDL = DebugLoc(MD); + } + if (!MD) { erase_if(MetadataToCopy, [Kind](const std::pair &KV) { return KV.first == Kind; @@ -216,6 +222,10 @@ class IRBuilderBase { /// Set location information used by debugging information. void SetCurrentDebugLocation(DebugLoc L) { AddOrRemoveMetadataToCopy(LLVMContext::MD_dbg, L.getAsMDNode()); + // Although we set StoredDL in the above call, we prefer to use the exact + // DebugLoc we were given, so overwrite it here; the call is only needed to + // update the entry in MetadataToCopy. + StoredDL = std::move(L); } /// Set nosanitize metadata. @@ -229,8 +239,11 @@ class IRBuilderBase { /// not on \p Src will be dropped from MetadataToCopy. void CollectMetadataToCopy(Instruction *Src, ArrayRef MetadataKinds) { - for (unsigned K : MetadataKinds) + for (unsigned K : MetadataKinds) { AddOrRemoveMetadataToCopy(K, Src->getMetadata(K)); + if (K == LLVMContext::MD_dbg) + SetCurrentDebugLocation(Src->getDebugLoc()); + } } /// Get location information used by debugging information. @@ -242,8 +255,21 @@ class IRBuilderBase { /// Add all entries in MetadataToCopy to \p I. void AddMetadataToInst(Instruction *I) const { - for (const auto &KV : MetadataToCopy) + for (const auto &KV : MetadataToCopy) { + if (KV.first == LLVMContext::MD_dbg) { + // If `!I->getDebugLoc()` then we will call this below anyway, so skip + // a duplicate call here. + if (I->getDebugLoc()) + I->setDebugLoc(StoredDL.getCopied()); + continue; + } I->setMetadata(KV.first, KV.second); + } + // If I does not have an existing DebugLoc and no DebugLoc has been set + // here, we copy our DebugLoc to I anyway, because more likely than not I + // is a new instruction whose DL should originate from this builder. + if (!I->getDebugLoc()) + I->setDebugLoc(StoredDL.getCopied()); } /// Get the return type of the current function that we're emitting diff --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h index c27572300d506..16024dbcfdaad 100644 --- a/llvm/include/llvm/IR/Instruction.h +++ b/llvm/include/llvm/IR/Instruction.h @@ -647,6 +647,7 @@ class Instruction : public User, /// The DebugLoc attached to this instruction will be overwritten by the /// merged DebugLoc. void applyMergedLocation(DILocation *LocA, DILocation *LocB); + void applyMergedLocation(DebugLoc LocA, DebugLoc LocB); /// Updates the debug location given that the instruction has been hoisted /// from a block to a predecessor of that block. diff --git a/llvm/lib/CodeGen/BranchFolding.cpp b/llvm/lib/CodeGen/BranchFolding.cpp index 92a03eb52e35d..d55be6c112ec7 100644 --- a/llvm/lib/CodeGen/BranchFolding.cpp +++ b/llvm/lib/CodeGen/BranchFolding.cpp @@ -841,7 +841,7 @@ void BranchFolder::mergeCommonTails(unsigned commonTailIndex) { "Reached BB end within common tail"); } assert(MI.isIdenticalTo(*Pos) && "Expected matching MIIs!"); - DL = DILocation::getMergedLocation(DL, Pos->getDebugLoc()); + DL = DebugLoc::getMergedLocation(DL, Pos->getDebugLoc()); NextCommonInsts[i] = ++Pos; } MI.setDebugLoc(DL); @@ -915,7 +915,7 @@ bool BranchFolder::TryTailMergeBlocks(MachineBasicBlock *SuccBB, // Walk through equivalence sets looking for actual exact matches. while (MergePotentials.size() > 1) { unsigned CurHash = MergePotentials.back().getHash(); - const DebugLoc &BranchDL = MergePotentials.back().getBranchDebugLoc(); + const DebugLoc BranchDL = MergePotentials.back().getBranchDebugLoc(); // Build SameTails, identifying the set of blocks with this hash code // and with the maximum number of instructions in common. diff --git a/llvm/lib/CodeGen/BranchFolding.h b/llvm/lib/CodeGen/BranchFolding.h index ff2bbe06c0488..5d05be78f60e5 100644 --- a/llvm/lib/CodeGen/BranchFolding.h +++ b/llvm/lib/CodeGen/BranchFolding.h @@ -50,11 +50,11 @@ class TargetRegisterInfo; class MergePotentialsElt { unsigned Hash; MachineBasicBlock *Block; - DebugLoc BranchDebugLoc; + MDNode *BranchDebugLoc; public: - MergePotentialsElt(unsigned h, MachineBasicBlock *b, DebugLoc bdl) - : Hash(h), Block(b), BranchDebugLoc(std::move(bdl)) {} + MergePotentialsElt(unsigned h, MachineBasicBlock *b, MDNode *bdl) + : Hash(h), Block(b), BranchDebugLoc(bdl) {} unsigned getHash() const { return Hash; } MachineBasicBlock *getBlock() const { return Block; } @@ -63,7 +63,7 @@ class TargetRegisterInfo; Block = MBB; } - const DebugLoc &getBranchDebugLoc() { return BranchDebugLoc; } + const DebugLoc getBranchDebugLoc() { return DebugLoc(BranchDebugLoc); } bool operator<(const MergePotentialsElt &) const; }; diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp index 86ac46540c5ef..a11d23fd7bb65 100644 --- a/llvm/lib/IR/DebugInfo.cpp +++ b/llvm/lib/IR/DebugInfo.cpp @@ -932,6 +932,9 @@ unsigned llvm::getDebugMetadataVersionFromModule(const Module &M) { void Instruction::applyMergedLocation(DILocation *LocA, DILocation *LocB) { setDebugLoc(DILocation::getMergedLocation(LocA, LocB)); } +void Instruction::applyMergedLocation(DebugLoc LocA, DebugLoc LocB) { + setDebugLoc(DebugLoc::getMergedLocation(LocA, LocB)); +} void Instruction::mergeDIAssignID( ArrayRef SourceInstructions) { diff --git a/llvm/lib/IR/DebugLoc.cpp b/llvm/lib/IR/DebugLoc.cpp index 3a6cb00c4dda6..478fa1607894d 100644 --- a/llvm/lib/IR/DebugLoc.cpp +++ b/llvm/lib/IR/DebugLoc.cpp @@ -20,10 +20,17 @@ DILocAndCoverageTracking::DILocAndCoverageTracking(const DILocation *L) : TrackingMDNodeRef(const_cast(L)), Kind(DebugLocKind::Normal), Origin(!L) {} -DbgLocOriginBacktrace::DbgLocOriginBacktrace(bool ShouldCollectTrace) - : Depth(0) { - if (ShouldCollectTrace) +DbgLocOriginBacktrace::DbgLocOriginBacktrace(bool ShouldCollectTrace) { + if (ShouldCollectTrace) { + auto &[Depth, Stacktrace] = Stacktraces.emplace_back(); Depth = sys::getStackTrace(Stacktrace); + } +} +void DbgLocOriginBacktrace::addTrace() { + if (Stacktraces.empty()) + return; + auto &[Depth, Stacktrace] = Stacktraces.emplace_back(); + Depth = sys::getStackTrace(Stacktrace); } DebugLoc DebugLoc::getTemporary() { @@ -36,6 +43,26 @@ DebugLoc DebugLoc::getLineZero() { return DebugLoc(DebugLocKind::LineZero); } +DebugLoc DebugLoc::getMergedLocations(ArrayRef Locs) { + if (Locs.empty()) + return DebugLoc(); + if (Locs.size() == 1) + return Locs[0]; + DebugLoc Merged = Locs[0]; + for (const DebugLoc &DL : llvm::drop_begin(Locs)) { + Merged = getMergedLocation(Merged, DL); + if (!Merged) + break; + } + return Merged; +} +DebugLoc DebugLoc::getMergedLocation(DebugLoc LocA, DebugLoc LocB) { + if (!LocA) + return LocA.getCopied(); + if (!LocB) + return LocB.getCopied(); + return DILocation::getMergedLocation(LocA, LocB); +} #else using namespace llvm; diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp index e5cde875ab1d8..22826e4879bd8 100644 --- a/llvm/lib/IR/IRBuilder.cpp +++ b/llvm/lib/IR/IRBuilder.cpp @@ -62,18 +62,19 @@ Type *IRBuilderBase::getCurrentFunctionReturnType() const { } DebugLoc IRBuilderBase::getCurrentDebugLocation() const { - for (auto &KV : MetadataToCopy) - if (KV.first == LLVMContext::MD_dbg) - return {cast(KV.second)}; - - return {}; + return StoredDL; } void IRBuilderBase::SetInstDebugLocation(Instruction *I) const { for (const auto &KV : MetadataToCopy) if (KV.first == LLVMContext::MD_dbg) { - I->setDebugLoc(DebugLoc(KV.second)); + I->setDebugLoc(StoredDL.getCopied()); return; } + // If I does not have an existing DebugLoc and no DebugLoc has been set + // here, we copy our DebugLoc to I anyway, because more likely than not I + // is a new instruction whose DL should originate from this builder. + if (!I->getDebugLoc()) + I->setDebugLoc(StoredDL.getCopied()); } CallInst * diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp index 6f0f3f244c050..2c0713aa88641 100644 --- a/llvm/lib/IR/Instruction.cpp +++ b/llvm/lib/IR/Instruction.cpp @@ -1279,6 +1279,9 @@ void Instruction::swapProfMetadata() { void Instruction::copyMetadata(const Instruction &SrcInst, ArrayRef WL) { + if (WL.empty() || is_contained(WL, LLVMContext::MD_dbg)) + setDebugLoc(SrcInst.getDebugLoc()); + if (!SrcInst.hasMetadata()) return; @@ -1292,8 +1295,6 @@ void Instruction::copyMetadata(const Instruction &SrcInst, if (WL.empty() || WLS.count(MD.first)) setMetadata(MD.first, MD.second); } - if (WL.empty() || WLS.count(LLVMContext::MD_dbg)) - setDebugLoc(SrcInst.getDebugLoc()); } Instruction *Instruction::clone() const { @@ -1311,5 +1312,6 @@ Instruction *Instruction::clone() const { New->SubclassOptionalData = SubclassOptionalData; New->copyMetadata(*this); + New->setDebugLoc(getDebugLoc().getCopied()); return New; } diff --git a/llvm/lib/Support/Unix/Signals.inc b/llvm/lib/Support/Unix/Signals.inc index fc8e5d2cd4c15..c494e16514fc0 100644 --- a/llvm/lib/Support/Unix/Signals.inc +++ b/llvm/lib/Support/Unix/Signals.inc @@ -508,6 +508,7 @@ int getStackTrace(std::array &StackTrace) { return backtrace(StackTrace.data(), MaxDepth); } template int getStackTrace<8ul>(std::array &); +template int getStackTrace<16ul>(std::array &); } } #endif diff --git a/llvm/lib/Support/Windows/Signals.inc b/llvm/lib/Support/Windows/Signals.inc index 85e778bc74536..d5fca28bcfb83 100644 --- a/llvm/lib/Support/Windows/Signals.inc +++ b/llvm/lib/Support/Windows/Signals.inc @@ -593,6 +593,7 @@ int getStackTrace(std::array &StackTrace) { return WalkDepth; } template int llvm::sys::getStackTrace<8ul>(std::array &); +template int llvm::sys::getStackTrace<16ul>(std::array &); } } #endif diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp b/llvm/lib/Transforms/Utils/Debugify.cpp index e20ec86dd3c08..1d56b6ed82118 100644 --- a/llvm/lib/Transforms/Utils/Debugify.cpp +++ b/llvm/lib/Transforms/Utils/Debugify.cpp @@ -81,20 +81,27 @@ std::string symbolizeStacktrace(const Instruction *I) { DbgLocOriginBacktrace ST = I->getDebugLoc().getOrigin(); std::string Result; raw_string_ostream OS(Result); - for (int Frame = 0; Frame < ST.Depth; ++Frame) { - assert(SymbolizedAddrs.contains(ST.Stacktrace[Frame]) && - "Expected each address to have been symbolized."); - OS << right_justify(formatv("#{0}", Frame).str(), std::log10(ST.Depth) + 2) - << ' ' << SymbolizedAddrs[ST.Stacktrace[Frame]]; + for (size_t TraceIdx = 0; TraceIdx < ST.Stacktraces.size(); ++TraceIdx) { + if (TraceIdx != 0) + OS << "========================================\n"; + auto &[Depth, Stacktrace] = ST.Stacktraces[TraceIdx]; + for (int Frame = 0; Frame < Depth; ++Frame) { + assert(SymbolizedAddrs.contains(Stacktrace[Frame]) && + "Expected each address to have been symbolized."); + OS << right_justify(formatv("#{0}", Frame).str(), std::log10(Depth) + 2) + << ' ' << SymbolizedAddrs[Stacktrace[Frame]]; + } } return Result; } void collectStackAddresses(Instruction &I) { DbgLocOriginBacktrace ST = I.getDebugLoc().getOrigin(); - for (int Frame = 0; Frame < ST.Depth; ++Frame) { - void *Addr = ST.Stacktrace[Frame]; - if (!SymbolizedAddrs.contains(Addr)) - UnsymbolizedAddrs.insert(Addr); + for (auto &[Depth, Stacktrace] : ST.Stacktraces) { + for (int Frame = 0; Frame < Depth; ++Frame) { + void *Addr = Stacktrace[Frame]; + if (!SymbolizedAddrs.contains(Addr)) + UnsymbolizedAddrs.insert(Addr); + } } } #else From f23826d60e593702e09c25f54b7e26015fbf060c Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Wed, 14 Aug 2024 17:19:35 +0100 Subject: [PATCH 07/15] Use DebugLoc::getMergedLocations instead of DILocation::* --- .../CodeGen/GlobalISel/LegalizationArtifactCombiner.h | 4 ++-- llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp | 6 +++--- llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp | 2 +- llvm/lib/CodeGen/MachineBasicBlock.cpp | 2 +- llvm/lib/CodeGen/MachineSink.cpp | 4 ++-- .../Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp | 4 ++-- llvm/lib/Transforms/Scalar/ConstantHoisting.cpp | 2 +- llvm/lib/Transforms/Scalar/LICM.cpp | 8 ++++---- llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp | 4 ++-- llvm/lib/Transforms/Utils/SimplifyCFG.cpp | 6 +++--- 10 files changed, 21 insertions(+), 21 deletions(-) diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h index bc83f19dc581f..e5ad976ecd3ce 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h @@ -100,8 +100,8 @@ class LegalizationArtifactCombiner { const LLT DstTy = MRI.getType(DstReg); if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) { auto &CstVal = SrcMI->getOperand(1); - auto *MergedLocation = DILocation::getMergedLocation( - MI.getDebugLoc().get(), SrcMI->getDebugLoc().get()); + auto MergedLocation = DebugLoc::getMergedLocation( + MI.getDebugLoc(), SrcMI->getDebugLoc()); // Set the debug location to the merged location of the SrcMI and the MI // if the aext fold is successful. Builder.setDebugLoc(MergedLocation); diff --git a/llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp index 547529bbe699a..f546003064c37 100644 --- a/llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp @@ -53,8 +53,8 @@ CSEMIRBuilder::getDominatingInstrForID(FoldingSetNodeID &ID, } else if (!dominates(MI, CurrPos)) { // Update the spliced machineinstr's debug location by merging it with the // debug location of the instruction at the insertion point. - auto *Loc = DILocation::getMergedLocation(getDebugLoc().get(), - MI->getDebugLoc().get()); + auto Loc = DebugLoc::getMergedLocation(getDebugLoc(), + MI->getDebugLoc()); MI->setDebugLoc(Loc); CurMBB->splice(CurrPos, CurMBB, MI); } @@ -164,7 +164,7 @@ CSEMIRBuilder::generateCopiesIfRequired(ArrayRef DstOps, if (Observer) Observer->changingInstr(*MIB); MIB->setDebugLoc( - DILocation::getMergedLocation(MIB->getDebugLoc(), getDebugLoc())); + DebugLoc::getMergedLocation(MIB->getDebugLoc(), getDebugLoc())); if (Observer) Observer->changedInstr(*MIB); } diff --git a/llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp b/llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp index 0d0c093648eba..c6712fafebcb3 100644 --- a/llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LoadStoreOpt.cpp @@ -373,7 +373,7 @@ bool LoadStoreOpt::doSingleStoreMerge(SmallVectorImpl &Stores) { // For each store, compute pairwise merged debug locs. DebugLoc MergedLoc = Stores.front()->getDebugLoc(); for (auto *Store : drop_begin(Stores)) - MergedLoc = DILocation::getMergedLocation(MergedLoc, Store->getDebugLoc()); + MergedLoc = DebugLoc::getMergedLocation(MergedLoc, Store->getDebugLoc()); Builder.setInstr(*Stores.back()); Builder.setDebugLoc(MergedLoc); diff --git a/llvm/lib/CodeGen/MachineBasicBlock.cpp b/llvm/lib/CodeGen/MachineBasicBlock.cpp index d681d00b5d8c4..4dee67a7adeab 100644 --- a/llvm/lib/CodeGen/MachineBasicBlock.cpp +++ b/llvm/lib/CodeGen/MachineBasicBlock.cpp @@ -1564,7 +1564,7 @@ MachineBasicBlock::findBranchDebugLoc() { DL = TI->getDebugLoc(); for (++TI ; TI != end() ; ++TI) if (TI->isBranch()) - DL = DILocation::getMergedLocation(DL, TI->getDebugLoc()); + DL = DebugLoc::getMergedLocation(DL, TI->getDebugLoc()); } return DL; } diff --git a/llvm/lib/CodeGen/MachineSink.cpp b/llvm/lib/CodeGen/MachineSink.cpp index 4b3ff57fb478a..61d5aa5b99079 100644 --- a/llvm/lib/CodeGen/MachineSink.cpp +++ b/llvm/lib/CodeGen/MachineSink.cpp @@ -1441,8 +1441,8 @@ static void performSink(MachineInstr &MI, MachineBasicBlock &SuccToSinkTo, // location to prevent debug-info driven tools from potentially reporting // wrong location information. if (!SuccToSinkTo.empty() && InsertPos != SuccToSinkTo.end()) - MI.setDebugLoc(DILocation::getMergedLocation(MI.getDebugLoc(), - InsertPos->getDebugLoc())); + MI.setDebugLoc(DebugLoc::getMergedLocation(MI.getDebugLoc(), + InsertPos->getDebugLoc())); else MI.setDebugLoc(DebugLoc()); diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp index 1661fa564c65c..e0dcc9b8d04f9 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -1574,8 +1574,8 @@ bool InstCombinerImpl::mergeStoreIntoSuccessor(StoreInst &SI) { // Insert a PHI node now if we need it. Value *MergedVal = OtherStore->getValueOperand(); // The debug locations of the original instructions might differ. Merge them. - DebugLoc MergedLoc = DILocation::getMergedLocation(SI.getDebugLoc(), - OtherStore->getDebugLoc()); + DebugLoc MergedLoc = DebugLoc::getMergedLocation(SI.getDebugLoc(), + OtherStore->getDebugLoc()); if (MergedVal != SI.getValueOperand()) { PHINode *PN = PHINode::Create(SI.getValueOperand()->getType(), 2, "storemerge"); diff --git a/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp b/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp index 4a6dedc93d306..3e0bc19c1b6f8 100644 --- a/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp +++ b/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp @@ -909,7 +909,7 @@ bool ConstantHoistingPass::emitBaseConstants(GlobalVariable *BaseGV) { emitBaseConstants(Base, &R); ReBasesNum++; // Use the same debug location as the last user of the constant. - Base->setDebugLoc(DILocation::getMergedLocation( + Base->setDebugLoc(DebugLoc::getMergedLocation( Base->getDebugLoc(), R.User.Inst->getDebugLoc())); } assert(!Base->use_empty() && "The use list is empty!?"); diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp index 1d236c018bab6..1b6a6b000ab40 100644 --- a/llvm/lib/Transforms/Scalar/LICM.cpp +++ b/llvm/lib/Transforms/Scalar/LICM.cpp @@ -2220,10 +2220,10 @@ bool llvm::promoteLoopAccessesToScalars( }); // Look at all the loop uses, and try to merge their locations. - std::vector LoopUsesLocs; - for (auto *U : LoopUses) - LoopUsesLocs.push_back(U->getDebugLoc().get()); - auto DL = DebugLoc(DILocation::getMergedLocations(LoopUsesLocs)); + std::vector LoopUsesLocs; + for (auto U : LoopUses) + LoopUsesLocs.push_back(U->getDebugLoc()); + auto DL = DebugLoc::getMergedLocations(LoopUsesLocs); // We use the SSAUpdater interface to insert phi nodes as required. SmallVector NewPHIs; diff --git a/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp b/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp index 11de37f7a7c10..76e534b872fab 100644 --- a/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp +++ b/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp @@ -124,7 +124,7 @@ performBlockTailMerging(Function &F, ArrayRef BBs, // Now, go through each block (with the current terminator type) // we've recorded, and rewrite it to branch to the new common block. - DILocation *CommonDebugLoc = nullptr; + DebugLoc CommonDebugLoc; for (BasicBlock *BB : BBs) { auto *Term = BB->getTerminator(); assert(Term->getOpcode() == CanonicalTerm->getOpcode() && @@ -141,7 +141,7 @@ performBlockTailMerging(Function &F, ArrayRef BBs, CommonDebugLoc = Term->getDebugLoc(); else CommonDebugLoc = - DILocation::getMergedLocation(CommonDebugLoc, Term->getDebugLoc()); + DebugLoc::getMergedLocation(CommonDebugLoc, Term->getDebugLoc()); // And turn BB into a block that just unconditionally branches // to the canonical block. diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp index 910b9dbeed444..1724cb292ff25 100644 --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -1840,11 +1840,11 @@ bool SimplifyCFGOpt::hoistSuccIdenticalTerminatorToSwitchOrIf( // Ensure terminator gets a debug location, even an unknown one, in case // it involves inlinable calls. - SmallVector Locs; + SmallVector Locs; Locs.push_back(I1->getDebugLoc()); for (auto *OtherSuccTI : OtherSuccTIs) Locs.push_back(OtherSuccTI->getDebugLoc()); - NT->setDebugLoc(DILocation::getMergedLocations(Locs)); + NT->setDebugLoc(DebugLoc::getMergedLocations(Locs)); // PHIs created below will adopt NT's merged DebugLoc. IRBuilder Builder(NT); @@ -2725,7 +2725,7 @@ static void MergeCompatibleInvokesImpl(ArrayRef Invokes, MergedDebugLoc = II->getDebugLoc(); else MergedDebugLoc = - DILocation::getMergedLocation(MergedDebugLoc, II->getDebugLoc()); + DebugLoc::getMergedLocation(MergedDebugLoc, II->getDebugLoc()); // And replace the old `invoke` with an unconditionally branch // to the block with the merged `invoke`. From 39df02fd5066a6400aeab632a0d465c3f3ccfb2c Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Wed, 14 Aug 2024 15:15:57 +0100 Subject: [PATCH 08/15] BugFix: don't randomly drop DILoc bugs for a file --- llvm/utils/llvm-original-di-preservation.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/llvm/utils/llvm-original-di-preservation.py b/llvm/utils/llvm-original-di-preservation.py index a3da233ae30dc..36577cec07826 100755 --- a/llvm/utils/llvm-original-di-preservation.py +++ b/llvm/utils/llvm-original-di-preservation.py @@ -462,9 +462,9 @@ def Main(): di_file_args = OrderedDict() # Use the defaultdict in order to make multidim dicts. - di_location_bugs = defaultdict(lambda: defaultdict(dict)) - di_subprogram_bugs = defaultdict(lambda: defaultdict(dict)) - di_variable_bugs = defaultdict(lambda: defaultdict(dict)) + di_location_bugs = defaultdict(lambda: defaultdict(list)) + di_subprogram_bugs = defaultdict(lambda: defaultdict(list)) + di_variable_bugs = defaultdict(lambda: defaultdict(list)) # Use the ordered dict to make a summary. di_location_bugs_summary = OrderedDict() @@ -509,9 +509,9 @@ def Main(): skipped_lines += 1 continue - di_loc_bugs = [] - di_sp_bugs = [] - di_var_bugs = [] + di_loc_bugs = di_location_bugs[bugs_file][bugs_pass] + di_sp_bugs = di_subprogram_bugs[bugs_file][bugs_pass] + di_var_bugs = di_variable_bugs[bugs_file][bugs_pass] # Omit duplicated bugs. di_loc_set = set() From f61843f352d42fd2cf54a78c6bcadaeee4603d30 Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Thu, 15 Aug 2024 11:45:54 +0100 Subject: [PATCH 09/15] Move DebugLoc::getMergedLocation(s) out of #ifdef --- llvm/lib/IR/DebugLoc.cpp | 41 ++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/llvm/lib/IR/DebugLoc.cpp b/llvm/lib/IR/DebugLoc.cpp index 478fa1607894d..1864471039202 100644 --- a/llvm/lib/IR/DebugLoc.cpp +++ b/llvm/lib/IR/DebugLoc.cpp @@ -43,26 +43,6 @@ DebugLoc DebugLoc::getLineZero() { return DebugLoc(DebugLocKind::LineZero); } -DebugLoc DebugLoc::getMergedLocations(ArrayRef Locs) { - if (Locs.empty()) - return DebugLoc(); - if (Locs.size() == 1) - return Locs[0]; - DebugLoc Merged = Locs[0]; - for (const DebugLoc &DL : llvm::drop_begin(Locs)) { - Merged = getMergedLocation(Merged, DL); - if (!Merged) - break; - } - return Merged; -} -DebugLoc DebugLoc::getMergedLocation(DebugLoc LocA, DebugLoc LocB) { - if (!LocA) - return LocA.getCopied(); - if (!LocB) - return LocB.getCopied(); - return DILocation::getMergedLocation(LocA, LocB); -} #else using namespace llvm; @@ -197,6 +177,27 @@ DebugLoc DebugLoc::appendInlinedAt(const DebugLoc &DL, DILocation *InlinedAt, return Last; } +DebugLoc DebugLoc::getMergedLocations(ArrayRef Locs) { + if (Locs.empty()) + return DebugLoc(); + if (Locs.size() == 1) + return Locs[0]; + DebugLoc Merged = Locs[0]; + for (const DebugLoc &DL : llvm::drop_begin(Locs)) { + Merged = getMergedLocation(Merged, DL); + if (!Merged) + break; + } + return Merged; +} +DebugLoc DebugLoc::getMergedLocation(DebugLoc LocA, DebugLoc LocB) { + if (!LocA) + return LocA.getCopied(); + if (!LocB) + return LocB.getCopied(); + return DILocation::getMergedLocation(LocA, LocB); +} + #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void DebugLoc::dump() const { print(dbgs()); } #endif From 93ec6986c968efaff9e57b91a4c83df947a2010f Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Mon, 2 Sep 2024 14:06:39 +0100 Subject: [PATCH 10/15] Review comments, and attempted optimization --- llvm/include/llvm/IR/DebugLoc.h | 11 ++- llvm/include/llvm/IR/IRBuilder.h | 34 +++---- llvm/include/llvm/Support/Signals.h | 10 ++ llvm/lib/IR/DebugLoc.cpp | 124 +++++++++++++++++++++++-- llvm/lib/IR/IRBuilder.cpp | 7 +- llvm/lib/Transforms/Utils/Debugify.cpp | 12 ++- 6 files changed, 153 insertions(+), 45 deletions(-) diff --git a/llvm/include/llvm/IR/DebugLoc.h b/llvm/include/llvm/IR/DebugLoc.h index dc4329c15787c..301770df8d531 100644 --- a/llvm/include/llvm/IR/DebugLoc.h +++ b/llvm/include/llvm/IR/DebugLoc.h @@ -26,10 +26,11 @@ namespace llvm { class Function; #ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING - struct DbgLocOriginBacktrace { + struct DbgLocOriginStacktrace { static constexpr unsigned long MaxDepth = 16; - SmallVector>, 0> Stacktraces; - DbgLocOriginBacktrace(bool ShouldCollectTrace); + size_t StacktraceIdx; + DbgLocOriginStacktrace(bool ShouldCollectTrace); + SmallVector>, 0> getStacktraces(); void addTrace(); }; @@ -58,7 +59,7 @@ namespace llvm { DebugLocKind Kind; // Currently we only need to track the Origin of this DILoc when using a // normal empty DebugLoc, so only collect the stack trace in those cases. - DbgLocOriginBacktrace Origin; + DbgLocOriginStacktrace Origin; DILocAndCoverageTracking(bool NeedsStacktrace = true) : TrackingMDNodeRef(nullptr), Kind(DebugLocKind::Normal), Origin(NeedsStacktrace) { } @@ -120,7 +121,7 @@ namespace llvm { #ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING DebugLoc(DebugLocKind Kind) : Loc(Kind) {} DebugLocKind getKind() const { return Loc.Kind; } - DbgLocOriginBacktrace getOrigin() const { return Loc.Origin; } + DbgLocOriginStacktrace getOrigin() const { return Loc.Origin; } DebugLoc getCopied() const { DebugLoc NewDL = *this; NewDL.Loc.Origin.addTrace(); diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h index 92ff0327b272b..751dea9b66830 100644 --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -90,17 +90,19 @@ class IRBuilderCallbackInserter : public IRBuilderDefaultInserter { /// Common base class shared among various IRBuilders. class IRBuilderBase { /// Pairs of (metadata kind, MDNode *) that should be added to all newly - /// created instructions, like !dbg metadata. + /// created instructions, excluding !dbg metadata, which is stored in the + // StoredDL field. SmallVector, 2> MetadataToCopy; - + // The DebugLoc that will be applied to instructions inserted by this builder. DebugLoc StoredDL; + // Tracks whether we have explicitly set a DebugLoc - valid or empty - in this + // builder, to determine whether to copy StoredDL to inserted instructions. + bool HasExplicitDL = false; /// Add or update the an entry (Kind, MD) to MetadataToCopy, if \p MD is not /// null. If \p MD is null, remove the entry with \p Kind. void AddOrRemoveMetadataToCopy(unsigned Kind, MDNode *MD) { - if (Kind == LLVMContext::MD_dbg) { - StoredDL = DebugLoc(MD); - } + assert(Kind != LLVMContext::MD_dbg && "MD_dbg metadata must be stored in StoredDL"); if (!MD) { erase_if(MetadataToCopy, [Kind](const std::pair &KV) { @@ -221,11 +223,10 @@ class IRBuilderBase { /// Set location information used by debugging information. void SetCurrentDebugLocation(DebugLoc L) { - AddOrRemoveMetadataToCopy(LLVMContext::MD_dbg, L.getAsMDNode()); - // Although we set StoredDL in the above call, we prefer to use the exact - // DebugLoc we were given, so overwrite it here; the call is only needed to - // update the entry in MetadataToCopy. + // For !dbg metadata attachments, we use DebugLoc instead of the raw MDNode + // to include optional introspection data for use in Debugify. StoredDL = std::move(L); + HasExplicitDL = true; } /// Set nosanitize metadata. @@ -240,9 +241,10 @@ class IRBuilderBase { void CollectMetadataToCopy(Instruction *Src, ArrayRef MetadataKinds) { for (unsigned K : MetadataKinds) { - AddOrRemoveMetadataToCopy(K, Src->getMetadata(K)); if (K == LLVMContext::MD_dbg) SetCurrentDebugLocation(Src->getDebugLoc()); + else + AddOrRemoveMetadataToCopy(K, Src->getMetadata(K)); } } @@ -255,20 +257,12 @@ class IRBuilderBase { /// Add all entries in MetadataToCopy to \p I. void AddMetadataToInst(Instruction *I) const { - for (const auto &KV : MetadataToCopy) { - if (KV.first == LLVMContext::MD_dbg) { - // If `!I->getDebugLoc()` then we will call this below anyway, so skip - // a duplicate call here. - if (I->getDebugLoc()) - I->setDebugLoc(StoredDL.getCopied()); - continue; - } + for (const auto &KV : MetadataToCopy) I->setMetadata(KV.first, KV.second); - } // If I does not have an existing DebugLoc and no DebugLoc has been set // here, we copy our DebugLoc to I anyway, because more likely than not I // is a new instruction whose DL should originate from this builder. - if (!I->getDebugLoc()) + if (HasExplicitDL || !I->getDebugLoc()) I->setDebugLoc(StoredDL.getCopied()); } diff --git a/llvm/include/llvm/Support/Signals.h b/llvm/include/llvm/Support/Signals.h index 8281274f2ef06..4c34b374a196d 100644 --- a/llvm/include/llvm/Support/Signals.h +++ b/llvm/include/llvm/Support/Signals.h @@ -72,10 +72,20 @@ namespace sys { void PrintStackTrace(raw_ostream &OS, int Depth = 0); #ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING +#ifdef NDEBUG +#error DebugLoc Coverage Tracking should not be enabled in Release builds. +#endif + /// Populates the given array with a stacktrace of the current program, up to MaxDepth frames. + /// Returns the number of frames returned, which will be inserted into \p StackTrace from index 0. + /// All entries after the returned depth will be unmodified. + /// NB: This is only intended to be used for introspection of LLVM by Debugify, will not be + /// enabled in release builds, and should not be relied on for other purposes. template int getStackTrace(std::array &StackTrace); /// Takes a set of \p Addresses, symbolizes them and stores the result in the /// provided \p SymbolizedAddresses map. + /// NB: This is only intended to be used for introspection of LLVM by Debugify, will not be + /// enabled in release builds, and should not be relied on for other purposes. void symbolizeAddresses(AddressSet &Addresses, SymbolizedAddressMap &SymbolizedAddresses); #endif diff --git a/llvm/lib/IR/DebugLoc.cpp b/llvm/lib/IR/DebugLoc.cpp index 1864471039202..b04f398ffb353 100644 --- a/llvm/lib/IR/DebugLoc.cpp +++ b/llvm/lib/IR/DebugLoc.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/Hashing.h" #include "llvm/IR/DebugLoc.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/DebugInfo.h" @@ -16,21 +17,126 @@ using namespace llvm; +struct StacktraceOrList { + union { + std::array Single; + std::array STList; + }; + uint8_t Size : 7; + uint8_t IsList : 1; + StacktraceOrList(int Size, std::array STList) : STList(STList), Size(Size), IsList(0) {} + StacktraceOrList(int Size, std::array Single) : Single(Single), Size(Size), IsList(1) {} + StacktraceOrList(bool Tombstone = false) : Size(Tombstone ? 0x7F : 0), IsList(Tombstone ? 1 : 0) { + static_assert(DbgLocOriginStacktrace::MaxDepth < 0x7F, "Size of backtrace array must fit in 7 bits - 1"); + } +}; + +hash_code hash_value(const StacktraceOrList &S) { + static_assert(DbgLocOriginStacktrace::MaxDepth < (1 << 7)); + hash_code Result; + if (S.IsList) { + Result = hash_combine_range(S.Single.begin(), S.Single.begin() + S.Size); + } else { + Result = hash_combine_range(S.STList.begin(), S.STList.begin() + S.Size); + } + return Result; +} + +template <> struct DenseMapInfo { + static inline StacktraceOrList getEmptyKey() { + return StacktraceOrList(); + } + + static inline StacktraceOrList getTombstoneKey() { + return StacktraceOrList(true); + } + + static unsigned getHashValue(const StacktraceOrList &Val) { + return hash_value(Val); + } + + static bool isEqual(const StacktraceOrList &LHS, const StacktraceOrList &RHS) { + if (LHS.IsList != RHS.IsList) + return false; + if (LHS.IsList) + return ArrayRef(LHS.Single.begin(), LHS.Single.begin() + LHS.Size) == ArrayRef(RHS.Single.begin(), RHS.Single.begin() + RHS.Size); + return ArrayRef(LHS.STList.begin(), LHS.STList.begin() + LHS.Size) == ArrayRef(RHS.STList.begin(), RHS.STList.begin() + RHS.Size); + } +}; + +// Storage for every unique stacktrace or list of stacktraces collected across this run of the program. +static std::vector CollectedStacktraces(1, StacktraceOrList()); +// Mapping from a unique stacktrace or list of stacktraces to an index in the CollectedStacktraces vector. +static DenseMap StacktraceStorageMap; + +size_t getIndex(const StacktraceOrList &S) { + // Special empty value that can't be inserted into the map. + if (S.Size == 0) + return 0; + auto [It, R] = StacktraceStorageMap.insert({S, CollectedStacktraces.size()}); + if (R) + CollectedStacktraces.push_back(S); + return It->second; +} +inline StacktraceOrList getStacktraceFromIndex(size_t Idx) { + return CollectedStacktraces[Idx]; +} +// Given an index to an existing stored stacktrace, and a new +size_t getIndexForAddedTrace(size_t Idx, StacktraceOrList S) { + size_t AddedIdx = getIndex(S); + if (Idx == 0) + return AddedIdx; + StacktraceOrList Current = getStacktraceFromIndex(Idx); + StacktraceOrList New; + if (Current.IsList) { + std::array STList = {Idx, AddedIdx}; + New = StacktraceOrList(2, STList); + } else { + // There is no way to represent a STList-backtrace containing more than MaxDepth + // backtraces, so just leave it unappended. + // FIXME: We could rotate it, so that we get the MaxDepth-most recent + // backtraces rather than the oldest? + if (Current.Size == DbgLocOriginStacktrace::MaxDepth) + return Idx; + New = StacktraceOrList(Current.Size + 1, Current.STList); + New.STList[Current.Size] = AddedIdx; + } + return getIndex(S); +} + + DILocAndCoverageTracking::DILocAndCoverageTracking(const DILocation *L) : TrackingMDNodeRef(const_cast(L)), Kind(DebugLocKind::Normal), Origin(!L) {} -DbgLocOriginBacktrace::DbgLocOriginBacktrace(bool ShouldCollectTrace) { - if (ShouldCollectTrace) { - auto &[Depth, Stacktrace] = Stacktraces.emplace_back(); - Depth = sys::getStackTrace(Stacktrace); - } +DbgLocOriginStacktrace::DbgLocOriginStacktrace(bool ShouldCollectTrace) : StacktraceIdx(0) { + if (!ShouldCollectTrace) + return; + std::array Stacktrace; + int Depth = sys::getStackTrace(Stacktrace); + StacktraceIdx = getIndexForAddedTrace(StacktraceIdx, StacktraceOrList(Depth, Stacktrace)); } -void DbgLocOriginBacktrace::addTrace() { - if (Stacktraces.empty()) +void DbgLocOriginStacktrace::addTrace() { + if (StacktraceIdx == 0) return; - auto &[Depth, Stacktrace] = Stacktraces.emplace_back(); - Depth = sys::getStackTrace(Stacktrace); + std::array Stacktrace; + int Depth = sys::getStackTrace(Stacktrace); + StacktraceIdx = getIndex(StacktraceOrList(Depth, Stacktrace)); +} +SmallVector>, 0> DbgLocOriginStacktrace::getStacktraces() { + SmallVector>, 0> Stacktraces; + if (StacktraceIdx == 0) + return Stacktraces; + StacktraceOrList S = getStacktraceFromIndex(StacktraceIdx); + if (S.IsList) { + Stacktraces.push_back({(int)S.Size, S.Single}); + } else { + for (size_t SingleIdx : ArrayRef(S.STList.data(), S.Size)) { + StacktraceOrList SingleS = getStacktraceFromIndex(SingleIdx); + Stacktraces.push_back({(int)SingleS.Size, SingleS.Single}); + } + } + return Stacktraces; } DebugLoc DebugLoc::getTemporary() { diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp index 22826e4879bd8..b22c56c0e7910 100644 --- a/llvm/lib/IR/IRBuilder.cpp +++ b/llvm/lib/IR/IRBuilder.cpp @@ -65,15 +65,10 @@ DebugLoc IRBuilderBase::getCurrentDebugLocation() const { return StoredDL; } void IRBuilderBase::SetInstDebugLocation(Instruction *I) const { - for (const auto &KV : MetadataToCopy) - if (KV.first == LLVMContext::MD_dbg) { - I->setDebugLoc(StoredDL.getCopied()); - return; - } // If I does not have an existing DebugLoc and no DebugLoc has been set // here, we copy our DebugLoc to I anyway, because more likely than not I // is a new instruction whose DL should originate from this builder. - if (!I->getDebugLoc()) + if (HasExplicitDL || !I->getDebugLoc()) I->setDebugLoc(StoredDL.getCopied()); } diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp b/llvm/lib/Transforms/Utils/Debugify.cpp index 1d56b6ed82118..f75e5ff267786 100644 --- a/llvm/lib/Transforms/Utils/Debugify.cpp +++ b/llvm/lib/Transforms/Utils/Debugify.cpp @@ -78,13 +78,14 @@ std::string symbolizeStacktrace(const Instruction *I) { sys::symbolizeAddresses(UnsymbolizedAddrs, SymbolizedAddrs); UnsymbolizedAddrs.clear(); } - DbgLocOriginBacktrace ST = I->getDebugLoc().getOrigin(); + DbgLocOriginStacktrace ST = I->getDebugLoc().getOrigin(); std::string Result; raw_string_ostream OS(Result); - for (size_t TraceIdx = 0; TraceIdx < ST.Stacktraces.size(); ++TraceIdx) { + auto Stacktraces = ST.getStacktraces(); + for (size_t TraceIdx = 0; TraceIdx < Stacktraces.size(); ++TraceIdx) { if (TraceIdx != 0) OS << "========================================\n"; - auto &[Depth, Stacktrace] = ST.Stacktraces[TraceIdx]; + auto &[Depth, Stacktrace] = Stacktraces[TraceIdx]; for (int Frame = 0; Frame < Depth; ++Frame) { assert(SymbolizedAddrs.contains(Stacktrace[Frame]) && "Expected each address to have been symbolized."); @@ -95,8 +96,9 @@ std::string symbolizeStacktrace(const Instruction *I) { return Result; } void collectStackAddresses(Instruction &I) { - DbgLocOriginBacktrace ST = I.getDebugLoc().getOrigin(); - for (auto &[Depth, Stacktrace] : ST.Stacktraces) { + DbgLocOriginStacktrace ST = I.getDebugLoc().getOrigin(); + auto Stacktraces = ST.getStacktraces(); + for (auto &[Depth, Stacktrace] : Stacktraces) { for (int Frame = 0; Frame < Depth; ++Frame) { void *Addr = Stacktrace[Frame]; if (!SymbolizedAddrs.contains(Addr)) From 052d724fbaa9b935830a264c37b48e5b6a22b887 Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Tue, 3 Sep 2024 11:52:18 +0000 Subject: [PATCH 11/15] Local fixes --- clang/lib/CodeGen/BackendUtil.cpp | 2 +- llvm/CMakeLists.txt | 7 ++++++- llvm/include/llvm/Config/config.h.cmake | 2 +- llvm/include/llvm/IR/DebugLoc.h | 6 +++--- llvm/include/llvm/Support/Signals.h | 4 ++-- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 2 +- llvm/lib/IR/DebugLoc.cpp | 7 ++++--- llvm/lib/Support/Signals.cpp | 2 +- llvm/lib/Support/Unix/Signals.inc | 2 +- llvm/lib/Support/Windows/Signals.inc | 2 +- llvm/lib/Target/BPF/BPFPreserveStaticOffset.cpp | 4 ++-- llvm/lib/Transforms/Utils/Debugify.cpp | 6 +++--- 12 files changed, 26 insertions(+), 20 deletions(-) diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index abdf43a97d739..c860839bab846 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -926,7 +926,7 @@ void EmitAssemblyHelper::RunOptimizationPipeline( } Debugify.registerCallbacks(PIC, MAM); -#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING +#if ENABLE_DEBUGLOC_COVERAGE_TRACKING // If we're using debug location coverage tracking, mark all the // instructions coming out of the frontend without a DebugLoc as being // intentional line-zero locations, to prevent both those instructions and diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index ee0d566de442f..6a283ea7d6d0d 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -524,7 +524,12 @@ endif() option(LLVM_ENABLE_CRASH_DUMPS "Turn on memory dumps on crashes. Currently only implemented on Windows." OFF) -option(LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING "Enhance debugify's line number tracking at the cost of performance; abi-breaking." ON) +option(LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING "Enhance debugify's line number tracking at the cost of performance; abi-breaking." OFF) +if(LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING) + set(ENABLE_DEBUGLOC_COVERAGE_TRACKING 1) +else() + set(ENABLE_DEBUGLOC_COVERAGE_TRACKING 0) +endif() set(WINDOWS_PREFER_FORWARD_SLASH_DEFAULT OFF) if (MINGW) diff --git a/llvm/include/llvm/Config/config.h.cmake b/llvm/include/llvm/Config/config.h.cmake index 58db63acfeb07..388ce1e8f74e3 100644 --- a/llvm/include/llvm/Config/config.h.cmake +++ b/llvm/include/llvm/Config/config.h.cmake @@ -21,7 +21,7 @@ /* Define to 1 to enable expensive checks for debug location coverage checking, and to 0 otherwise. */ -#cmakedefine01 LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING +#cmakedefine01 ENABLE_DEBUGLOC_COVERAGE_TRACKING /* Define to 1 to prefer forward slashes on Windows, and to 0 prefer backslashes. */ diff --git a/llvm/include/llvm/IR/DebugLoc.h b/llvm/include/llvm/IR/DebugLoc.h index 301770df8d531..0663a7e321d56 100644 --- a/llvm/include/llvm/IR/DebugLoc.h +++ b/llvm/include/llvm/IR/DebugLoc.h @@ -25,7 +25,7 @@ namespace llvm { class DILocation; class Function; -#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING +#if ENABLE_DEBUGLOC_COVERAGE_TRACKING struct DbgLocOriginStacktrace { static constexpr unsigned long MaxDepth = 16; size_t StacktraceIdx; @@ -91,7 +91,7 @@ namespace llvm { using DebugLocTrackingRef = DILocAndCoverageTracking; #else using DebugLocTrackingRef = TrackingMDNodeRef; -#endif // LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING +#endif // ENABLE_DEBUGLOC_COVERAGE_TRACKING /// A debug info location. /// @@ -118,7 +118,7 @@ namespace llvm { /// IR. explicit DebugLoc(const MDNode *N); -#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING +#if ENABLE_DEBUGLOC_COVERAGE_TRACKING DebugLoc(DebugLocKind Kind) : Loc(Kind) {} DebugLocKind getKind() const { return Loc.Kind; } DbgLocOriginStacktrace getOrigin() const { return Loc.Origin; } diff --git a/llvm/include/llvm/Support/Signals.h b/llvm/include/llvm/Support/Signals.h index 4c34b374a196d..85b6d57d1b848 100644 --- a/llvm/include/llvm/Support/Signals.h +++ b/llvm/include/llvm/Support/Signals.h @@ -23,7 +23,7 @@ namespace llvm { class StringRef; class raw_ostream; -#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING +#if ENABLE_DEBUGLOC_COVERAGE_TRACKING template struct DenseMapInfo; template class DenseSet; namespace detail { @@ -71,7 +71,7 @@ namespace sys { /// specified, the entire frame is printed. void PrintStackTrace(raw_ostream &OS, int Depth = 0); -#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING +#if ENABLE_DEBUGLOC_COVERAGE_TRACKING #ifdef NDEBUG #error DebugLoc Coverage Tracking should not be enabled in Release builds. #endif diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 374c35fd53957..377f2300d72b2 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -2081,7 +2081,7 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) { } if (!DL) { -#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING +#if ENABLE_DEBUGLOC_COVERAGE_TRACKING assert(DL.getKind() != DebugLocKind::Temporary && "Temporary DebugLocs should never be considered for emission!"); #endif diff --git a/llvm/lib/IR/DebugLoc.cpp b/llvm/lib/IR/DebugLoc.cpp index b04f398ffb353..16f2862a6b5e6 100644 --- a/llvm/lib/IR/DebugLoc.cpp +++ b/llvm/lib/IR/DebugLoc.cpp @@ -12,7 +12,7 @@ #include "llvm/IR/DebugInfo.h" #include "llvm/IR/Function.h" -#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING +#if ENABLE_DEBUGLOC_COVERAGE_TRACKING #include "llvm/Support/Signals.h" using namespace llvm; @@ -41,7 +41,7 @@ hash_code hash_value(const StacktraceOrList &S) { } return Result; } - +namespace llvm { template <> struct DenseMapInfo { static inline StacktraceOrList getEmptyKey() { return StacktraceOrList(); @@ -63,6 +63,7 @@ template <> struct DenseMapInfo { return ArrayRef(LHS.STList.begin(), LHS.STList.begin() + LHS.Size) == ArrayRef(RHS.STList.begin(), RHS.STList.begin() + RHS.Size); } }; +} // Storage for every unique stacktrace or list of stacktraces collected across this run of the program. static std::vector CollectedStacktraces(1, StacktraceOrList()); @@ -156,7 +157,7 @@ using namespace llvm; DebugLoc DebugLoc::getTemporary() { return DebugLoc(); } DebugLoc DebugLoc::getUnknown() { return DebugLoc(); } DebugLoc DebugLoc::getLineZero() { return DebugLoc(); } -#endif // LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING +#endif // ENABLE_DEBUGLOC_COVERAGE_TRACKING //===----------------------------------------------------------------------===// // DebugLoc Implementation diff --git a/llvm/lib/Support/Signals.cpp b/llvm/lib/Support/Signals.cpp index 2fed1ae99eb0d..cad76a4702164 100644 --- a/llvm/lib/Support/Signals.cpp +++ b/llvm/lib/Support/Signals.cpp @@ -253,7 +253,7 @@ static bool printSymbolizedStackTrace(StringRef Argv0, void **StackTrace, return true; } -#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING +#if ENABLE_DEBUGLOC_COVERAGE_TRACKING void sys::symbolizeAddresses(AddressSet &Addresses, SymbolizedAddressMap &SymbolizedAddresses) { assert(!DisableSymbolicationFlag && !getenv(DisableSymbolizationEnv) && diff --git a/llvm/lib/Support/Unix/Signals.inc b/llvm/lib/Support/Unix/Signals.inc index c494e16514fc0..098a1f2c45bd2 100644 --- a/llvm/lib/Support/Unix/Signals.inc +++ b/llvm/lib/Support/Unix/Signals.inc @@ -500,7 +500,7 @@ static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) { } -#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING +#if ENABLE_DEBUGLOC_COVERAGE_TRACKING namespace llvm { namespace sys { template diff --git a/llvm/lib/Support/Windows/Signals.inc b/llvm/lib/Support/Windows/Signals.inc index d5fca28bcfb83..6e37c5739dc6e 100644 --- a/llvm/lib/Support/Windows/Signals.inc +++ b/llvm/lib/Support/Windows/Signals.inc @@ -539,7 +539,7 @@ void sys::PrintStackTraceOnErrorSignal(StringRef Argv0, extern "C" VOID WINAPI RtlCaptureContext(PCONTEXT ContextRecord); #endif -#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING +#if ENABLE_DEBUGLOC_COVERAGE_TRACKING namespace llvm { namespace sys { template diff --git a/llvm/lib/Target/BPF/BPFPreserveStaticOffset.cpp b/llvm/lib/Target/BPF/BPFPreserveStaticOffset.cpp index 5d8339b4a44ce..e843b4eed186b 100644 --- a/llvm/lib/Target/BPF/BPFPreserveStaticOffset.cpp +++ b/llvm/lib/Target/BPF/BPFPreserveStaticOffset.cpp @@ -228,7 +228,7 @@ static Instruction *makeGEPAndLoad(Module *M, GEPChainInfo &GEP, CallInst *Call = makeIntrinsicCall(M, Intrinsic::bpf_getelementptr_and_load, {Load->getType()}, Args); setParamElementType(Call, 0, GEP.SourceElementType); - Call->applyMergedLocation(mergeDILocations(GEP.Members), Load->getDebugLoc()); + Call->applyMergedLocation(DebugLoc(mergeDILocations(GEP.Members)), Load->getDebugLoc()); Call->setName((*GEP.Members.rbegin())->getName()); if (Load->isUnordered()) { Call->setOnlyReadsMemory(); @@ -252,7 +252,7 @@ static Instruction *makeGEPAndStore(Module *M, GEPChainInfo &GEP, setParamElementType(Call, 1, GEP.SourceElementType); if (Store->getValueOperand()->getType()->isPointerTy()) setParamReadNone(Call, 0); - Call->applyMergedLocation(mergeDILocations(GEP.Members), + Call->applyMergedLocation(DebugLoc(mergeDILocations(GEP.Members)), Store->getDebugLoc()); if (Store->isUnordered()) { Call->setOnlyWritesMemory(); diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp b/llvm/lib/Transforms/Utils/Debugify.cpp index f75e5ff267786..dba6ae6fbdec2 100644 --- a/llvm/lib/Transforms/Utils/Debugify.cpp +++ b/llvm/lib/Transforms/Utils/Debugify.cpp @@ -31,7 +31,7 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/JSON.h" #include -#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING +#if ENABLE_DEBUGLOC_COVERAGE_TRACKING // We need the Signals header to operate on stacktraces if we're using enhanced // coverage tracking. #include "llvm/Support/Signals.h" @@ -65,7 +65,7 @@ cl::opt DebugifyLevel( raw_ostream &dbg() { return Quiet ? nulls() : errs(); } -#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING +#if ENABLE_DEBUGLOC_COVERAGE_TRACKING // These maps refer to addresses in this instance of LLVM, so we can reuse them // everywhere - therefore, we store them at file scope. static DenseMap SymbolizedAddrs; @@ -348,7 +348,7 @@ bool llvm::stripDebugifyMetadata(Module &M) { bool hasLoc(const Instruction &I) { const DILocation *Loc = I.getDebugLoc().get(); -#ifdef LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING +#if ENABLE_DEBUGLOC_COVERAGE_TRACKING DebugLocKind Kind = I.getDebugLoc().getKind(); return Loc || Kind != DebugLocKind::Normal; #else From 513a7ec8d1e30ea9250b2ce32d8b47cc9fabafcd Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Tue, 3 Sep 2024 11:54:35 +0000 Subject: [PATCH 12/15] Revert "Review comments, and attempted optimization" Kept some review comment stuff though. This reverts commit 93ec6986c968efaff9e57b91a4c83df947a2010f. --- llvm/include/llvm/IR/DebugLoc.h | 13 ++- llvm/include/llvm/IR/IRBuilder.h | 34 ++++--- llvm/include/llvm/Support/Signals.h | 2 - llvm/lib/IR/DebugLoc.cpp | 125 ++----------------------- llvm/lib/IR/IRBuilder.cpp | 7 +- llvm/lib/Transforms/Utils/Debugify.cpp | 12 +-- 6 files changed, 46 insertions(+), 147 deletions(-) diff --git a/llvm/include/llvm/IR/DebugLoc.h b/llvm/include/llvm/IR/DebugLoc.h index 0663a7e321d56..176795d24f894 100644 --- a/llvm/include/llvm/IR/DebugLoc.h +++ b/llvm/include/llvm/IR/DebugLoc.h @@ -25,12 +25,11 @@ namespace llvm { class DILocation; class Function; -#if ENABLE_DEBUGLOC_COVERAGE_TRACKING - struct DbgLocOriginStacktrace { +#ifdef ENABLE_DEBUGLOC_COVERAGE_TRACKING + struct DbgLocOriginBacktrace { static constexpr unsigned long MaxDepth = 16; - size_t StacktraceIdx; - DbgLocOriginStacktrace(bool ShouldCollectTrace); - SmallVector>, 0> getStacktraces(); + SmallVector>, 0> Stacktraces; + DbgLocOriginBacktrace(bool ShouldCollectTrace); void addTrace(); }; @@ -59,7 +58,7 @@ namespace llvm { DebugLocKind Kind; // Currently we only need to track the Origin of this DILoc when using a // normal empty DebugLoc, so only collect the stack trace in those cases. - DbgLocOriginStacktrace Origin; + DbgLocOriginBacktrace Origin; DILocAndCoverageTracking(bool NeedsStacktrace = true) : TrackingMDNodeRef(nullptr), Kind(DebugLocKind::Normal), Origin(NeedsStacktrace) { } @@ -121,7 +120,7 @@ namespace llvm { #if ENABLE_DEBUGLOC_COVERAGE_TRACKING DebugLoc(DebugLocKind Kind) : Loc(Kind) {} DebugLocKind getKind() const { return Loc.Kind; } - DbgLocOriginStacktrace getOrigin() const { return Loc.Origin; } + DbgLocOriginBacktrace getOrigin() const { return Loc.Origin; } DebugLoc getCopied() const { DebugLoc NewDL = *this; NewDL.Loc.Origin.addTrace(); diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h index 751dea9b66830..92ff0327b272b 100644 --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -90,19 +90,17 @@ class IRBuilderCallbackInserter : public IRBuilderDefaultInserter { /// Common base class shared among various IRBuilders. class IRBuilderBase { /// Pairs of (metadata kind, MDNode *) that should be added to all newly - /// created instructions, excluding !dbg metadata, which is stored in the - // StoredDL field. + /// created instructions, like !dbg metadata. SmallVector, 2> MetadataToCopy; - // The DebugLoc that will be applied to instructions inserted by this builder. + DebugLoc StoredDL; - // Tracks whether we have explicitly set a DebugLoc - valid or empty - in this - // builder, to determine whether to copy StoredDL to inserted instructions. - bool HasExplicitDL = false; /// Add or update the an entry (Kind, MD) to MetadataToCopy, if \p MD is not /// null. If \p MD is null, remove the entry with \p Kind. void AddOrRemoveMetadataToCopy(unsigned Kind, MDNode *MD) { - assert(Kind != LLVMContext::MD_dbg && "MD_dbg metadata must be stored in StoredDL"); + if (Kind == LLVMContext::MD_dbg) { + StoredDL = DebugLoc(MD); + } if (!MD) { erase_if(MetadataToCopy, [Kind](const std::pair &KV) { @@ -223,10 +221,11 @@ class IRBuilderBase { /// Set location information used by debugging information. void SetCurrentDebugLocation(DebugLoc L) { - // For !dbg metadata attachments, we use DebugLoc instead of the raw MDNode - // to include optional introspection data for use in Debugify. + AddOrRemoveMetadataToCopy(LLVMContext::MD_dbg, L.getAsMDNode()); + // Although we set StoredDL in the above call, we prefer to use the exact + // DebugLoc we were given, so overwrite it here; the call is only needed to + // update the entry in MetadataToCopy. StoredDL = std::move(L); - HasExplicitDL = true; } /// Set nosanitize metadata. @@ -241,10 +240,9 @@ class IRBuilderBase { void CollectMetadataToCopy(Instruction *Src, ArrayRef MetadataKinds) { for (unsigned K : MetadataKinds) { + AddOrRemoveMetadataToCopy(K, Src->getMetadata(K)); if (K == LLVMContext::MD_dbg) SetCurrentDebugLocation(Src->getDebugLoc()); - else - AddOrRemoveMetadataToCopy(K, Src->getMetadata(K)); } } @@ -257,12 +255,20 @@ class IRBuilderBase { /// Add all entries in MetadataToCopy to \p I. void AddMetadataToInst(Instruction *I) const { - for (const auto &KV : MetadataToCopy) + for (const auto &KV : MetadataToCopy) { + if (KV.first == LLVMContext::MD_dbg) { + // If `!I->getDebugLoc()` then we will call this below anyway, so skip + // a duplicate call here. + if (I->getDebugLoc()) + I->setDebugLoc(StoredDL.getCopied()); + continue; + } I->setMetadata(KV.first, KV.second); + } // If I does not have an existing DebugLoc and no DebugLoc has been set // here, we copy our DebugLoc to I anyway, because more likely than not I // is a new instruction whose DL should originate from this builder. - if (HasExplicitDL || !I->getDebugLoc()) + if (!I->getDebugLoc()) I->setDebugLoc(StoredDL.getCopied()); } diff --git a/llvm/include/llvm/Support/Signals.h b/llvm/include/llvm/Support/Signals.h index 85b6d57d1b848..126e04b25cec1 100644 --- a/llvm/include/llvm/Support/Signals.h +++ b/llvm/include/llvm/Support/Signals.h @@ -84,8 +84,6 @@ namespace sys { /// Takes a set of \p Addresses, symbolizes them and stores the result in the /// provided \p SymbolizedAddresses map. - /// NB: This is only intended to be used for introspection of LLVM by Debugify, will not be - /// enabled in release builds, and should not be relied on for other purposes. void symbolizeAddresses(AddressSet &Addresses, SymbolizedAddressMap &SymbolizedAddresses); #endif diff --git a/llvm/lib/IR/DebugLoc.cpp b/llvm/lib/IR/DebugLoc.cpp index 16f2862a6b5e6..a8fcbdf8b5353 100644 --- a/llvm/lib/IR/DebugLoc.cpp +++ b/llvm/lib/IR/DebugLoc.cpp @@ -6,7 +6,6 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/Hashing.h" #include "llvm/IR/DebugLoc.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/DebugInfo.h" @@ -17,127 +16,21 @@ using namespace llvm; -struct StacktraceOrList { - union { - std::array Single; - std::array STList; - }; - uint8_t Size : 7; - uint8_t IsList : 1; - StacktraceOrList(int Size, std::array STList) : STList(STList), Size(Size), IsList(0) {} - StacktraceOrList(int Size, std::array Single) : Single(Single), Size(Size), IsList(1) {} - StacktraceOrList(bool Tombstone = false) : Size(Tombstone ? 0x7F : 0), IsList(Tombstone ? 1 : 0) { - static_assert(DbgLocOriginStacktrace::MaxDepth < 0x7F, "Size of backtrace array must fit in 7 bits - 1"); - } -}; - -hash_code hash_value(const StacktraceOrList &S) { - static_assert(DbgLocOriginStacktrace::MaxDepth < (1 << 7)); - hash_code Result; - if (S.IsList) { - Result = hash_combine_range(S.Single.begin(), S.Single.begin() + S.Size); - } else { - Result = hash_combine_range(S.STList.begin(), S.STList.begin() + S.Size); - } - return Result; -} -namespace llvm { -template <> struct DenseMapInfo { - static inline StacktraceOrList getEmptyKey() { - return StacktraceOrList(); - } - - static inline StacktraceOrList getTombstoneKey() { - return StacktraceOrList(true); - } - - static unsigned getHashValue(const StacktraceOrList &Val) { - return hash_value(Val); - } - - static bool isEqual(const StacktraceOrList &LHS, const StacktraceOrList &RHS) { - if (LHS.IsList != RHS.IsList) - return false; - if (LHS.IsList) - return ArrayRef(LHS.Single.begin(), LHS.Single.begin() + LHS.Size) == ArrayRef(RHS.Single.begin(), RHS.Single.begin() + RHS.Size); - return ArrayRef(LHS.STList.begin(), LHS.STList.begin() + LHS.Size) == ArrayRef(RHS.STList.begin(), RHS.STList.begin() + RHS.Size); - } -}; -} - -// Storage for every unique stacktrace or list of stacktraces collected across this run of the program. -static std::vector CollectedStacktraces(1, StacktraceOrList()); -// Mapping from a unique stacktrace or list of stacktraces to an index in the CollectedStacktraces vector. -static DenseMap StacktraceStorageMap; - -size_t getIndex(const StacktraceOrList &S) { - // Special empty value that can't be inserted into the map. - if (S.Size == 0) - return 0; - auto [It, R] = StacktraceStorageMap.insert({S, CollectedStacktraces.size()}); - if (R) - CollectedStacktraces.push_back(S); - return It->second; -} -inline StacktraceOrList getStacktraceFromIndex(size_t Idx) { - return CollectedStacktraces[Idx]; -} -// Given an index to an existing stored stacktrace, and a new -size_t getIndexForAddedTrace(size_t Idx, StacktraceOrList S) { - size_t AddedIdx = getIndex(S); - if (Idx == 0) - return AddedIdx; - StacktraceOrList Current = getStacktraceFromIndex(Idx); - StacktraceOrList New; - if (Current.IsList) { - std::array STList = {Idx, AddedIdx}; - New = StacktraceOrList(2, STList); - } else { - // There is no way to represent a STList-backtrace containing more than MaxDepth - // backtraces, so just leave it unappended. - // FIXME: We could rotate it, so that we get the MaxDepth-most recent - // backtraces rather than the oldest? - if (Current.Size == DbgLocOriginStacktrace::MaxDepth) - return Idx; - New = StacktraceOrList(Current.Size + 1, Current.STList); - New.STList[Current.Size] = AddedIdx; - } - return getIndex(S); -} - - DILocAndCoverageTracking::DILocAndCoverageTracking(const DILocation *L) : TrackingMDNodeRef(const_cast(L)), Kind(DebugLocKind::Normal), Origin(!L) {} -DbgLocOriginStacktrace::DbgLocOriginStacktrace(bool ShouldCollectTrace) : StacktraceIdx(0) { - if (!ShouldCollectTrace) - return; - std::array Stacktrace; - int Depth = sys::getStackTrace(Stacktrace); - StacktraceIdx = getIndexForAddedTrace(StacktraceIdx, StacktraceOrList(Depth, Stacktrace)); +DbgLocOriginBacktrace::DbgLocOriginBacktrace(bool ShouldCollectTrace) { + if (ShouldCollectTrace) { + auto &[Depth, Stacktrace] = Stacktraces.emplace_back(); + Depth = sys::getStackTrace(Stacktrace); + } } -void DbgLocOriginStacktrace::addTrace() { - if (StacktraceIdx == 0) +void DbgLocOriginBacktrace::addTrace() { + if (Stacktraces.empty()) return; - std::array Stacktrace; - int Depth = sys::getStackTrace(Stacktrace); - StacktraceIdx = getIndex(StacktraceOrList(Depth, Stacktrace)); -} -SmallVector>, 0> DbgLocOriginStacktrace::getStacktraces() { - SmallVector>, 0> Stacktraces; - if (StacktraceIdx == 0) - return Stacktraces; - StacktraceOrList S = getStacktraceFromIndex(StacktraceIdx); - if (S.IsList) { - Stacktraces.push_back({(int)S.Size, S.Single}); - } else { - for (size_t SingleIdx : ArrayRef(S.STList.data(), S.Size)) { - StacktraceOrList SingleS = getStacktraceFromIndex(SingleIdx); - Stacktraces.push_back({(int)SingleS.Size, SingleS.Single}); - } - } - return Stacktraces; + auto &[Depth, Stacktrace] = Stacktraces.emplace_back(); + Depth = sys::getStackTrace(Stacktrace); } DebugLoc DebugLoc::getTemporary() { diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp index b22c56c0e7910..22826e4879bd8 100644 --- a/llvm/lib/IR/IRBuilder.cpp +++ b/llvm/lib/IR/IRBuilder.cpp @@ -65,10 +65,15 @@ DebugLoc IRBuilderBase::getCurrentDebugLocation() const { return StoredDL; } void IRBuilderBase::SetInstDebugLocation(Instruction *I) const { + for (const auto &KV : MetadataToCopy) + if (KV.first == LLVMContext::MD_dbg) { + I->setDebugLoc(StoredDL.getCopied()); + return; + } // If I does not have an existing DebugLoc and no DebugLoc has been set // here, we copy our DebugLoc to I anyway, because more likely than not I // is a new instruction whose DL should originate from this builder. - if (HasExplicitDL || !I->getDebugLoc()) + if (!I->getDebugLoc()) I->setDebugLoc(StoredDL.getCopied()); } diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp b/llvm/lib/Transforms/Utils/Debugify.cpp index dba6ae6fbdec2..f38d41c7f71ec 100644 --- a/llvm/lib/Transforms/Utils/Debugify.cpp +++ b/llvm/lib/Transforms/Utils/Debugify.cpp @@ -78,14 +78,13 @@ std::string symbolizeStacktrace(const Instruction *I) { sys::symbolizeAddresses(UnsymbolizedAddrs, SymbolizedAddrs); UnsymbolizedAddrs.clear(); } - DbgLocOriginStacktrace ST = I->getDebugLoc().getOrigin(); + DbgLocOriginBacktrace ST = I->getDebugLoc().getOrigin(); std::string Result; raw_string_ostream OS(Result); - auto Stacktraces = ST.getStacktraces(); - for (size_t TraceIdx = 0; TraceIdx < Stacktraces.size(); ++TraceIdx) { + for (size_t TraceIdx = 0; TraceIdx < ST.Stacktraces.size(); ++TraceIdx) { if (TraceIdx != 0) OS << "========================================\n"; - auto &[Depth, Stacktrace] = Stacktraces[TraceIdx]; + auto &[Depth, Stacktrace] = ST.Stacktraces[TraceIdx]; for (int Frame = 0; Frame < Depth; ++Frame) { assert(SymbolizedAddrs.contains(Stacktrace[Frame]) && "Expected each address to have been symbolized."); @@ -96,9 +95,8 @@ std::string symbolizeStacktrace(const Instruction *I) { return Result; } void collectStackAddresses(Instruction &I) { - DbgLocOriginStacktrace ST = I.getDebugLoc().getOrigin(); - auto Stacktraces = ST.getStacktraces(); - for (auto &[Depth, Stacktrace] : Stacktraces) { + DbgLocOriginBacktrace ST = I.getDebugLoc().getOrigin(); + for (auto &[Depth, Stacktrace] : ST.Stacktraces) { for (int Frame = 0; Frame < Depth; ++Frame) { void *Addr = Stacktrace[Frame]; if (!SymbolizedAddrs.contains(Addr)) From c9862be13ee82203d2b7ee6b56d9778614f93bdb Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Tue, 3 Sep 2024 17:01:39 +0000 Subject: [PATCH 13/15] Reapply some missing work --- llvm/include/llvm/IR/IRBuilder.h | 34 +++++++++++++------------------- llvm/lib/IR/IRBuilder.cpp | 7 +------ 2 files changed, 15 insertions(+), 26 deletions(-) diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h index 92ff0327b272b..751dea9b66830 100644 --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -90,17 +90,19 @@ class IRBuilderCallbackInserter : public IRBuilderDefaultInserter { /// Common base class shared among various IRBuilders. class IRBuilderBase { /// Pairs of (metadata kind, MDNode *) that should be added to all newly - /// created instructions, like !dbg metadata. + /// created instructions, excluding !dbg metadata, which is stored in the + // StoredDL field. SmallVector, 2> MetadataToCopy; - + // The DebugLoc that will be applied to instructions inserted by this builder. DebugLoc StoredDL; + // Tracks whether we have explicitly set a DebugLoc - valid or empty - in this + // builder, to determine whether to copy StoredDL to inserted instructions. + bool HasExplicitDL = false; /// Add or update the an entry (Kind, MD) to MetadataToCopy, if \p MD is not /// null. If \p MD is null, remove the entry with \p Kind. void AddOrRemoveMetadataToCopy(unsigned Kind, MDNode *MD) { - if (Kind == LLVMContext::MD_dbg) { - StoredDL = DebugLoc(MD); - } + assert(Kind != LLVMContext::MD_dbg && "MD_dbg metadata must be stored in StoredDL"); if (!MD) { erase_if(MetadataToCopy, [Kind](const std::pair &KV) { @@ -221,11 +223,10 @@ class IRBuilderBase { /// Set location information used by debugging information. void SetCurrentDebugLocation(DebugLoc L) { - AddOrRemoveMetadataToCopy(LLVMContext::MD_dbg, L.getAsMDNode()); - // Although we set StoredDL in the above call, we prefer to use the exact - // DebugLoc we were given, so overwrite it here; the call is only needed to - // update the entry in MetadataToCopy. + // For !dbg metadata attachments, we use DebugLoc instead of the raw MDNode + // to include optional introspection data for use in Debugify. StoredDL = std::move(L); + HasExplicitDL = true; } /// Set nosanitize metadata. @@ -240,9 +241,10 @@ class IRBuilderBase { void CollectMetadataToCopy(Instruction *Src, ArrayRef MetadataKinds) { for (unsigned K : MetadataKinds) { - AddOrRemoveMetadataToCopy(K, Src->getMetadata(K)); if (K == LLVMContext::MD_dbg) SetCurrentDebugLocation(Src->getDebugLoc()); + else + AddOrRemoveMetadataToCopy(K, Src->getMetadata(K)); } } @@ -255,20 +257,12 @@ class IRBuilderBase { /// Add all entries in MetadataToCopy to \p I. void AddMetadataToInst(Instruction *I) const { - for (const auto &KV : MetadataToCopy) { - if (KV.first == LLVMContext::MD_dbg) { - // If `!I->getDebugLoc()` then we will call this below anyway, so skip - // a duplicate call here. - if (I->getDebugLoc()) - I->setDebugLoc(StoredDL.getCopied()); - continue; - } + for (const auto &KV : MetadataToCopy) I->setMetadata(KV.first, KV.second); - } // If I does not have an existing DebugLoc and no DebugLoc has been set // here, we copy our DebugLoc to I anyway, because more likely than not I // is a new instruction whose DL should originate from this builder. - if (!I->getDebugLoc()) + if (HasExplicitDL || !I->getDebugLoc()) I->setDebugLoc(StoredDL.getCopied()); } diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp index 22826e4879bd8..b22c56c0e7910 100644 --- a/llvm/lib/IR/IRBuilder.cpp +++ b/llvm/lib/IR/IRBuilder.cpp @@ -65,15 +65,10 @@ DebugLoc IRBuilderBase::getCurrentDebugLocation() const { return StoredDL; } void IRBuilderBase::SetInstDebugLocation(Instruction *I) const { - for (const auto &KV : MetadataToCopy) - if (KV.first == LLVMContext::MD_dbg) { - I->setDebugLoc(StoredDL.getCopied()); - return; - } // If I does not have an existing DebugLoc and no DebugLoc has been set // here, we copy our DebugLoc to I anyway, because more likely than not I // is a new instruction whose DL should originate from this builder. - if (!I->getDebugLoc()) + if (HasExplicitDL || !I->getDebugLoc()) I->setDebugLoc(StoredDL.getCopied()); } From 1be10f66ba724591f3d4c591a10c50ca4209a4ad Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Tue, 3 Sep 2024 17:03:38 +0000 Subject: [PATCH 14/15] Missed a spot --- llvm/CMakeLists.txt | 2 -- llvm/include/llvm/Support/Signals.h | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index 6a283ea7d6d0d..2a404ba598feb 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -527,8 +527,6 @@ option(LLVM_ENABLE_CRASH_DUMPS "Turn on memory dumps on crashes. Currently only option(LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING "Enhance debugify's line number tracking at the cost of performance; abi-breaking." OFF) if(LLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING) set(ENABLE_DEBUGLOC_COVERAGE_TRACKING 1) -else() - set(ENABLE_DEBUGLOC_COVERAGE_TRACKING 0) endif() set(WINDOWS_PREFER_FORWARD_SLASH_DEFAULT OFF) diff --git a/llvm/include/llvm/Support/Signals.h b/llvm/include/llvm/Support/Signals.h index 126e04b25cec1..85b6d57d1b848 100644 --- a/llvm/include/llvm/Support/Signals.h +++ b/llvm/include/llvm/Support/Signals.h @@ -84,6 +84,8 @@ namespace sys { /// Takes a set of \p Addresses, symbolizes them and stores the result in the /// provided \p SymbolizedAddresses map. + /// NB: This is only intended to be used for introspection of LLVM by Debugify, will not be + /// enabled in release builds, and should not be relied on for other purposes. void symbolizeAddresses(AddressSet &Addresses, SymbolizedAddressMap &SymbolizedAddresses); #endif From 72906cdbb474e52820c8556bccd6179fb4a9d00c Mon Sep 17 00:00:00 2001 From: Stephen Tozer Date: Tue, 3 Sep 2024 17:04:32 +0000 Subject: [PATCH 15/15] clang-format --- clang/lib/CodeGen/BackendUtil.cpp | 4 ++-- .../GlobalISel/LegalizationArtifactCombiner.h | 4 ++-- llvm/include/llvm/IR/DebugLoc.h | 8 +++----- llvm/include/llvm/IR/IRBuilder.h | 3 ++- llvm/include/llvm/Support/Signals.h | 19 +++++++++++-------- llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp | 3 +-- llvm/lib/IR/DebugLoc.cpp | 12 +++--------- llvm/lib/IR/IRBuilder.cpp | 4 +--- llvm/lib/Support/Signals.cpp | 4 ++-- llvm/lib/Support/Unix/Signals.inc | 5 ++--- llvm/lib/Support/Windows/Signals.inc | 8 +++++--- .../Target/BPF/BPFPreserveStaticOffset.cpp | 3 ++- .../InstCombineLoadStoreAlloca.cpp | 4 ++-- llvm/lib/Transforms/Utils/Debugify.cpp | 4 ++-- 14 files changed, 40 insertions(+), 45 deletions(-) diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index c860839bab846..88f86bfd62c06 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -913,10 +913,10 @@ void EmitAssemblyHelper::RunOptimizationPipeline( CodeGenOpts.DIBugsReportFilePath); std::error_code EC; raw_fd_ostream OS_FILE{CodeGenOpts.DIBugsReportFilePath, EC, - sys::fs::OF_Append | sys::fs::OF_TextWithCRLF}; + sys::fs::OF_Append | sys::fs::OF_TextWithCRLF}; if (EC) { errs() << "Could not open file: " << EC.message() << ", " - << CodeGenOpts.DIBugsReportFilePath << '\n'; + << CodeGenOpts.DIBugsReportFilePath << '\n'; } else { if (auto L = OS_FILE.lock()) { OS_FILE << CodeGenOpts.DIBugsReportArgString; diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h index e5ad976ecd3ce..f7bbcb8d52696 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h @@ -100,8 +100,8 @@ class LegalizationArtifactCombiner { const LLT DstTy = MRI.getType(DstReg); if (isInstLegal({TargetOpcode::G_CONSTANT, {DstTy}})) { auto &CstVal = SrcMI->getOperand(1); - auto MergedLocation = DebugLoc::getMergedLocation( - MI.getDebugLoc(), SrcMI->getDebugLoc()); + auto MergedLocation = + DebugLoc::getMergedLocation(MI.getDebugLoc(), SrcMI->getDebugLoc()); // Set the debug location to the merged location of the SrcMI and the MI // if the aext fold is successful. Builder.setDebugLoc(MergedLocation); diff --git a/llvm/include/llvm/IR/DebugLoc.h b/llvm/include/llvm/IR/DebugLoc.h index 176795d24f894..b4ff0d9929183 100644 --- a/llvm/include/llvm/IR/DebugLoc.h +++ b/llvm/include/llvm/IR/DebugLoc.h @@ -60,8 +60,8 @@ namespace llvm { // normal empty DebugLoc, so only collect the stack trace in those cases. DbgLocOriginBacktrace Origin; DILocAndCoverageTracking(bool NeedsStacktrace = true) - : TrackingMDNodeRef(nullptr), Kind(DebugLocKind::Normal), Origin(NeedsStacktrace) { - } + : TrackingMDNodeRef(nullptr), Kind(DebugLocKind::Normal), + Origin(NeedsStacktrace) {} // Valid or nullptr MDNode*, normal DebugLocKind DILocAndCoverageTracking(const MDNode *Loc) : TrackingMDNodeRef(const_cast(Loc)), @@ -127,9 +127,7 @@ namespace llvm { return NewDL; } #else - DebugLoc getCopied() const { - return *this; - } + DebugLoc getCopied() const { return *this; } #endif static DebugLoc getTemporary(); diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h index 751dea9b66830..337fca49f8d9d 100644 --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -102,7 +102,8 @@ class IRBuilderBase { /// Add or update the an entry (Kind, MD) to MetadataToCopy, if \p MD is not /// null. If \p MD is null, remove the entry with \p Kind. void AddOrRemoveMetadataToCopy(unsigned Kind, MDNode *MD) { - assert(Kind != LLVMContext::MD_dbg && "MD_dbg metadata must be stored in StoredDL"); + assert(Kind != LLVMContext::MD_dbg && + "MD_dbg metadata must be stored in StoredDL"); if (!MD) { erase_if(MetadataToCopy, [Kind](const std::pair &KV) { diff --git a/llvm/include/llvm/Support/Signals.h b/llvm/include/llvm/Support/Signals.h index 85b6d57d1b848..113f9cdf1a723 100644 --- a/llvm/include/llvm/Support/Signals.h +++ b/llvm/include/llvm/Support/Signals.h @@ -75,17 +75,20 @@ namespace sys { #ifdef NDEBUG #error DebugLoc Coverage Tracking should not be enabled in Release builds. #endif - /// Populates the given array with a stacktrace of the current program, up to MaxDepth frames. - /// Returns the number of frames returned, which will be inserted into \p StackTrace from index 0. - /// All entries after the returned depth will be unmodified. - /// NB: This is only intended to be used for introspection of LLVM by Debugify, will not be - /// enabled in release builds, and should not be relied on for other purposes. - template int getStackTrace(std::array &StackTrace); + /// Populates the given array with a stacktrace of the current program, up to + /// MaxDepth frames. Returns the number of frames returned, which will be + /// inserted into \p StackTrace from index 0. All entries after the returned + /// depth will be unmodified. NB: This is only intended to be used for + /// introspection of LLVM by Debugify, will not be enabled in release builds, + /// and should not be relied on for other purposes. + template + int getStackTrace(std::array &StackTrace); /// Takes a set of \p Addresses, symbolizes them and stores the result in the /// provided \p SymbolizedAddresses map. - /// NB: This is only intended to be used for introspection of LLVM by Debugify, will not be - /// enabled in release builds, and should not be relied on for other purposes. + /// NB: This is only intended to be used for introspection of LLVM by + /// Debugify, will not be enabled in release builds, and should not be relied + /// on for other purposes. void symbolizeAddresses(AddressSet &Addresses, SymbolizedAddressMap &SymbolizedAddresses); #endif diff --git a/llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp index f546003064c37..b8f0bf76ed011 100644 --- a/llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp @@ -53,8 +53,7 @@ CSEMIRBuilder::getDominatingInstrForID(FoldingSetNodeID &ID, } else if (!dominates(MI, CurrPos)) { // Update the spliced machineinstr's debug location by merging it with the // debug location of the instruction at the insertion point. - auto Loc = DebugLoc::getMergedLocation(getDebugLoc(), - MI->getDebugLoc()); + auto Loc = DebugLoc::getMergedLocation(getDebugLoc(), MI->getDebugLoc()); MI->setDebugLoc(Loc); CurMBB->splice(CurrPos, CurMBB, MI); } diff --git a/llvm/lib/IR/DebugLoc.cpp b/llvm/lib/IR/DebugLoc.cpp index a8fcbdf8b5353..1f5c73015b92a 100644 --- a/llvm/lib/IR/DebugLoc.cpp +++ b/llvm/lib/IR/DebugLoc.cpp @@ -33,15 +33,9 @@ void DbgLocOriginBacktrace::addTrace() { Depth = sys::getStackTrace(Stacktrace); } -DebugLoc DebugLoc::getTemporary() { - return DebugLoc(DebugLocKind::Temporary); -} -DebugLoc DebugLoc::getUnknown() { - return DebugLoc(DebugLocKind::Unknown); -} -DebugLoc DebugLoc::getLineZero() { - return DebugLoc(DebugLocKind::LineZero); -} +DebugLoc DebugLoc::getTemporary() { return DebugLoc(DebugLocKind::Temporary); } +DebugLoc DebugLoc::getUnknown() { return DebugLoc(DebugLocKind::Unknown); } +DebugLoc DebugLoc::getLineZero() { return DebugLoc(DebugLocKind::LineZero); } #else diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp index b22c56c0e7910..88cd401019156 100644 --- a/llvm/lib/IR/IRBuilder.cpp +++ b/llvm/lib/IR/IRBuilder.cpp @@ -61,9 +61,7 @@ Type *IRBuilderBase::getCurrentFunctionReturnType() const { return BB->getParent()->getReturnType(); } -DebugLoc IRBuilderBase::getCurrentDebugLocation() const { - return StoredDL; -} +DebugLoc IRBuilderBase::getCurrentDebugLocation() const { return StoredDL; } void IRBuilderBase::SetInstDebugLocation(Instruction *I) const { // If I does not have an existing DebugLoc and no DebugLoc has been set // here, we copy our DebugLoc to I anyway, because more likely than not I diff --git a/llvm/lib/Support/Signals.cpp b/llvm/lib/Support/Signals.cpp index cad76a4702164..df23afda6d583 100644 --- a/llvm/lib/Support/Signals.cpp +++ b/llvm/lib/Support/Signals.cpp @@ -274,8 +274,8 @@ void sys::symbolizeAddresses(AddressSet &Addresses, } if (!LLVMSymbolizerPathOrErr) LLVMSymbolizerPathOrErr = sys::findProgramByName("llvm-symbolizer"); - assert(!!LLVMSymbolizerPathOrErr - && "Debugify origin stacktraces require llvm-symbolizer."); + assert(!!LLVMSymbolizerPathOrErr && + "Debugify origin stacktraces require llvm-symbolizer."); const std::string &LLVMSymbolizerPath = *LLVMSymbolizerPathOrErr; // Try to guess the main executable name, since we don't have argv0 available diff --git a/llvm/lib/Support/Unix/Signals.inc b/llvm/lib/Support/Unix/Signals.inc index 098a1f2c45bd2..913bacfe44803 100644 --- a/llvm/lib/Support/Unix/Signals.inc +++ b/llvm/lib/Support/Unix/Signals.inc @@ -499,7 +499,6 @@ static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) { return 0; } - #if ENABLE_DEBUGLOC_COVERAGE_TRACKING namespace llvm { namespace sys { @@ -509,8 +508,8 @@ int getStackTrace(std::array &StackTrace) { } template int getStackTrace<8ul>(std::array &); template int getStackTrace<16ul>(std::array &); -} -} +} // namespace sys +} // namespace llvm #endif /// If this is an ELF platform, we can find all loaded modules and their virtual diff --git a/llvm/lib/Support/Windows/Signals.inc b/llvm/lib/Support/Windows/Signals.inc index 6e37c5739dc6e..b385c226af865 100644 --- a/llvm/lib/Support/Windows/Signals.inc +++ b/llvm/lib/Support/Windows/Signals.inc @@ -574,7 +574,9 @@ int getStackTrace(std::array &StackTrace) { // It's possible that DbgHelp.dll hasn't been loaded yet (e.g. if this // function is called before the main program called `llvm::InitLLVM`). // In this case just return, not stacktrace will be printed. - assert(isDebugHelpInitialized() && "getStackTrace must not be called before DbgHelp.dll has been loaded."); + assert( + isDebugHelpInitialized() && + "getStackTrace must not be called before DbgHelp.dll has been loaded."); // Initialize the symbol handler. fSymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES); @@ -594,8 +596,8 @@ int getStackTrace(std::array &StackTrace) { } template int llvm::sys::getStackTrace<8ul>(std::array &); template int llvm::sys::getStackTrace<16ul>(std::array &); -} -} +} // namespace sys +} // namespace llvm #endif static void LocalPrintStackTrace(raw_ostream &OS, PCONTEXT C) { diff --git a/llvm/lib/Target/BPF/BPFPreserveStaticOffset.cpp b/llvm/lib/Target/BPF/BPFPreserveStaticOffset.cpp index e843b4eed186b..7bdeb3f744a63 100644 --- a/llvm/lib/Target/BPF/BPFPreserveStaticOffset.cpp +++ b/llvm/lib/Target/BPF/BPFPreserveStaticOffset.cpp @@ -228,7 +228,8 @@ static Instruction *makeGEPAndLoad(Module *M, GEPChainInfo &GEP, CallInst *Call = makeIntrinsicCall(M, Intrinsic::bpf_getelementptr_and_load, {Load->getType()}, Args); setParamElementType(Call, 0, GEP.SourceElementType); - Call->applyMergedLocation(DebugLoc(mergeDILocations(GEP.Members)), Load->getDebugLoc()); + Call->applyMergedLocation(DebugLoc(mergeDILocations(GEP.Members)), + Load->getDebugLoc()); Call->setName((*GEP.Members.rbegin())->getName()); if (Load->isUnordered()) { Call->setOnlyReadsMemory(); diff --git a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp index e0dcc9b8d04f9..1bafcda612b05 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -1574,8 +1574,8 @@ bool InstCombinerImpl::mergeStoreIntoSuccessor(StoreInst &SI) { // Insert a PHI node now if we need it. Value *MergedVal = OtherStore->getValueOperand(); // The debug locations of the original instructions might differ. Merge them. - DebugLoc MergedLoc = DebugLoc::getMergedLocation(SI.getDebugLoc(), - OtherStore->getDebugLoc()); + DebugLoc MergedLoc = + DebugLoc::getMergedLocation(SI.getDebugLoc(), OtherStore->getDebugLoc()); if (MergedVal != SI.getValueOperand()) { PHINode *PN = PHINode::Create(SI.getValueOperand()->getType(), 2, "storemerge"); diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp b/llvm/lib/Transforms/Utils/Debugify.cpp index f38d41c7f71ec..3cb4a6dc2af60 100644 --- a/llvm/lib/Transforms/Utils/Debugify.cpp +++ b/llvm/lib/Transforms/Utils/Debugify.cpp @@ -87,9 +87,9 @@ std::string symbolizeStacktrace(const Instruction *I) { auto &[Depth, Stacktrace] = ST.Stacktraces[TraceIdx]; for (int Frame = 0; Frame < Depth; ++Frame) { assert(SymbolizedAddrs.contains(Stacktrace[Frame]) && - "Expected each address to have been symbolized."); + "Expected each address to have been symbolized."); OS << right_justify(formatv("#{0}", Frame).str(), std::log10(Depth) + 2) - << ' ' << SymbolizedAddrs[Stacktrace[Frame]]; + << ' ' << SymbolizedAddrs[Stacktrace[Frame]]; } } return Result;
{}
{0}
{0}{0}