Reorganize the AST dot printing in order to use LLVM facilities for
files handling. In addition, clean up the code, and add a function
(useful in debug) in order to dump the dot of and AST from GDB (accepts
a `char *` instead of a `std::string`.
This commit fixes two interacting problems in the beautification of if
statements.
First, in `simplifyShortCircuit`, there were two assertion on null
pointers that were too strict. These assertions didn't take into
consideration that one among the "then" and the "else" branch of an
`IfNode` could be simplified away _during_ the beautification itself.
Second, a previous commit had moved the execution `flipEmptyThen` after
the two beautification of short-circuit, leading to assertions failed
in `simplifyTrivialShortCircuit`.
This was caused by the fact that `simplifyTrivialShortCircuit` only
never expected `IfNode`s with empty "then".
This was fixed by running `flipEmptyThen` also before
`simplifyTrivialShortCircuit`.
The simplifyLastContinue beautifier was too ambitious and there were
many corner cases that it handled in the wrong way, leaving the AST in a
shape that could not be emitted, or breaking the semantics.
This commit severely weakens the simplifyLastContinue, so that it does
not break things anymore.
It is now able to match only continue statements that are in the last
position of a sequence node which is the body of a ScsNode.
This obviously is not enough but allows revng-c to pass all the
decompilation tests.
In the future we will need to extend simplifyLastContinue to match more
cases in a sane way.
This commit moves the matching of short-circuited ifs before the stage
of flipping if nodes with emtpy then.
This is necessary because the if short-circuiting may produce if nodes
with empty then, which can be then flipped by the next beautify step.
Before this commit, we couldn't handle simplification of atomic
sequences in cases of switches that had a default.
The reason is that if you remove a case from a switch that has a
default, you are implicitly saying that the case that you remove will be
handled by the default, hence you're changing the semantics.
Now we handle this case by not removing the case, substituting it with a
SwitchBreak node instead.
Remove from the `RegionCFGTreeImpl.h` header the helper functions used
for the first AST simplification that are now part of the
`GenerateAst.h` header.
`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`.
Collection of the metrics related to the short circuit and trivial short
circuit simplification. The metrics are computed directly during the
beautify pass and later serialized on a .csv file.
The companion function for the short circuit simplification, which tells
if the computation of the condition of a conditional node can be
inlined, always returns true, and therefore enables all the possible
optimizations.
Added a new attribute for the `ContinueNode`, which tells if a
`ContinueNode` should be considered implicit. An implicit continue node
means that it can be dropped without it altering the semantics of the
code (e.g., when the `continue` is the last statement inside the body of
a cycle).
This attribute enables us to avoid directly dropping the continue node,
which would also cause the computation attached to this node to be
dropped, also in the output of the decompiler pass.
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.
We now match the `IfCheckNode` trees created by the dispatchers
insertion as an unique switch.
To this we introduced a new `SwitchCheckNode` AST type, which cannot
inherith from the `SwitchNode` since the underlying container for the
`case`s is different (the index is saved as an `unsigned`, while instead
in the `SwitchNode` we use a `ConstantInt *`.
Apply the short circuit simplification only if the basic block
associated with the internal node requires no statement serialization to
happen in the decompiled code. We use the information provided by the
`MarkForSerialization` to know this.
The condition inside the `IfNode`s are now represented using a custom
`ExprNode` object, which has a new hierarchy of possible nodes present
in an expression (`not`, `and` and `or`).
Moved the `flipEmptyThen` post-processing inside the beautify pass.
The ownership of the `ExprNode` is kept inside the `ASTTree` object.
This means that during the flattening we also need to transfer these
objects and to adjust the pointers inside the `IfNode`s.
Moved a lot of passes that apply optimizations on the AST in the
decompilation pass.
All the optimization functions are now in a dedicated file
(`CDecompilerBeautify.cpp`) and the only function used as interface with
the `CDecompilerAction` pass is the `beautifyAST` function.
This means that now the simplifications will be applied on the already
flattened AST.
Some basic transformations have been left in the `RestructureCFG` pass,
to avoid having an AST of poor quality as output of the pass.