Conversation
added 2 commits
September 15, 2026 16:27
assembly_ast flattened every block into an instruction sequence, so an if-converted predicated run was rendered as unconditional assigns and the low-level form of its guard was attached to nothing. Since serialization only indexes nodes reachable from the ast start nodes, that expression never reached the exported AST, leaving provenance's expression-mapping pointing at an id no node carries. Partition a block that has control flow and emit each predicated fragment as a branch on the flag condition, mirroring what ast_fragment already does for the high-level AST. assembly_ast_cc_condition returns the same ll_ast_cc_condition object that ast_cc_condition_prov mapped the high-level condition onto, so the emitted node keeps its exprid and the mapping resolves. A fragment with no low-level predicate falls back to the flat sequence with a warning. Also makes the low-level AST stop claiming that a conditional instruction always executes.
The low-level block emitters added with the predicated guard were copies of their high-level counterparts so refactor to give each high-level emitter an ll selector.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
For ARM predicated instructions, the high level AST from the lifting is represented as a branch on the instruction predicate. The serialization from the high level to low level representation flattened every block into one instruction sequence so a conditional store was rendered as though it always executes. This resulted in the low-level form of the guard being detached from the rest of the graph (i.e the
expriddid not have a node.)The following is an example three-line function whose guarded store gcc if-converts:
Before, in the low-level AST, the store always happens and the provenance pointed at a guard that was not there:
Five of the six entries resolve to a node. The sixth is the guard where the high-level exprid 18 is node #349, (idx ge 0) (the condition of the high-level if) that maps to low-level exprid 15, which did not have a node in the low-level AST. A consumer that resolves the low-level form of a guard finds nothing, which caused the mram-patcher to raise a KeyError.
After. The predicated run is emitted as a branch, and node #421 carries exprid 15:
(N eq V) is the flag test the ge predicate reads and it is the same expression object the mapping already pointed at.
assembly_astnow partitions a block that has control flow and emits each fragment, mirroring the structure the high-level side already uses (ast -> fragmented_ast -> ast_fragment). A predicated fragment becomes a branch so the node keeps its exprid.