Skip to content

[CFG] CFG edge validator#703

Open
hughperkins wants to merge 2 commits into
hp/remove-cfg-lambdasfrom
hp/cfg-edge-validator
Open

[CFG] CFG edge validator#703
hughperkins wants to merge 2 commits into
hp/remove-cfg-lambdasfrom
hp/cfg-edge-validator

Conversation

@hughperkins
Copy link
Copy Markdown
Collaborator

Issue: #

Brief Summary

copilot:summary

Walkthrough

copilot:walkthrough

The endpoint-only invariants (start_node / final_node in range, both
non-null) don't catch the asymmetric-edge corruption typical of a
pre-CFG IR transform producing malformed IR that build_cfg then turns
into a CFG with mismatched prev/next pointers. Such corruption
surfaces as a segfault deep in worklist propagation, not at the
boundary.

Add a second phase to assert_structural_invariants: for every node n
and every successor m in n->next, require m->prev to contain n (and
symmetrically for predecessors). Null entries are tolerated -- erase()
clears entries before simplify_graph compacts, so the intermediate
non-compact state must still validate.

Cost is O(V+E), small for typical kernels and dominated by the analyses
that follow; left always-on (release builds too) because the
alternative on violation is silent corruption.
When a structural-invariant check fires, the assert message now points
at a fresh file under <tmp>/cfg_invariant_failures/structural_<ns>.txt
containing the CFG state at the moment of violation -- node-by-node
ranges, prev/next edges, intra-node next/prev links, the offending
nodes' statements. Designed for post-mortem on the kind of failure that
shows up after a pre-CFG IR transform (e.g. an unstructured-control-flow
normaliser) produces a CFG that build_cfg cannot canonicalise: instead
of "assert fired, now bisect from scratch" the user has a viewable
graph at the exact failure point.

The dumper is deliberately tolerant of malformed state. It is invoked
only after a violation has been detected so the graph is by construction
not internally consistent: null entries print as <ERASED>, per-node dump
calls are individually try/catch wrapped so a single bad pointer
doesn't take down the whole dump, and the outer try/catch handles
filesystem failures. Returns the path on success or empty if the dump
itself failed; the assert message picks "<dump failed>" in that case.

Also fold the previously-one-per-violation QD_ASSERT_INFO calls into a
single comprehensive message at the end -- the endpoint phase now
collects all violations before bailing, so the user sees every broken
endpoint at once instead of fixing them serially. Edge-consistency
phase still short-circuits on first violation (subsequent edges may
share corrupted pointers).
@hughperkins hughperkins changed the base branch from main to hp/remove-cfg-lambdas May 16, 2026 07:08
@chatgpt-codex-connector
Copy link
Copy Markdown

💡 Codex Review

.start_node = start_node,

P2 Badge Replace C++20 designated initializers

This new file is picked up by the core source glob, while the project is explicitly built as C++17 (CMakeLists.txt sets CMAKE_CXX_STANDARD 17, and MSVC gets /std:c++17). Designated initializers are a C++20 feature, so supported C++17/MSVC builds that compile this file will fail here; please use positional aggregate initialization or add constructors instead.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@github-actions
Copy link
Copy Markdown

@github-actions
Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant