Argus.Cfg (Panoptes v0.13.0)

Copy Markdown View Source

Basic-block control-flow graphs derived from Layer-1 facts, with dominators and loop headers.

Built per module from the instruction/label_at/jump/branch/ select_branch facts, so the graph is memoized with the module's extraction rather than re-derived on every solve: instructions are grouped into maximal straight-line blocks (the classic leader algorithm), edges carry their kind (Argus.Cfg.Block.edge_kind/0), and each function gets a dominator tree (iterative Cooper–Harvey–Kennedy over reverse postorder) and the set of natural-loop headers (back-edge targets).

The entry block is the one holding the function's entry label from function_def — not instruction 0, which is the func_info failure landing pad that never falls through.

Known imprecision, by design: a call to erlang:raise/erlang:error is an ordinary call followed by a (never-taken) fallthrough edge — fail-edge and terminator classification is fact-driven, not BIF-name-driven.

Summary

Functions

Build per-function CFGs from typed facts (Argus.Pipeline.extract/2 with format: :typed).

The graph of one function of a module given as disassembly (%{module: ..., functions: ...}), built from the facts the emitter would produce. What an extractor uses when it was handed bare disassembly rather than a pipeline module whose graphs are already attached.

Functions

build(facts)

@spec build(Argus.Facts.t()) :: %{
  required({String.t(), non_neg_integer()}) => Argus.Cfg.Function.t()
}

Build per-function CFGs from typed facts (Argus.Pipeline.extract/2 with format: :typed).

build_for(data, name, arity)

@spec build_for(map(), atom(), arity()) :: Argus.Cfg.Function.t() | nil

The graph of one function of a module given as disassembly (%{module: ..., functions: ...}), built from the facts the emitter would produce. What an extractor uses when it was handed bare disassembly rather than a pipeline module whose graphs are already attached.