[llvm] [llvm-objdump] Add the --visualize-jumps option (PR #74858)

Nick Desaulniers via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 8 09:02:24 PST 2023


================
@@ -503,5 +506,194 @@ SourcePrinter::SourcePrinter(const object::ObjectFile *Obj,
   Symbolizer.reset(new symbolize::LLVMSymbolizer(SymbolizerOpts));
 }
 
+// TODO Light/dark shades? 256-color terminals?
+const raw_ostream::Colors LineColors[] = {
+  raw_ostream::RED,
+  raw_ostream::GREEN,
+  raw_ostream::YELLOW,
+  raw_ostream::BLUE,
+  raw_ostream::MAGENTA,
+  raw_ostream::CYAN,
+};
+
+void ControlFlowPrinter::addEdge(uint64_t From, uint64_t To) {
+  auto It = Targets.find(To);
+  if (It == Targets.end())
+    It = Targets.insert(std::make_pair(To, ControlFlowTarget(To, PickColor()))).first;
+  It->second.addSource(From);
+}
+
+void ControlFlowPrinter::finalise() {
+  if (!enabled()) {
+    setControlFlowColumnWidth(0);
+    return;
+  }
+
+  SmallVector<ControlFlowTarget *> SortedTargets;
+  for (auto &[Addr, Info] : Targets) {
+    SortedTargets.push_back(&Info);
+  }
+  std::sort(SortedTargets.begin(), SortedTargets.end(),
+            [](ControlFlowTarget *LHS, ControlFlowTarget *RHS) {
+              return LHS->Length() < RHS->Length();
+            });
+
+  // FIXME This is O(n^3) in the worst case, can we do better?
+  for (auto &T : SortedTargets) {
+    int Column = 0;
+    for (;; ++Column)
+      if (!std::any_of(SortedTargets.begin(), SortedTargets.end(),
+                       [T, Column](ControlFlowTarget *T2) {
+                         return T != T2 && T2->Column == Column &&
+                                T->Overlaps(*T2);
+                       }))
+        break;
+    T->Column = Column;
+    MaxColumn = std::max(MaxColumn, Column);
+
+#if 1
+    LLVM_DEBUG(
+      dbgs() << "Target: 0x" << Twine::utohexstr(T->Target) << " (" << T->Length()
+             << ") Column " << Column << ":\n";
+      for (auto Source : T->Sources)
+        dbgs() << "  Source: 0x" << Twine::utohexstr(Source) << "\n";
+    );
+#endif
+  }
+
+  setControlFlowColumnWidth(MaxColumn * 2 + 4);
+}
+
+const char *ControlFlowPrinter::getLineChar(LineChar C) const {
+  bool IsASCII =
+      (OutputMode & VisualizeJumpsMode::CharsMask) == VisualizeJumpsMode::CharsASCII;
+  switch (C) {
+  case LineChar::Horiz:
+    return IsASCII ? "-" : (const char *)u8"\u2500";
+  case LineChar::Vert:
+    return IsASCII ? "|" : (const char *)u8"\u2502";
+  case LineChar::TopCorner:
+    return IsASCII ? "/" : (const char *)u8"\u256d";
+  case LineChar::BottomCorner:
+    return IsASCII ? "\\" : (const char *)u8"\u2570";
+  case LineChar::Tee:
+    return IsASCII ? "+" : (const char *)u8"\u251c";
+  case LineChar::Arrow:
+    return ">";
+  }
+  llvm_unreachable("Unhandled LineChar enum");
+}
+
+#define C(id) getLineChar(LineChar::id)
+
+void ControlFlowPrinter::printInst(formatted_raw_ostream &OS,
+                                   uint64_t Addr) const {
+  if (!enabled())
+    return;
+
+  SmallVector<const ControlFlowTarget *, 8> Columns;
+  Columns.resize(MaxColumn + 1);
+  const ControlFlowTarget *Horizontal = nullptr;
+
+  IndentToColumn(STI, OS, DisassemblyColumn::ControlFlow);
+
+  // TODO: What happens if an instruction has both incoming and outgoing edges?
----------------
nickdesaulniers wrote:

so, a branch to a branch? isn't that what the Tee is used for?

https://github.com/llvm/llvm-project/pull/74858


More information about the llvm-commits mailing list