derive and expose address keyed GP register liveness - #290
Conversation
af5441e to
18827d3
Compare
|
Technology really is hard, that still shows the wrong diff. Will do commit-by-commit review on this one 🔥 |
| def register_liveness(self) -> Mapping[str, Dict[str, List[str]]]: | ||
| return self._register_liveness | ||
|
|
||
| def set_register_liveness( |
4ab5916 to
ba0c29f
Compare
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.
ba0c29f to
d6614c7
Compare
| "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. | ||
| """ |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Yes, sorry that was my misunderstanding of the ABI and the Flag preservation. I've now removed that and added a warning.
fae1c48 to
1acd557
Compare
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.
1acd557 to
142f028
Compare
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.
142f028 to
74efa53
Compare
sipma
left a comment
There was a problem hiding this comment.
Thank you!
Ricardo, thank you for doing the review!
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.