We now switch to the `llvm::df_iterator` based `nodesBetween`
implementation.
This new implementation makes use of the idiomatic way of extending the
DFS implementation provided by LLVM, instead of rolling our custom
implementation for the `nodesBetween` algorithm.
We improve the `getBackedges` and `nodesBetween` helper functions that
can be used for backedge discovery and computation of all the nodes
reachable on all the paths defined between two nodes in a graph.
We build upon the `llvm::df_iterator` function, by customizing the visit
stack to perform the desired visits.
Not every case can benefit from extra liniency, so they were manually
reviewed on a case by case basis.
Additionally, this drops a couple of "this should be a non-strict
specialization" commits, because of a bug with clang
(see the GenericGraph concepts rework commit for more details) as
to avoid confusion (we wouldn't want anyone trying to solve these
"todo"s) until the clang struct type deduction is fixed. Especially
considering that there are currently no cases where these softer
versions would be beneficial (we never inherit from templates in
question).
`ValueMaterializer` is a rewrite of what was called `AdvancedValueInfo`
which follows the same principles.
The main benefits over the old version is:
* We materialize the data-flow graph and the CFG of the relevant part of
root. This makes debugging significantly easier.
* We drop the old MonotoneFramework infrastructure in favor of
getMaximalFixedPoint.
* We significantly reduce the amount of queries we make to
AdvancedValueInfo.
Now extractvalue instruction are replaced by dedicated
OpaqueExtractValue custom opcode, that prevents LLVM from doing strange
things with extractvalues during optimizations (such as e.g. sinking).
This is important since extractvalue instructions and struct-typed
values in general in our LLVM IR are not real first-class citizens, but
only a byproduct of the binary lifting process, and they actually
represent bundles of registers that are returned from isolated
functions.
Introduce the hybrid beautifier aiming to simplify double `not`s (one on
the IR side (e.g., a `icmp ne`), and one on the `ExprNode` side on the
`GHAST` in the form of a `NotNode`.
To do this hybrid beautifier, we basically need to do the following:
- Implement a preliminary collection phase which computes which
`ExprNode`s are affected by which `BasicBlock`.
- Compute the so-called consesus, i.e., verify that for all the
`ExprNode`s affected by a certain `BasicBlock`, the transformation
would be beneficial in terms of output. Basically:
1) That the number of `!(!=)` transformed into `(==)` outscores the
number of correlated `(!=)` which are transformed into `!(==)`.
2) That the number of `!(==)` transformed into `(!=)` outscores the
number of correlated `(==)` which are transformed into `!(!=)`.
- Actually perform the transformation for those situations where the
consensus agrees.
This commit enables to emit accesses with the square bracket array
access operator on pointers.
This is accomplished by adding an additional mandatory argument to
ModelGEP (AND NOT to ModelGEPRef) to represent this case.
MakeModelGEPPass is updated to take this into account, together with all
the other passes that handle ModelGEPs.
By using this class we can create ptml::Tags without
XML tags. It is useful in the revng-c part when we
want to generate Plain C. All PTML Tags, from now on,
should be created via this class only.
In addition, port `Yield` library to be using this.