We now craft a new decompilation pipeline. We remove the exceptions
introduced as fallbacks to preserve the semantics, and we perform passes
of `dce` and `simplifycfg` to remove all the superfluos basic block
remaining after this change. To do this, we need an additional pass that
removes also the calls to the `llvm.assume` intrinsic, and another pass
of `dce` to remove all the dead uses.
In addition, we also remove dead stores to the `cpu_loop_exiting` global
variable in order to improve the decompiled code.
As a byproduct of this, we remove also the dependency from the
`-remove-pc-stores` pass, since its jobs is included by the changes
mentioned above.
FunctionIsolation used to base its work on calls to the marker function
`function_call`, as opposed to information provided by the StackAnalysis
(i.e., `revng.member.type` along with `func.call`).
This also affected EnforceABI, which took care of finishing the work
left over by FunctionIsolation. This was hackish and inelegant.
This commit makes FunctionIsolation work exclusively employing
information from StackAnalysis and purges away code that is no longer
necessary from EnforceABI.
Now cover a corner case where we have a tile composed by two successors,
which we entirely dominate, and a common postdominator which we don't
postdominate (basically we miss a superfluos dummy here).
In this case, include in the tile `then` and `else` bodies, but do not
include in the tile the common postdom (it will be taken care by someone
else more higher in the CFG).
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.
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.
This commit fixes a bug causing iterator invalidation in
`markUnexpectedPCAsInlined`.
Before this commit we were iterating over a graph while adding nodes,
which could cause iteration invalidation on realloc.
Added assertions that checks that, once, during combing, we start
analyzing a path deriving from an inlined edge, we only encounter nodes
which do not require combing (all predecessors have been visited), or
that are reachable only from inlined edges (this is usually the case for
edges bringing to the `UnexpectedPC` basic block).
When we perform the tagging of the inlined edges in occurence of, we
also perform a duplication of the `UnexpectedPC` basic block.
In this way, we can avoid, walking through inlined edges during the
combing, since we now that all the nodes following an inlined edges will
be dominated by the corresponding conditional bringing to it.
Update the `Body` pointer inside an `ScsNode` when processing the
`copyASTNodesFrom` method, in order to update the `Body` pointer of
nested collapsed nodes.
Remove from the `RegionCFGTreeImpl.h` header the helper functions used
for the first AST simplification that are now part of the
`GenerateAst.h` header.
The generation of tiles for nodes with two successors was broken for
nodes with two successors because it assumed that at least one of them
was inlined.
This is may not be true in general.
This commit fixes the tile generation for those cases.
Before this commit, outgoing edges from switch nodes were not created
with correct case labels.
For a while we assumed this was fine as long as we fixed them later,
with the tagCaseEdges() method.
However, we didn't realize that adding labels later could not handle
correctly come situation, namely switches with a case that was a set
node followed by a break node to the outermost RegionCFG.
The only way to handle that situation correctly without pattern matching
is to construct the RegionCFG with the correct labels in the first
place.
This is exactly what this commit does.
We now do not generate again the AST for collapsed node that have been
duplicated.
If we encounter a region for which the AST was already generated, we
simply use the already computed AST (also because the tiling now
destroys the `RegionCFG` while it build the AST).
Count the number of duplication (needed later in the `Mark` pass) right
before the AST generation phase, where the `RegionCFG` will be destroyed
by the tiling matching.
When generating the AST, we now iterate directly on the non-filtered
graph in post order, instead of computing a depth first iteration on the
dominator tree built on the non filtered graph.
Handle the situation where we have 2 successors, and we dominate only 1
node.
This tile can be generated only when we have 2 successors, and one of
this successors is an inlined node. No common postdominator in
contemplated in this tile.
Handle the situation where we have 2 successor nodes, but we only
dominate 1 of them.
This tile can generate different situations, depending on the actual
structure: we can have a diamond shaped region with an inlined edge, we
can have a diamond without the postdominator and no inlined edge.