diff options
| author | blasty <peter@haxx.in> | 2026-08-06 15:11:54 +0200 |
|---|---|---|
| committer | blasty <peter@haxx.in> | 2026-08-06 15:11:54 +0200 |
| commit | 179c8f2ce7e25f61725f69e6e3a8f22dae2c32c9 (patch) | |
| tree | 7190465a3b3ac849c38a12ca80939a6c801e056d /server | |
| parent | README/TODO: literal formats (diff) | |
| download | ida-tui-179c8f2ce7e25f61725f69e6e3a8f22dae2c32c9.tar.gz ida-tui-179c8f2ce7e25f61725f69e6e3a8f22dae2c32c9.tar.xz ida-tui-179c8f2ce7e25f61725f69e6e3a8f22dae2c32c9.zip | |
graph: a layered CFG layout engine
Textbook Sugiyama, the same shape IDA's own graph uses: break cycles,
longest-path layering, dummy nodes, median/transposition ordering,
priority x-coords, then port-and-channel edge routing. Pure python -- no
IDA, no Textual, no I/O -- so it is tested offline in milliseconds with no
worker, which is the whole reason the hard part is kept out of the UI.
Dummy nodes are what make routing tractable: a long edge occupies real
horizontal space, so no edge ever has to cross a box. The tests assert
exactly that over a 128-function corpus, and it holds at 0.
Two things cost real time to find. A self-loop never drains its own
in-degree, so it deadlocks the ranking and collapses the graph into three
layers, 280 columns wide -- they are dropped from the layout and drawn as
a marker. And crossing minimisation is the entire runtime: recounting
globally per candidate swap is O(n^3) and took 20.4s on a 424-block
function, against 152ms for Fenwick inversion counting plus a local
O(deg*deg) swap delta.
The result is not a painted canvas -- that function is ~13M cells. It is
an index: per-row runs, bucketed vertical intervals, and point marks,
queried one row at a time.
Diffstat (limited to 'server')
0 files changed, 0 insertions, 0 deletions
