Skip to content

derive and expose address keyed GP register liveness - #290

Merged
sipma merged 9 commits into
static-analysis-engineering:masterfrom
leftbyte:dphung/pir-req3-register-liveness
Aug 22, 2026
Merged

derive and expose address keyed GP register liveness#290
sipma merged 9 commits into
static-analysis-engineering:masterfrom
leftbyte:dphung/pir-req3-register-liveness

Conversation

@leftbyte

@leftbyte leftbyte commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

This PR is stacked on top of #289.

Same mechanism as PR #289, applied to general-purpose registers: derives register live-in/live-out per instruction address from the reaching-def facts. Gives a sound answer to "which registers are live across this point".

This metadata is used in the patcher's predicated-if register-safety check to fall back to a (register-safe) trampoline when the in-place body would clobber a register live at the region exit.

@leftbyte
leftbyte force-pushed the dphung/pir-req3-register-liveness branch 2 times, most recently from af5441e to 18827d3 Compare August 7, 2026 04:54
@leftbyte leftbyte changed the title derive and expose address-keyed GP-register-liveness WIP: derive and expose address-keyed GP-register-liveness Aug 7, 2026
@leftbyte leftbyte changed the title WIP: derive and expose address-keyed GP-register-liveness WIP: derive and expose address keyed GP register liveness Aug 11, 2026
@leftbyte leftbyte changed the title WIP: derive and expose address keyed GP register liveness derive and expose address keyed GP register liveness Aug 18, 2026
@waskyo

waskyo commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Review will be in leftbyte#1 while we merge #289. Because technology is hard.

Technology really is hard, that still shows the wrong diff. Will do commit-by-commit review on this one 🔥

@waskyo waskyo left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just the one comment.

Comment thread chb/ast/ASTProvenance.py Outdated
def register_liveness(self) -> Mapping[str, Dict[str, List[str]]]:
return self._register_liveness

def set_register_liveness(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as in #289, use setter?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@leftbyte
leftbyte force-pushed the dphung/pir-req3-register-liveness branch from 4ab5916 to ba0c29f Compare August 20, 2026 23:11
Dan Phung added 3 commits August 21, 2026 10:57
Add ASTILiveness, which computes NZCV flag live-in/live-out per
instruction address for a function by building per-address use/kill sets
from the per-instruction flag-reaching-def facts and running a backward
live-variable fixpoint over the CFG.

Block instructions are ordered with the same lexicographic sort BasicBlock
uses, which also tolerates the analysis's inlined-instruction addresses.
Add a flag-liveness map (keyed by instruction address) to ASTProvenance
with the standard getter/setter, and round-trip it through
serialize/deserialize alongside the other provenance facts.
Compute flag-liveness in mk_asts, alongside set_ast_provenance, so it
flows through the same builder path as the other provenance facts (rather
than only on the results-ast command path). The computation is auxiliary
and guarded so a failure cannot abort AST generation.
@leftbyte
leftbyte force-pushed the dphung/pir-req3-register-liveness branch from ba0c29f to d6614c7 Compare August 21, 2026 17:58
"F:0x...._0x....") belongs to an instruction the analysis inlined
from another function, so it is not a site in this function's CFG.
Neither one can kill anything here.
"""

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am somewhat confused about this comment. It seems incorrect, but raises an interesting issue, at least for flag definitions. Flags are not preserved across function calls. I realize this is an omission also on the ocaml side, where flag definitions are currently not clobbered by calls, like registers R0-R3 are; I will fix that. However, if you encounter a def-site prefixed with F, then that location does kill, because the execution sequence determines what flags are set. If indeed a flag def-site is in the inlined (presumably a payload) function, then that is what the downstream code sees. For the same reason, an "init" def-site for a flag definition is suspicious if that is an actual reaching definition for a user; it should probably generate a warning.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, sorry that was my misunderstanding of the ABI and the Flag preservation. I've now removed that and added a warning.

@leftbyte
leftbyte force-pushed the dphung/pir-req3-register-liveness branch 2 times, most recently from fae1c48 to 1acd557 Compare August 21, 2026 20:30
Dan Phung added 2 commits August 21, 2026 13:47
is_real_def_site excluded any "F"-prefixed def-site as "not a site in
this function's CFG", which was wrong. Those instructions execute and
define what they define, and their addresses are ordinary keys in
fn.blocks and fn.instructions. _use_kill was therefore recording uses at
those addresses while discarding their kills.
An "init" def-site means the value was defined on function entry rather
than by an instruction. For a registers that is ordinary and an incoming
parameter is defined exactly there. This is not normal for a flag
because the ABI leaves NZCV undefined on entry to a function.
@leftbyte
leftbyte force-pushed the dphung/pir-req3-register-liveness branch from 1acd557 to 142f028 Compare August 21, 2026 20:54
Dan Phung added 4 commits August 21, 2026 20:39
Extend ASTILiveness with register_liveness, computing GP-register
live-in/live-out per instruction address from the per-instruction
reaching-def facts (restricted to the architecture register set to exclude
spill slots and stack temporaries), reusing the shared use/kill and
backward-fixpoint engine already used for flag-liveness.
Add a register-liveness map (keyed by instruction address) to
ASTProvenance with the standard getter/setter, and round-trip it through
serialize/deserialize alongside the other provenance facts.
Compute register-liveness in mk_asts, alongside set_ast_provenance and the
flag-liveness computation, so it flows through the same builder path as the
other provenance facts. The computation is auxiliary and guarded so a
failure cannot abort AST generation.
@leftbyte
leftbyte force-pushed the dphung/pir-req3-register-liveness branch from 142f028 to 74efa53 Compare August 22, 2026 03:45

@sipma sipma left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

Ricardo, thank you for doing the review!

@sipma
sipma merged commit 990a344 into static-analysis-engineering:master Aug 22, 2026
1 check passed
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.

3 participants