Model classes are now described by a YAML document, which is used to
generate C++ headers containing classes and all the boilerplate
required for YAML serialization/deserialization, usage in
SortedVectors, etc. See the README in include/revng/Model for more
info.
Remove the logic for detecting Instructions with duplicated uses
introduced by control-flow restructuring (the use is duplicated, but the
instruction is not).
By dropping this detection, we'll end up not marking for serialization
some Instructions. Hence, when emitting C code, such Instructions will
just be emitted as inline expressions, without declaring a dedicated
local variable to hold their value. This is somehow suboptimal w.r.t the
fact that the expression will be emitted many times, one for each
duplicated use. However, this is not semantically incorrect, just
verbose.
On the other hand, the logic for detecting Instructions with duplicated
uses has always been subtly broken, because it only looked at the number
of duplicates for a given basic block introduced by control-flow
restructuring.
This information is not enough to detect Instructions with duplicated
uses. Proper detection should actually be based on GHAST.
`main` is not in all cases a dynamically exported symbol, therefore,
it's not safe to rely on it.
This commit switches to use `PathList`'s `getCurrentExecutableFullPath`,
which reads `/proc/self/exe`.
The constructor now accepts a llvm::object::Binary directly rather than
a path. Will be used by the revng-pipeline which will retain ownership
of the binary.
A dereference iterator is used to map a pointer-like object to the
pointee, as an example given a `vector<unique_ptr<int>> Vector`, using
`dereferenceRange(Vector)` will present a range of `int &` rather than a
range of `unique_ptr<int> &`.
mapToValueIterator can be used on a map range
to access the underlying object directly rather
than the pair<key, object>.
This allows e.g. the following programming pattern:
```
RecursiveCoroutine<std::optional<SomeType>> f();
int g() {
return *f();
}
```
Without operator* defined for `RecursiveCoroutine` this would fail,
requiring an explicit cast such as:
```
int g() {
return *static_cast<std::optional<SomeType>>(f());
}
```
Before this commit `is_specialization<const X<T>, X>` was not
specialized, so that `const X<T>` did not count as a specialization of
`X`. This resulted in bad selection of template specialization based on
concepts that were using `is_specialization_v`, such as
`IsUpcastablePointer`.
This commit fixes the problem, so that now the concept
`IsUpcastablePointer` is true for `const UpcastablePointer<T>` as well.
This also enabled to remove some workarounds for the `IsMutableSet` and
`IsSortedVector` concepts, and treat them uniformly with other concepts
that were using `is_specialization_v`.
Before this commit, it was only matched by types that satisfied the
constraint `IsUpcastablePointer`, which is too strict.
Now also types that match `UpcastablePointerLike` satisfy the
constraints for this concept.