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).
The new value is `800000`, same as that of
`PenaltyBreakBeforeFirstCallParameter`.
Currenly there are no cases where this is relevant in the codebase
(since it was not allowed), so here's an artificial one to illustrate
the situation:
(behaviour before this commit)
```
auto x = short_whatever(
whatever_but_the_name_is_long("first", "second", "a long argument"));
```
(behaviour after this commit)
```
auto x = short_whatever(whatever_but_the_name_is_long("first",
"second",
"a long argument"));
```
`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.
Sometimes code performs an indirect jump without changing the value of
the PC. In most cases this is due to non-code or some other faulty
situation, but it is in principle possible that an instruction performs
an indirect branch to its own address.
This commit ensures that this situation does not end up in an hard
failure.
This is necessary because i386 has weird sizes for `long double` that
result in `float86_t` in the model, so we need to pass additional
arguments to the recompilation tests, in order to avoid compiler errors.
Before this commit, both `generic80_t` and `generic96_t` were always
defined as structs containing an array of chars of the proper size.
This ensured that they always had the proper size, but it didn't play
well with recompilation of decompiled C code, because it wasn't possible
to assign e.g. a `float80_t` to a `generic80_t` (or viceversa), which
was the whole point of having `generic80_t` and `generic96_t`.
This commit works around this by making sure that, whenever `float80_t`
(and `float96_t`) is defined, the definition of `generic80_t` (and
respectively of `generic96_t`) always matches, allowing error-free
recompilation of decompiled sources.
This change is intended for the name not to clash with another set of
tests that lives in revng-c.yml.
The first is intended as a set of unittests for model-to-header,
the second is intended to generated headers to test recompilation of
decompiled C code.
This commit guards 128-bits integer typedefs and helpers with:
`#ifdef __SIZEOF_INT128_`, because these are compiler extensions that
are not always guaranteed to be defined (e.g. they are not available
when compiling for x86 32-bits).
Before this commit, we used to decomple UndefValue to the literal 0.
This was causing problems in some cases, such as switch(0 /*undef*/)
where clang was issuing a warning that was impossible do disable without
turning off -Wall alltogether, which is undesirable.
This commit introduces a set of helper functions in
revng-primitive-types.h, that are now used to avoid emitting undef as
constant.
This is more semantically meaningful when looking at the decompiled
code, and it has the nice side effect that it silences the clang
warnings mentioned above.
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.