diff --git a/llvm/docs/HowToUpdateDebugInfo.rst b/llvm/docs/HowToUpdateDebugInfo.rst index a87efe7e6e43f..c3262a96b62e4 100644 --- a/llvm/docs/HowToUpdateDebugInfo.rst +++ b/llvm/docs/HowToUpdateDebugInfo.rst @@ -420,7 +420,41 @@ tests. Changes to this pass are not allowed to break existing tests. check lines. In cases where this can't be avoided (say, if a test wouldn't be precise enough), moving the test to its own file is preferred. -.. _MIRDebugify: +Using Coverage Tracking to remove false positives +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +As described :ref:`above`, there are valid reasons for +instructions to not have source locations. Therefore, when detecting dropped or +not-generated source locations, it may be preferable to avoid detecting cases +where the missing source location is intentional. For this, you can use the +"coverage tracking" feature in LLVM to prevent these from appearing in the +``debugify`` output. This is enabled in a build of LLVM by setting the CMake +flag ``-DLLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING=COVERAGE``. When this has been +set, LLVM will enable runtime tracking of +:ref:`DebugLoc annotations`, allowing ``debugify`` to ignore +instructions that have an explicitly recorded reason given for not having a +source location. + +For triaging source location bugs detected with ``debugify``, you may find it +helpful to instead set the CMake flag to enable "origin tracking", +``-DLLVM_ENABLE_DEBUGLOC_COVERAGE_TRACKING=COVERAGE_AND_ORIGIN``. This flag adds +more detail to ``debugify``'s output, by including one or more stacktraces with +every missing source location, capturing the point at which the empty source +location was created, and every point at which it was copied to an instruction, +making it trivial in most cases to find the origin of the underlying bug. If +using origin tracking, it is recommended to also build LLVM with debug info +enabled, so that the stacktrace can be accurately symbolized. + +.. note:: + + The coverage tracking feature has been designed primarily for use with the + :ref:`original debug info preservation` mode of ``debugify``, and + so may not be reliable in other settings. When using this mode, the + stacktraces produced by the ``COVERAGE_AND_ORIGIN`` setting will be printed + in an easy-to-read format as part of the reports generated by the + ``llvm-original-di-preservation.py`` script. + +.. _OriginalDI: Test original debug info preservation in optimizations ------------------------------------------------------ @@ -478,6 +512,8 @@ as follows: Please do note that there are some known false positives, for source locations and debug record checking, so that will be addressed as a future work. +.. _MIRDebugify: + Mutation testing for MIR-level transformations ---------------------------------------------- diff --git a/llvm/include/llvm/Support/Signals.h b/llvm/include/llvm/Support/Signals.h index 5969a0a6b230b..21b425fffef53 100644 --- a/llvm/include/llvm/Support/Signals.h +++ b/llvm/include/llvm/Support/Signals.h @@ -26,10 +26,8 @@ namespace llvm { // Typedefs that are convenient but only used by the stack-trace-collection code // added if DebugLoc origin-tracking is enabled. -using AddressSet = DenseSet>; -using SymbolizedAddressMap = - DenseMap, DenseMapInfo, - detail::DenseMapPair>>; +using AddressSet = DenseSet; +using SymbolizedAddressMap = DenseMap>; } // namespace llvm #endif diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp b/llvm/lib/Transforms/Utils/Debugify.cpp index 5f70bc442d2f0..a1f030a336c15 100644 --- a/llvm/lib/Transforms/Utils/Debugify.cpp +++ b/llvm/lib/Transforms/Utils/Debugify.cpp @@ -16,8 +16,10 @@ #include "llvm/Transforms/Utils/Debugify.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Config/llvm-config.h" #include "llvm/IR/DIBuilder.h" #include "llvm/IR/DebugInfo.h" +#include "llvm/IR/DebugLoc.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" @@ -28,6 +30,11 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/JSON.h" #include +#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN +// We need the Signals header to operate on stacktraces if we're using DebugLoc +// origin-tracking. +#include "llvm/Support/Signals.h" +#endif #define DEBUG_TYPE "debugify" @@ -59,6 +66,54 @@ cl::opt DebugifyLevel( raw_ostream &dbg() { return Quiet ? nulls() : errs(); } +#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN +// These maps refer to addresses in the current LLVM process, so we can reuse +// them everywhere - therefore, we store them at file scope. +static SymbolizedAddressMap SymbolizedAddrs; +static AddressSet 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(); + } + const DbgLocOrigin::StackTracesTy &OriginStackTraces = + I->getDebugLoc().getOriginStackTraces(); + std::string Result; + raw_string_ostream OS(Result); + for (size_t TraceIdx = 0; TraceIdx < OriginStackTraces.size(); ++TraceIdx) { + if (TraceIdx != 0) + OS << "========================================\n"; + auto &[Depth, StackTrace] = OriginStackTraces[TraceIdx]; + unsigned VirtualFrameNo = 0; + for (int Frame = 0; Frame < Depth; ++Frame) { + assert(SymbolizedAddrs.contains(StackTrace[Frame]) && + "Expected each address to have been symbolized."); + for (std::string &SymbolizedFrame : SymbolizedAddrs[StackTrace[Frame]]) { + OS << right_justify(formatv("#{0}", VirtualFrameNo++).str(), + std::log10(Depth) + 2) + << ' ' << SymbolizedFrame << '\n'; + } + } + } + return Result; +} +void collectStackAddresses(Instruction &I) { + auto &OriginStackTraces = I.getDebugLoc().getOriginStackTraces(); + for (auto &[Depth, StackTrace] : OriginStackTraces) { + for (int Frame = 0; Frame < Depth; ++Frame) { + void *Addr = StackTrace[Frame]; + if (!SymbolizedAddrs.contains(Addr)) + UnsymbolizedAddrs.insert(Addr); + } + } +} +#else +void collectStackAddresses(Instruction &I) {} +#endif // LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN + uint64_t getAllocSizeInBits(Module &M, Type *Ty) { return Ty->isSized() ? M.getDataLayout().getTypeAllocSizeInBits(Ty) : 0; } @@ -375,6 +430,8 @@ bool llvm::collectDebugInfoMetadata(Module &M, LLVM_DEBUG(dbgs() << " Collecting info for inst: " << I << '\n'); DebugInfoBeforePass.InstToDelete.insert({&I, &I}); + // Track the addresses to symbolize, if the feature is enabled. + collectStackAddresses(I); DebugInfoBeforePass.DILocations.insert({&I, hasLoc(I)}); } } @@ -450,14 +507,23 @@ static bool checkInstructions(const DebugInstMap &DILocsBefore, auto BBName = BB->hasName() ? BB->getName() : "no-name"; auto InstName = Instruction::getOpcodeName(Instr->getOpcode()); + auto CreateJSONBugEntry = [&](const char *Action) { + Bugs.push_back(llvm::json::Object({ + {"metadata", "DILocation"}, + {"fn-name", FnName.str()}, + {"bb-name", BBName.str()}, + {"instr", InstName}, + {"action", Action}, +#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN + {"origin", symbolizeStackTrace(Instr)}, +#endif + })); + }; + 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"}})); + CreateJSONBugEntry("not-generate"); else dbg() << "WARNING: " << NameOfWrappedPass << " did not generate DILocation for " << *Instr @@ -470,11 +536,7 @@ 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"}})); + CreateJSONBugEntry("drop"); else dbg() << "WARNING: " << NameOfWrappedPass << " dropped DILocation of " << *Instr << " (BB: " << BBName << ", Fn: " << FnName @@ -612,6 +674,8 @@ bool llvm::checkDebugInfoMetadata(Module &M, LLVM_DEBUG(dbgs() << " Collecting info for inst: " << I << '\n'); + // Track the addresses to symbolize, if the feature is enabled. + collectStackAddresses(I); DebugInfoAfterPass.DILocations.insert({&I, hasLoc(I)}); } } diff --git a/llvm/test/tools/llvm-original-di-preservation/Inputs/expected-origin.html b/llvm/test/tools/llvm-original-di-preservation/Inputs/expected-origin.html new file mode 100644 index 0000000000000..ed08c850cb4ad --- /dev/null +++ b/llvm/test/tools/llvm-original-di-preservation/Inputs/expected-origin.html @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Location Bugs found by the Debugify
FileLLVM Pass NameLLVM IR InstructionFunction NameBasic Block NameActionOrigin
test.llLoopVectorizePassaddfnno-namenot-generate
View Origin StackTrace
Stack Trace 0:
+ #0 0x00005895d035c935 llvm::DbgLocOrigin::DbgLocOrigin(bool) /tmp/llvm-project/llvm/lib/IR/DebugLoc.cpp:22:9
+ #1 0x00005895d03af013 llvm::DILocAndCoverageTracking::DILocAndCoverageTracking() /tmp/llvm-project/llvm/include/llvm/IR/DebugLoc.h:90:11
+ #2 0x00005895d03af013 llvm::DebugLoc::DebugLoc() /tmp/llvm-project/llvm/include/llvm/IR/DebugLoc.h:133:5
+ #3 0x00005895d03af013 llvm::Instruction::Instruction(llvm::Type*, unsigned int, llvm::User::AllocInfo, llvm::InsertPosition) /tmp/llvm-project/llvm/lib/IR/Instruction.cpp:37:14
+ #4 0x00005895d06862b5 llvm::PHINode::PHINode(llvm::Type*, unsigned int, llvm::Twine const&, llvm::InsertPosition) /tmp/llvm-project/llvm/include/llvm/IR/Instructions.h:0:9
+ #5 0x00005895d06862b5 llvm::PHINode::Create(llvm::Type*, unsigned int, llvm::Twine const&, llvm::InsertPosition) /tmp/llvm-project/llvm/include/llvm/IR/Instructions.h:2651:9
+ #6 0x00005895d06862b5 llvm::InstCombinerImpl::foldPHIArgGEPIntoPHI(llvm::PHINode&) /tmp/llvm-project/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp:617:9
+ #7 0x00005895d0688fe0 llvm::InstCombinerImpl::visitPHINode(llvm::PHINode&) /tmp/llvm-project/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp:1456:22
+ #8 0x00005895d05cd21f llvm::InstCombinerImpl::run() /tmp/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp:5327:22
+ #9 0x00005895d05d067e combineInstructionsOverFunction(llvm::Function&, llvm::InstructionWorklist&, llvm::AAResults*, llvm::AssumptionCache&, llvm::TargetLibraryInfo&, llvm::TargetTransformInfo&, llvm::DominatorTree&, llvm::OptimizationRemarkEmitter&, llvm::BlockFrequencyInfo*, llvm::BranchProbabilityInfo*, llvm::ProfileSummaryInfo*, llvm::InstCombineOptions const&) /tmp/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp:5643:31
+#10 0x00005895d05cf9a9 llvm::InstCombinePass::run(llvm::Function&, llvm::AnalysisManager&) /tmp/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp:5706:8
+#11 0x00005895d107d07d llvm::detail::PassModel>::run(llvm::Function&, llvm::AnalysisManager&) /tmp/llvm-project/llvm/include/llvm/IR/PassManagerInternal.h:91:5
+#12 0x00005895d04204a7 llvm::PassManager>::run(llvm::Function&, llvm::AnalysisManager&) /tmp/llvm-project/llvm/include/llvm/IR/PassManagerImpl.h:85:8
+#13 0x00005895ce4cb09d llvm::detail::PassModel>, llvm::AnalysisManager>::run(llvm::Function&, llvm::AnalysisManager&) /tmp/llvm-project/llvm/include/llvm/IR/PassManagerInternal.h:91:5
+#14 0x00005895cfae2865 llvm::CGSCCToFunctionPassAdaptor::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) /tmp/llvm-project/llvm/lib/Analysis/CGSCCPassManager.cpp:0:38
+#15 0x00005895ce4cad5d llvm::detail::PassModel, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) /tmp/llvm-project/llvm/include/llvm/IR/PassManagerInternal.h:91:5
+#16 0x00005895cfade813 llvm::PassManager, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) /tmp/llvm-project/llvm/lib/Analysis/CGSCCPassManager.cpp:93:12
+#17 0x00005895d1e3968d llvm::detail::PassModel, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>, llvm::AnalysisManager, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) /tmp/llvm-project/llvm/include/llvm/IR/PassManagerInternal.h:91:5
+#18 0x00005895cfae1224 llvm::DevirtSCCRepeatedPass::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) /tmp/llvm-project/llvm/lib/Analysis/CGSCCPassManager.cpp:0:38
+#19 0x00005895d1e5067d llvm::detail::PassModel, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) /tmp/llvm-project/llvm/include/llvm/IR/PassManagerInternal.h:91:5
+
+ + + + + + + + + + + +
Summary of Location Bugs
LLVM Pass NameNumber of bugs
LoopVectorizePass1
+
+
+ + + + + + + + + + + +
SP Bugs found by the Debugify
FileLLVM Pass NameFunction NameAction
No bugs found
+
+ + + + + + + + + + +
Summary of SP Bugs
LLVM Pass NameNumber of bugs
No bugs found
+
+
+ + + + + + + + + + + + +
Variable Location Bugs found by the Debugify
FileLLVM Pass NameVariableFunctionAction
No bugs found
+
+ + + + + + + + + + +
Summary of Variable Location Bugs
LLVM Pass NameNumber of bugs
No bugs found
+ + \ No newline at end of file diff --git a/llvm/test/tools/llvm-original-di-preservation/Inputs/expected-skipped.html b/llvm/test/tools/llvm-original-di-preservation/Inputs/expected-skipped.html index f70ebbf86b0a2..d8941cbdedbef 100644 --- a/llvm/test/tools/llvm-original-di-preservation/Inputs/expected-skipped.html +++ b/llvm/test/tools/llvm-original-di-preservation/Inputs/expected-skipped.html @@ -128,6 +128,15 @@ drop + + + wrstabs.c + Simplify the CFG + tindex + stab_bool_type + drop + + prdbg.c diff --git a/llvm/test/tools/llvm-original-di-preservation/Inputs/origin.json b/llvm/test/tools/llvm-original-di-preservation/Inputs/origin.json new file mode 100644 index 0000000000000..ab59bc295add1 --- /dev/null +++ b/llvm/test/tools/llvm-original-di-preservation/Inputs/origin.json @@ -0,0 +1 @@ +{"file":"test.ll", "pass":"LoopVectorizePass", "bugs": [[{"action":"not-generate","bb-name":"no-name","fn-name":"fn","instr":"add","metadata":"DILocation", "origin": "Stack Trace 0:\n #0 0x00005895d035c935 llvm::DbgLocOrigin::DbgLocOrigin(bool) /tmp/llvm-project/llvm/lib/IR/DebugLoc.cpp:22:9\n #1 0x00005895d03af013 llvm::DILocAndCoverageTracking::DILocAndCoverageTracking() /tmp/llvm-project/llvm/include/llvm/IR/DebugLoc.h:90:11\n #2 0x00005895d03af013 llvm::DebugLoc::DebugLoc() /tmp/llvm-project/llvm/include/llvm/IR/DebugLoc.h:133:5\n #3 0x00005895d03af013 llvm::Instruction::Instruction(llvm::Type*, unsigned int, llvm::User::AllocInfo, llvm::InsertPosition) /tmp/llvm-project/llvm/lib/IR/Instruction.cpp:37:14\n #4 0x00005895d06862b5 llvm::PHINode::PHINode(llvm::Type*, unsigned int, llvm::Twine const&, llvm::InsertPosition) /tmp/llvm-project/llvm/include/llvm/IR/Instructions.h:0:9\n #5 0x00005895d06862b5 llvm::PHINode::Create(llvm::Type*, unsigned int, llvm::Twine const&, llvm::InsertPosition) /tmp/llvm-project/llvm/include/llvm/IR/Instructions.h:2651:9\n #6 0x00005895d06862b5 llvm::InstCombinerImpl::foldPHIArgGEPIntoPHI(llvm::PHINode&) /tmp/llvm-project/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp:617:9\n #7 0x00005895d0688fe0 llvm::InstCombinerImpl::visitPHINode(llvm::PHINode&) /tmp/llvm-project/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp:1456:22\n #8 0x00005895d05cd21f llvm::InstCombinerImpl::run() /tmp/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp:5327:22\n #9 0x00005895d05d067e combineInstructionsOverFunction(llvm::Function&, llvm::InstructionWorklist&, llvm::AAResults*, llvm::AssumptionCache&, llvm::TargetLibraryInfo&, llvm::TargetTransformInfo&, llvm::DominatorTree&, llvm::OptimizationRemarkEmitter&, llvm::BlockFrequencyInfo*, llvm::BranchProbabilityInfo*, llvm::ProfileSummaryInfo*, llvm::InstCombineOptions const&) /tmp/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp:5643:31\n#10 0x00005895d05cf9a9 llvm::InstCombinePass::run(llvm::Function&, llvm::AnalysisManager&) /tmp/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp:5706:8\n#11 0x00005895d107d07d llvm::detail::PassModel>::run(llvm::Function&, llvm::AnalysisManager&) /tmp/llvm-project/llvm/include/llvm/IR/PassManagerInternal.h:91:5\n#12 0x00005895d04204a7 llvm::PassManager>::run(llvm::Function&, llvm::AnalysisManager&) /tmp/llvm-project/llvm/include/llvm/IR/PassManagerImpl.h:85:8\n#13 0x00005895ce4cb09d llvm::detail::PassModel>, llvm::AnalysisManager>::run(llvm::Function&, llvm::AnalysisManager&) /tmp/llvm-project/llvm/include/llvm/IR/PassManagerInternal.h:91:5\n#14 0x00005895cfae2865 llvm::CGSCCToFunctionPassAdaptor::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) /tmp/llvm-project/llvm/lib/Analysis/CGSCCPassManager.cpp:0:38\n#15 0x00005895ce4cad5d llvm::detail::PassModel, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) /tmp/llvm-project/llvm/include/llvm/IR/PassManagerInternal.h:91:5\n#16 0x00005895cfade813 llvm::PassManager, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) /tmp/llvm-project/llvm/lib/Analysis/CGSCCPassManager.cpp:93:12\n#17 0x00005895d1e3968d llvm::detail::PassModel, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>, llvm::AnalysisManager, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) /tmp/llvm-project/llvm/include/llvm/IR/PassManagerInternal.h:91:5\n#18 0x00005895cfae1224 llvm::DevirtSCCRepeatedPass::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) /tmp/llvm-project/llvm/lib/Analysis/CGSCCPassManager.cpp:0:38\n#19 0x00005895d1e5067d llvm::detail::PassModel, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) /tmp/llvm-project/llvm/include/llvm/IR/PassManagerInternal.h:91:5"}]]} diff --git a/llvm/test/tools/llvm-original-di-preservation/basic.test b/llvm/test/tools/llvm-original-di-preservation/basic.test index 81f987aa221bb..5ef670b42c667 100644 --- a/llvm/test/tools/llvm-original-di-preservation/basic.test +++ b/llvm/test/tools/llvm-original-di-preservation/basic.test @@ -1,5 +1,6 @@ RUN: %llvm-original-di-preservation %p/Inputs/sample.json %t.html | FileCheck %s RUN: diff -w %p/Inputs/expected-sample.html %t.html +CHECK: The {{.+}}.html generated. CHECK-NOT: Skipped lines: RUN: %llvm-original-di-preservation %p/Inputs/corrupted.json %t2.html | FileCheck %s -check-prefix=CORRUPTED @@ -9,5 +10,8 @@ CORRUPTED: Skipped bugs: 1 RUN: %llvm-original-di-preservation -compress %p/Inputs/sample.json %t3.html | FileCheck %s -check-prefix=COMPRESSED RUN: diff -w %p/Inputs/expected-compressed.html %t3.html +COMPRESSED: The {{.+}}.html generated. COMPRESSED-NOT: Skipped lines: +RUN: %llvm-original-di-preservation %p/Inputs/origin.json %t4.html | FileCheck %s +RUN: diff -w %p/Inputs/expected-origin.html %t4.html diff --git a/llvm/utils/llvm-original-di-preservation.py b/llvm/utils/llvm-original-di-preservation.py index dc1fa518ca8e6..03793b1136f8d 100755 --- a/llvm/utils/llvm-original-di-preservation.py +++ b/llvm/utils/llvm-original-di-preservation.py @@ -13,7 +13,8 @@ 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 @@ -79,6 +80,15 @@ def generate_html_report( table_title_di_loc ) + # If any DILocation bug has an origin stack trace, we emit an extra column in the table, which we must therefore + # determine up-front. + has_origin_col = any( + x.origin is not None + for per_file_bugs in di_location_bugs.values() + for per_pass_bugs in per_file_bugs.values() + for x in per_pass_bugs + ) + header_di_loc = [ "File", "LLVM Pass Name", @@ -87,6 +97,8 @@ def generate_html_report( "Basic Block Name", "Action", ] + if has_origin_col: + header_di_loc.append("Origin") for column in header_di_loc: table_di_loc += " {0}\n".format(column.strip()) @@ -112,6 +124,13 @@ def generate_html_report( row.append(x.fn_name) row.append(x.bb_name) row.append(x.action) + if has_origin_col: + if x.origin is not None: + row.append( + f"
View Origin StackTrace
{x.origin}
" + ) + else: + row.append("") row.append(" \n") # Dump the bugs info into the table. for column in row: @@ -428,9 +447,9 @@ def Main(): sys.exit(1) # 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() @@ -470,9 +489,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() @@ -487,6 +506,7 @@ def Main(): if bugs_metadata == "DILocation": try: + origin = bug.get("origin") action = bug["action"] bb_name = bug["bb-name"] fn_name = bug["fn-name"] @@ -494,7 +514,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: