The graph-ir branch contains a quick trial on how the IR could be revamped. Part of that is a new builder/modifier scheme where the user does not directly interact with modules, functions, processes, entities, blocks, and instructions, but rather uses builder instances. These lock the module or unit in place using a lifetime and are the only means to modify these structs -- they don't provide such functionality themselves.
This provides a single point of modification for the IR, and allows the code to perform a lot of bookkeeping on the side, such as pred/succ and usage tables, as well as dominator tree invalidation. The current IR would greatly benefit from such a scheme as it streamlines interaction with LLHD and provides more opportunities to make things fast on the inside.
An interesting improvement would be to make the changes applied to these builders deferred, such that the user can accumulate modifications which then only become visible upon committing them. This would allow the user to interact with analyses such as DTs and TRGs without them being invalidated by modification, with the express mental model being that the changes are delayed and as such the analyses remain valid.
An important side-effect of this is that modification through a single structure allows that structure to maintain a lot of accelerating lookup data structures, such as predecessor/successor lists, terminator maps, phi node lists, cached dominator tables, etc.
Todo
[ ] Use an arena to allocate values, instructions, blocks in PrimaryTable2
[ ] Split handles such as Value into ValueId (the actual index) and Value (a wrapper around the index, and other pointers).
[ ] Block
[ ] Value
[ ] Inst
[ ] Distinguish between removing a node (e.g. remove_value) and deallocating it (e.g. dealloc_value). The former does not invalidate existing references, but marks node for deletion.
The graph-ir branch contains a quick trial on how the IR could be revamped. Part of that is a new builder/modifier scheme where the user does not directly interact with modules, functions, processes, entities, blocks, and instructions, but rather uses builder instances. These lock the module or unit in place using a lifetime and are the only means to modify these structs -- they don't provide such functionality themselves.
https://github.com/fabianschuiki/llhd/blob/75aeda71d0e8ea8ee548a21c4dd52b892c5f914f/examples/gir.rs#L47-L85 https://github.com/fabianschuiki/llhd/blob/75aeda71d0e8ea8ee548a21c4dd52b892c5f914f/examples/gir.rs#L107-L155
This provides a single point of modification for the IR, and allows the code to perform a lot of bookkeeping on the side, such as pred/succ and usage tables, as well as dominator tree invalidation. The current IR would greatly benefit from such a scheme as it streamlines interaction with LLHD and provides more opportunities to make things fast on the inside.
An interesting improvement would be to make the changes applied to these builders deferred, such that the user can accumulate modifications which then only become visible upon committing them. This would allow the user to interact with analyses such as DTs and TRGs without them being invalidated by modification, with the express mental model being that the changes are delayed and as such the analyses remain valid.
An important side-effect of this is that modification through a single structure allows that structure to maintain a lot of accelerating lookup data structures, such as predecessor/successor lists, terminator maps, phi node lists, cached dominator tables, etc.
Todo
PrimaryTable2
Value
intoValueId
(the actual index) andValue
(a wrapper around the index, and other pointers).remove_value
) and deallocating it (e.g.dealloc_value
). The former does not invalidate existing references, but marks node for deletion.