15
15
16
16
#include " llvm/Transforms/Utils/Debugify.h"
17
17
#include " llvm/ADT/BitVector.h"
18
+ #include " llvm/ADT/DenseMap.h"
19
+ #include " llvm/ADT/DenseSet.h"
18
20
#include " llvm/ADT/StringExtras.h"
21
+ #include " llvm/Config/config.h"
19
22
#include " llvm/IR/DIBuilder.h"
20
23
#include " llvm/IR/DebugInfo.h"
21
24
#include " llvm/IR/InstIterator.h"
28
31
#include " llvm/Support/FileSystem.h"
29
32
#include " llvm/Support/JSON.h"
30
33
#include < optional>
34
+ #if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
35
+ // We need the Signals header to operate on stacktraces if we're using DebugLoc
36
+ // origin-tracking.
37
+ #include " llvm/Support/Signals.h"
38
+ #endif
31
39
32
40
#define DEBUG_TYPE " debugify"
33
41
@@ -59,6 +67,49 @@ cl::opt<Level> DebugifyLevel(
59
67
60
68
raw_ostream &dbg () { return Quiet ? nulls () : errs (); }
61
69
70
+ #if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
71
+ // These maps refer to addresses in this instance of LLVM, so we can reuse them
72
+ // everywhere - therefore, we store them at file scope.
73
+ static DenseMap<void *, std::string> SymbolizedAddrs;
74
+ static DenseSet<void *> UnsymbolizedAddrs;
75
+
76
+ std::string symbolizeStackTrace (const Instruction *I) {
77
+ // We flush the set of unsymbolized addresses at the latest possible moment,
78
+ // i.e. now.
79
+ if (!UnsymbolizedAddrs.empty ()) {
80
+ sys::symbolizeAddresses (UnsymbolizedAddrs, SymbolizedAddrs);
81
+ UnsymbolizedAddrs.clear ();
82
+ }
83
+ auto OriginStackTraces = I->getDebugLoc ().getOriginStackTraces ();
84
+ std::string Result;
85
+ raw_string_ostream OS (Result);
86
+ for (size_t TraceIdx = 0 ; TraceIdx < OriginStackTraces.size (); ++TraceIdx) {
87
+ if (TraceIdx != 0 )
88
+ OS << " ========================================\n " ;
89
+ auto &[Depth, StackTrace] = OriginStackTraces[TraceIdx];
90
+ for (int Frame = 0 ; Frame < Depth; ++Frame) {
91
+ assert (SymbolizedAddrs.contains (StackTrace[Frame]) &&
92
+ " Expected each address to have been symbolized." );
93
+ OS << right_justify (formatv (" #{0}" , Frame).str (), std::log10 (Depth) + 2 )
94
+ << ' ' << SymbolizedAddrs[StackTrace[Frame]];
95
+ }
96
+ }
97
+ return Result;
98
+ }
99
+ void collectStackAddresses (Instruction &I) {
100
+ auto &OriginStackTraces = I.getDebugLoc ().getOriginStackTraces ();
101
+ for (auto &[Depth, StackTrace] : OriginStackTraces) {
102
+ for (int Frame = 0 ; Frame < Depth; ++Frame) {
103
+ void *Addr = StackTrace[Frame];
104
+ if (!SymbolizedAddrs.contains (Addr))
105
+ UnsymbolizedAddrs.insert (Addr);
106
+ }
107
+ }
108
+ }
109
+ #else
110
+ void collectStackAddresses (Instruction &I) {}
111
+ #endif // LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
112
+
62
113
uint64_t getAllocSizeInBits (Module &M, Type *Ty) {
63
114
return Ty->isSized () ? M.getDataLayout ().getTypeAllocSizeInBits (Ty) : 0 ;
64
115
}
@@ -379,6 +430,8 @@ bool llvm::collectDebugInfoMetadata(Module &M,
379
430
LLVM_DEBUG (dbgs () << " Collecting info for inst: " << I << ' \n ' );
380
431
DebugInfoBeforePass.InstToDelete .insert ({&I, &I});
381
432
433
+ // Track the addresses to symbolize, if the feature is enabled.
434
+ collectStackAddresses (I);
382
435
DebugInfoBeforePass.DILocations .insert ({&I, hasLoc (I)});
383
436
}
384
437
}
@@ -454,14 +507,20 @@ static bool checkInstructions(const DebugInstMap &DILocsBefore,
454
507
auto BBName = BB->hasName () ? BB->getName () : " no-name" ;
455
508
auto InstName = Instruction::getOpcodeName (Instr->getOpcode ());
456
509
510
+ auto CreateJSONBugEntry = [&](const char *Action) {
511
+ Bugs.push_back (llvm::json::Object ({
512
+ {" metadata" , " DILocation" }, {" fn-name" , FnName.str ()},
513
+ {" bb-name" , BBName.str ()}, {" instr" , InstName}, {" action" , Action},
514
+ #if LLVM_ENABLE_DEBUGLOC_ORIGIN_TRACKING
515
+ {" origin" , symbolizeStackTrace (Instr)},
516
+ #endif
517
+ }));
518
+ };
519
+
457
520
auto InstrIt = DILocsBefore.find (Instr);
458
521
if (InstrIt == DILocsBefore.end ()) {
459
522
if (ShouldWriteIntoJSON)
460
- Bugs.push_back (llvm::json::Object ({{" metadata" , " DILocation" },
461
- {" fn-name" , FnName.str ()},
462
- {" bb-name" , BBName.str ()},
463
- {" instr" , InstName},
464
- {" action" , " not-generate" }}));
523
+ CreateJSONBugEntry (" not-generate" );
465
524
else
466
525
dbg () << " WARNING: " << NameOfWrappedPass
467
526
<< " did not generate DILocation for " << *Instr
@@ -474,11 +533,7 @@ static bool checkInstructions(const DebugInstMap &DILocsBefore,
474
533
// If the instr had the !dbg attached before the pass, consider it as
475
534
// a debug info issue.
476
535
if (ShouldWriteIntoJSON)
477
- Bugs.push_back (llvm::json::Object ({{" metadata" , " DILocation" },
478
- {" fn-name" , FnName.str ()},
479
- {" bb-name" , BBName.str ()},
480
- {" instr" , InstName},
481
- {" action" , " drop" }}));
536
+ CreateJSONBugEntry (" drop" );
482
537
else
483
538
dbg () << " WARNING: " << NameOfWrappedPass << " dropped DILocation of "
484
539
<< *Instr << " (BB: " << BBName << " , Fn: " << FnName
@@ -622,6 +677,8 @@ bool llvm::checkDebugInfoMetadata(Module &M,
622
677
623
678
LLVM_DEBUG (dbgs () << " Collecting info for inst: " << I << ' \n ' );
624
679
680
+ // Track the addresses to symbolize, if the feature is enabled.
681
+ collectStackAddresses (I);
625
682
DebugInfoAfterPass.DILocations .insert ({&I, hasLoc (I)});
626
683
}
627
684
}
0 commit comments