Split the `invalidate` method in two phases: in `invalidateCheck` it
just checks if the model diff warrants the execution of the actual
`invalidate` method, which requires fetching the custom invalidation
data from storage. The actual `invalidation` method remains the same.
This should make invalidation faster for storage providers that store
the invalidation remotely.
Sometimes QEMU will emit code that reads a local temporary *before* it
is assigned in the `TranslationBlock`. This usually happens when lifting
non-code, but it's still a problem since it leads to phis around the
dispatcher, which we don't want.
For example, consider the following x86-64 code:
```
0000000140002000 <.text>:
140002000: f0 lock
140002001: 38 00 cmpb %al, (%rax)
```
It leads to:
```
[libtcg] Translation starting from 0x140002000:Generic64
[libtcg] ---- 0000000040002000
[libtcg] mov_i64 loc2,rax
[libtcg] mov_i64 loc1,rax
[libtcg] mov_i64 cc_src,loc1
[libtcg] mov_i64 loc8,loc0
[libtcg] sub_i64 cc_dst,loc0,loc1
[libtcg] discard cc_src2
[libtcg] discard cc_op
```
Note how `loc0` is read before being initialized.
Currently we zero-initialize all the temporaries. It would be in
princple possible to detect those that need the initialization, which
would also enable us to emit a warning.
Make the interface required by `SingleOutputPipe` similar to other
piperuns by requiring a constructor, the use of `PipeRunArgument`s and
the implementation of a non-static `run` function.
This commit drops libptc in favor of its new form libtcg.
It brings several improvements, among which:
* The QEMU version we work on has been upgraded.
* CPUStateAccessAnalysis has been reimplemented in a way that makes it
easier to debug and solves some limitations (e.g., tracking leaking
pointers).
* Identification of pieces of the CPU state that are read by each helper
and fixing access to the CPU state is now performed at build-time.
* We no longer mmap the code we need to translate, dropping all the
issues related to code that needed to be mapped where something is
already present.
* We now have two distinct flavors of helper modules: the full one and
the "slim" one. The latter contains the definition only of functions
we intend to inline. It is used in most of the pipeline, a good thing
since we spend less time optimizing code we don't really care about.
The full module is only used on the re-compilation branch of the
pipeline.
* We no longer split the `cpu_loop` function.
* We change MetaAddress to rely on architectures from `model::` as
opposed to the LLVM ones.
* We no longer attach debug info to LLVM IR containing the original
assembly.
* We now verify that the lifted code only contains code we expect.
* Make the following private headers public:
* Lift/CPUStateAccessAnalysisPass.h
* Lift/CSVOffsets.h
* Lift/PTCDump.h
* Lift/VariableManager.h
* Move from revngSupport to revngLift:
* IRAnnotators.{h,cpp}
* SelfReferencingDbgAnnotationWriter.{h,cpp}
* Move from revngSupport to revngModel:
* FunctionTags.{h,cpp}
* ProgramCounterHandler.{h,cpp}
* Move from revngSupport to revngRecompile:
* OriginalAssemblyAnnotationWriter.{h,cpp}
This commit is the final step in ensuring all the pipes commit what they
should. It also asserts this actually happens, enabling us to easily
catch future problems.
Replace the stub implementation of invalidation with the proper
implementation. A ReadPathCache is added to each global so that it can
keep tracks of what target are associated to which read paths.
This is a big step to split revng-lift in two parts: one that only
writes the model and one that actually lifts to LLVM IR.
* Introduce `revng import binary`
* Split off `BinaryFile.h`
* Drop `revng.h`
* `GeneratedCodeBasicInfo`: use model
* Reduce role of `GeneratedCodeBasicInfo` in favor of
`model::Architecture` and `model::Register` methods
* `CodeGenerator`: adopt `RawBinaryView` and model
* `JumpTargetManager`: adopt `RawBinaryView` and model
* `ExternalJumpsHandler`: adopt model
* `InstructionTranslator`: discard `Architecture` in favor of
`EndianessMismatch`
* Many other changes
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.