Conversation
sipma
left a comment
There was a problem hiding this comment.
It looks good to me. Thank you for fixing this.
Ricardo, could you please also have a look at it, and merge it if you think it is okay?
waskyo
left a comment
There was a problem hiding this comment.
First pass: I think I understand the reason for the change and (high-level) what you're doing to fix it, now I'm just trying to make sure the code details match up.
Apologies for the pain.
5dac642 to
b254851
Compare
waskyo
left a comment
There was a problem hiding this comment.
Just the 1 question + previous request for a magic-comment.
Can you do a final regression test run and if it passes I'll merge? 🙏
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.
aeb2634 to
2f11127
Compare
|
passed regressions with only CHB branch: https://github.com/Aarno-Labs/codehawk-regression/actions/runs/35637485245 |
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.