Do not promote registers to `undef` initializers of registers not marked
as being preserved by the current function.
This is useful to highlight usages of registers that are not an
argument, nor a callee saved register. Mainly this has been introduced
to preserved reads from x86-64 `fs` register.
We need to prevent DCE from killing `revng_init_local_sp`, since certain
passes downstream might want to introduce new uses of it, and they might
be the first.
`SegregateStackAccesses` will take care of removing it by hand.
This commit fixes file output `revng.api` in two ways:
* The buffer's size is properly reported in `PipelineC.cpp`
* The function `deserialize_container` in `revng.api.manager` no longer
appends a `\0` to `content`, while avoiding a redundant copy
The `xmlns` attribute outputted contained two sets of `""` (one
introducted by the format string and one from `Tag`) which would break
strict XML parsers
`DocumentError`s are the inteded way of propagating errors from the
pipeline to the frontend when a location is required to inform the user
of the error whereabouts.
The previous implementation was iterating on the instructions in order.
This caused problems when we had two instructions, A and B, both tagged
IsRef, and B was using A and B had 2 or more uses.
In this case the pass was looking at A before looking at B, so A was not
duplicated because it only had one use (B).
Then B was analyzed and it had 2 uses so it was duplicated, causing the
number of uses of A to increase accordingly.
This commit fixes the problem iterating on the BasicBlocks in post
order, and on the instruction list in reverse order.
It also fixes MarkAssignments.cpp not to erroneously mark instructions
that are marked IsRef.
Using a named metadata is simply wrong, because we need to have many of
these metadata alive at the same time with different values.
Using a named metadata has the unpleasant side effect of making all the
`SegmentRef` functions to refer to the same segment.
Change the way the jump instructions are outputted in the assembly
output to be PC-relative. This fixes an issue where the addresses in the
output where shifted forward.
This change fixes the pipeline behavior when producing targets:
* produce and extract now return rp_buffer, which has a start pointer
and size
* the python api `revng.api` will return on produce/extract either str
or bytes depending on the mime type of the container
* the GraphQL api will encode bytes in base64
To keep consistency with the rest of PipelineC, return `nullptr` when
calling `rp_container_extract_one` when the content of the specified
target hasn't been produced
Before this commit we couldn't handle gracefully situations where the
model had an array with elements of given size X and the IR had strided
accesses with a stride Y that was larger than X.
This commit gracefully handles that case, but for now it always bail
out.
In the future we could think of handling this better if Y is a multiple
of X.
A logic issue was addressed in `Runner::getDiffInvalidations`.
Premature invalidation of all targets (overestimated targets
found by `getInvalidations`) could lead to an error due to
lack of those targets (do not exist yet). We make sure that
such targets exist before providing them to the pipeline.
A logic issue existed in the Pipe, as it was mistakenly relying on
`IsolatedRoot` instead of the isolated function. That was breaking
things if those functions were to be removed. This issue has been
addressed by correcting the behaviour of the Pipe.
This change makes sure that CollectCFG is always intertwined
with FunctionIsolation, as it needs to run before the latter
executed. To avoid possible rearrangements on the pipeline
in the future, CollectCFG pass is now registered within FI.
A cyclic dependency between shared objects `revngYield` and
`revngFunctionIsolation` could exist if `FunctionIsolation`
were to use `yield`-defined methods. This has been prevented
by splitting pipes off within `Yield`.
A logic issue existed when validating whether a `cl::opt<T>`
was set. This has been addressed by replacing `isDefaultOption`
method with `getNumOccurrences`, as the former one was not
meant to be used for checking if the option was set or not.
Likewise, the default Option itself is written to a `std::string`,
in method `get`; the latter is leveraged by `Invokable`.
Ensure that no backedges are left after the restructuring of all the
metaregions.
This additional assertion should help ensuring that no entries in the
`Backedges` set are left after the restructuring process, in turn making
it easier to spot bugs if backedges references are not handled correctly
during the steps of the restructuring.
Before this commit, MakeModelGEPPass was materializing all possible
traversals of the type system to select the best match for translating
some pointer arithmetic on the IR into ModelGEPs.
This proved to be very slow and to do a lot of useless computation on
larger binaries with big type systems.
This commit partially rewrites MakeModelGEPPass to adopt a
branch-and-bound approach to only explore paths on the type system that
have some chance of improving the best match.
Before this commit, the dla::Step CompactCompatibleArrays was
occasionally generating artificial nodes that were larger than the inner
data, forcing their size to Stride - AvailableSlack.
This commit fixes the problem keeping track of the actual size that is
consumed in the array element, and forcing the size of the artificial
nodes to that.
Assign a value to cloned and collapsed nodes in terms of shortest path
from entry, which is a criterion we use to elect region entry.
The shortest path is computed at the beginning for the nodes present in
the CFG, but needs to keep updated for additional nodes that we insert
that may become loop entry candidates.
During the creation of the exit dispatcher, take care of removing from
the `Backedges` set the additional backedge that is collapsed in case
two exiting backedges do target the same destination.
When this is not done, a ghost backedge is left inside the set, making
it not coherent with the state of the graph.
In addition, we add an assertion which ensures that during this phase of
the restructuring dummy nodes are present only as source of retreating
edges, and have one and only one successor.
The dla::Step ArrangeAccessesHierarchically looks throught the DLA graph
and for each node with many outgoing instance edges tries to see if some
of them are hierachically contained within each other.
In order to do this, before this commit, we were building an auxiliary
graph representing this hierarchy, and in order to build it we had to
perform a number of comparisons between edges that was quadratic with
the number of edges.
Moreover, once all the comparisons were done, we had a deep graph
representing inclusion between edges, but we only cared about the
top-level of this graph, i.e. only the edges that contained other edges
hierarchically, but were not contained in other edges (we'll call them
the root edges).
So we were doing a quadratic number of comparisons but possibly many of
them were useless.
Finally, all the edges that were included in root edges, were pushed
down, but only for a single layer, because they needed to be re-compared
later with the children of the root edges they were being pushed
through. This latter part was responsible for a lot of wasted
computation that just needed to be done over and over at all the layers.
Overall this algorithm was doing a lot of wasted computation.
This commit replaces this logic with a new algorithm.
Now we keep track only of the root edges, and we compare only root edges
with other root edges.
Initially all edges are root edges.
Then we start comparing them.
If a root edge A is included in another one B, then A is not a root edge
anymore, and all the edges that were previously found to be included in
A are not included in B.
This algorithm still does a worst case of quadratic number of
comparisons, but drastically reduces the amount of useless computation
that is redone later. In particular:
- in cases where there are a lot of root edges (meaning that only a few,
or no edge can be included in others) we do a number of comparison
close to quadratic, but we're only pushing non-root edges down, so
we'll never have to redo comparisons in deeper layers
- in cases where there is only a small number of root edges, we're doing
a number of comparisons close to linear, and we never compare non-root
edges with each other, so we're saving a lot of computation that would
be wasted (because it would need to be redone in deeper layers).
Before this commit we were manually building a topological ordering,
that resulted in worse overall performance in some scenarios.
This commit changes the dla::Step to temporarily introduce a fake root
node, and computes a RPOT from there, which overall yields better
results.