Add a flag to enable the decompilation of a single function.
In order to have a single flag shared between the `RestructureCFGPass`
and the `CDecompilerPass`, we added a new dedicated decompilation unit
called `TargetFunctionOption`.
`ExprNode` and its child classes use LLVM-style RTTI.
Until now their destruction was not handled properly, causing the
constructor-destructor type mismatch warnings on ASAN.
Despite this all the code was working properly, but just for luck,
because of the fact that these classes are very shallow.
This commit fixes the issue, and allow `ExprNode` and its child classes
to be extended without worrying about wrong destructors being invoked.
Replicate the changes made by this commit
f2a0df309f78e1b5d7c5f81ada5110523644559e perfomed by Pietro on the
branch containing the development fixes for `revng-c`.
Add new headers files (terminating with `BB`, as `BasicBlockNodeBB.h`),
which will be used as the new header files by the users, and which
contain a declaration of the template instantiation, and a `using`
aliasing the instantiation.
This has been made to comply with the `-Wundefined-func-template` flag,
automatically enabled when using `-Weverything`
Enhanced the `findReachableNodes` algorithm, with a new `StackSet`
parallel data structure which is used to quickly check if we are
encountering a node already on the visit stack.
Modified the `findReachableNodes` to include in the returned set of
nodes also nodes which are encountered on self loop paths and that
should consequently be included in this set.
Add a new dummy node as the source of each backedge found in the graph,
during the preprocessing.
This help in the semplification phase of the SCS, since the new dummy
node helps triggering merging of metaregions with have a non empty
intersection.
The new SCS merging criterion, checks that there are no abnormal
retreating nodes between SCS, meaning retreatings which exit from the
current SCS and do not point to the head of another SCS.
This kind of situation, if ignored could cause the introduction of some
cycles between outlined nodes and existing nodes, inserting new cycles
during the restructuring, which is a behavior which we aim to avoid.
When outlining nodes, we now include them in eventual parent metaregions
that included the nodes collapsed.
This should lead to minor duplication (as in the `cp` benchmark), since
we avoid duplicating two times nodes if also the external region causes
the first iteration outlining.
We know keep updated the RPOT during node removals (otherwise we have
situation of pointer clashes) instead of recomputing it at each
metaregion restructuring iteration.
To avoid skeing the results the serialization of `DOT` intermediate file
for both restructuring and AST semplification passes are now serialized
only when the corresponding loggers (`CombLogger` and `BeautifyLogger`)
are enabled.
When a retreating edge involves as source node a `SetNode` belonging to
an internal region (which should be the default `SetNode` that remains
outside the collpased node), move it just after the `CheckNode` that is
being introduced, so that the semantics of the code remains untouched.
Use a `llvm::SmallString` for the `Name` field of `BasicBlockNode`.
This enables us to modify the name of the node, which is very useful
during debugging and manual inspection of the graph serialized in
output.
Fix the metaregion identification phase, in particular the add of the
addditional nodes merged when encountering a node which is the target of
a backedge identifying another metaregion.
The add of the additional nodes must be done in a fixed point fashion,
otherwise in case of dependent insertions the order of the nodes
triggers different behaviours (and bugs).
`BasicBlockNode` and `RegionCFG` classes are now template classes. This
means that the `BasicBlockNode` class can be used as a generic wrapper
for any type of object in the original graph (it is usually used to wrap
a `llvm::BasicBlock *` for decompilation purposes, but in tests it can
be used to wrap a `DotNode` object) that implementes `GraphTraits`.
Improved the interaction with the `StringRef` name field of
`BasicBlockNode`.
In case of artificial nodes, the name is left empty and created
on-the-fly for serialization purposes.
Removed the computation of the information contained in the
`NDuplicates` prevously done in the `MarkForSerialization` pass, since
the information is now precomputed in the `RestructureCFG` pass and
exposed with a dedicated method.
Update the `OriginalBB` map (which will be later used for retrieving the
original basic block linked to a certain BBNode) during nested
`RegionCFG` creation and during flattening, which are steps that modify
the allocation of the `BBNode` objects.
The `RegionCFG::initialize` method is now a template method, which
accepts as input any kind of object which exposes the `GraphTraits`.
In this way we can build a `RegionCFG` object not only starting from
LLVM IR, which can be very useful for testing purpose.
Since we also removed the information about the original
`llvm::BasicBlock` inside the `BasicBlockNode`, we need to keep this
link to later feed this information to the GHAST in an external data
structure (potentially a `std::map`).
The `BasicBlockNode` does not contain anymore any pointer to the
`llvm::BasicBlock` object that generated the `BasicBlockNode`.
This change is necessary for decoupling completely the `BasicBlockNode`
and `RegionCFG` classes from the LLVM IR, so that we can build up a
`RegionCFG` from any object which implements the `GraphTraits`.
The `RegionCFG` does not contain anymore a map between
`llvm::BasicBlock` and `BasicBlockNode`.
Once we compute the set of backedges, they should be fixed and should
not change during the restructuring phase, otherwise we may end-up
inserting loops including outlined node if the information about the
backedges changes completely during the analysis (edge that were
backedges and for which a corresponding SCS was computed become forward
edges, and viceversa, and this behaviors break our assumptions that
outlined node do not take part in loops ever).
This means that we need to keep updated the set of backedges computed at
the beginning instead of recomputing it at each restructuring iteration.
We need to take particular care in updating the information in presence
of the default `SetNode` inserted in case of an entry dispatcher.
The actual implementation is pretty naive, and the update of the
`Backedges` `std::set` is for sure not optimal, we should consider using
a `std::multimap` for it.
We should also consider updating the reverse postorder instead of
recomputing it, but at it seems that recomputing it may cause
sub-optimal restructuring, but no errors should be triggered.
New SCS merge step for situations in which we have an abnormal edge
exiting from an SCS.
This criterion, during the preprocessing of the metaregions, if an SCS
with an abnormal retreating edge is found (an abnormal retreating is a
retreating edge which target is outside the scope of the current SCS
under analysis), merges the metaregion under analysis with the one which
has been created starting from the backedge.
This preprocessing phase is made in a fixed point fashion.
When creating the collapsed node, remember to add in the substitution
phase of the old nodes of the regions (relative to the outer regions),
also any nodes added as default `SetNode`s for any entry dispatcher
inserted.
Add an assert which verify that all the targets of the retreating edges
fall inside the SCS under analysis.
Add other asserts to verify that the graphs passed to the comb pass are
acyclic after restructuring.
The `removeNotReachables` method now can take care of removing any
reference of the removed nodes from any `MetaRegion` which contains any
reference to it.
Now avoiding `predecessors()` iterator invalidation and enforcing
bounds check when using `ClonedMap` during first iteration outlining.
Also avoiding usage of `FirstCandidate` once the real head of a
`RegionCFG` has been elected (only `Head` ptr should be used).