Isolated the part creating `switch` AST nodes in a dedicated section of
the `generateAST` method.
In addition, the creation of the standard nodes has been refactored with
a `switch` case covering all the possible situations.
Removed the distinction between entry and exit dispatcher nodes since
they are semantically equivalent.
Only the name differentiates them (useful for debugging purpose).
Drop duplicated code in `addPredecessor/addSuccessor` reusing the code
of respectively `hasPredecessor/hasSuccessor`.
Restructure the code of `hasPredecessor/hasSuccessor` with idiomatic use
of `std::find`.
Restructure the core algorithm of the weaving, according to the
following idea:
- Compute the PDT.
- Iterate on the graph in post order.
- For every switch node S, take its immediate post dominator P.
- Let C be the set of cases for S and iterate in reverse post order on
the nodes N between S and P.
- If N post-dominates at least one case in C, but not all of them, it's
a candidate for weaving.
- Waving inserts a common predecessor K to the cases to be weaved. The
weaved cases are removed from C, and K is added to C (C is the set of
case labels for the switch S).
- The PDT is then updated to reflect the addition of K.
Remove an assert used to check that no switch nodes were present in the
graph. These assertions are not useful anymore since we now handle
generic conditional nodes.
Reorganize attribute `Kind` incorporating it into the `Type` attribute,
by lowering its memory footprint.
Modified the constructors, some accessors and helpers accordingly.
Removed some development leftover in the aforementioned method. In the
future we should consider adding some logic to not set as a successor
for each `switch` node the `unexpectedpc`, which causes sub-optimal
performances in the restructuring (and combing, and untangling, and
waeving).
Improve constructors of `SwitchNode`, `RegularSwitchNode` and
`SwitchCheckNode` by adding a new default parameter for the successor
and therefore removing a useless parameter.
We now set the postdominator (meaning the point where the combing stop
the exploration for dominated nodes) for the case nodes using the
postdominator of the switch node corresponding to the case.
Workaround that resort to looking for the original switch node in the IR
to force the creation of a switch node even if we have < 4 nodes under
our domination.
First implementation sketch of the waveing pass.
The implementation operates by going through the postdominator tree, and
by adding preposterous switch nodes in case we have a topology that we
cannot emit using standard switches.
In this way, we build a tree of nested switch costructs.
Added a new constructor for the dispatcher nodes which will be emitted
as `switch` nodes by the decompiler.
These nodes are introduced during the restructuring phase as loop
dispatchers.
Improved the creation of `Regular` and `Check` switch nodes types during
the preliminary AST creation phase performed on the `RegionCFG`.
In particular, we now handle the dispatchers creating the right AST node
type.
Create directly regular switch nodes in the AST build starting from the
`RegionCFG`.
As of now, a switch node is built only if we find a node that
immediately dominates more than 3 nodes.
In the future, we will need to refine this criterion.
During the RegionCFG creation from the LLVM IR handle the creation of
nodes with possibly more than two successors.
In this way we do not have to disassemble the switch nodes in nested if
trees.