Unfortunately, in DWARF, there's no widespread indicator on whether a
function is regular ARM or Thumb. Therefore, in this commit, instead of
blindly creating a new function, we first check if, in the model, we
already have a function at that address.
This means that, if we have a Thumb function in DWARF, but it doesn't
already exist in the model, we will import as regular ARM, which is
wrong.
Specifically, this can happen with `revng model import debug-info`.
Mirror the existing pointer overload of dumpToString but thread a
ModuleSlotTracker through to the underlying call, so that callers
can amortise slot-numbering work across many dumps. The new
overload returns "nullptr" when the input pointer is null,
matching the non-MST pointer overload.
Replace the home-grown hasSideEffects, mayHaveSideEffects,
mayWriteToMemory and mayReadMemory helpers (in
DecompilationHelpers.h) with the equivalent predicates from
llvm::Instruction. The legacy code paths still need a few extra
checks, so the templated wrappers in SwitchToStatements.cpp
specialise on IsLegacy and fall back to the LLVM predicates in
non-legacy mode.
This removes the now-unused helpers from DecompilationHelpers.h.
Introduce templated readers and writers for the "revng.pointers"
metadata in revng/Support/IRHelpers.h. The metadata is a pair of
boolean tuples describing, for an llvm::Function or llvm::CallInst,
which of its return values and which of its argument operands are
pointer-typed in the model. This is the model-agnostic
representation later passes (e.g. ArithmeticToGEP) consume to find
pointers without having to look at the model directly.
Refactor the binary import and dependency resolution infrastructure to
support multiple platforms (Linux, Windows, macOS) via a
configuration-driven root system.
Major changes:
* Overhaul PDB and DWARF importers for platform-aware debug info
loading.
* Refactor LDDTree into a template-based architecture with
platform-specific implementations (ELF, PE/COFF).
* Mostly rewrite the PDB importer, which had significant limitations.
This allows the existing annotation registry to be reused in a more
convenient nature. Before now, it was only used for *parsing* or,
rather, *verifying* annotations. Now that we can take advantage of
it for emission as well, there's more control it needs to provide
in particular as far as annotation arguments are concerned.
In the new pipeline the root module is split off in its individual
isolated modules at the end of `isolate`. Before splitting, there are a
lot of global variables in the root module and only a small part is
going to be needed after splitting for each module. To avoid excessive
memory usage employ `ConservativeModuleCloner` in `Isolate` so that
only the needed global variables are actually cloned when splitting off.
Re-organize the variants of `libtcg-helpers-*.bc` as such:
* `libtcg-helpers-full-$ARCH.bc`: unchanged, contains all helper
function with their bodies and all CSVs.
* `libtcg-helpers-declarations-only-$ARCH.bc`: all helper
functions have been turned to declarations. All CSVs (except a couple
of special ones) have been dropped.
* `libtcg-helpers-to-inline-$ARCH.bc`: only functions with the
`revng_inline` section retain their body. Only CSVs that are used by
these functions are present.
Lift now loads only the `declarations-only` variant of helpers, as
their body is not required until `inline-helpers`. In `inline-helpers`
the `to-inline` variant is loaded and linked, which then allows the
helpers to be inlined.
Add the `SimplePassManager` and `SimpleFunctionPassManager` classes
which add wrappers around the new LLVM pass manager. Change all the
applicable uses of the legacy pass manager with the wrapper.
Add infrastructure to pypeline that allows containers to be notified
when they are being used last, this allows two things:
* `Pipe`s eagerly clearing those containers once they are done reading
their contents
* `ScheduledTask`s clearing those out at the end of their execution in
case the pipe did not do it
This overall should improve memory usage as container no longer take up
memory if they are no longer used as part of a `Schedule`.
Fix the behavior of binary importers by propagating the path of the
input binary from revng2 downwards, allowing finding `.debug` files in
the correct paths.
When initializing `revng::InitRevng` it is assumed by its parent,
`InitLLVM`, that the lifetime of `Argv` and be equivalent to
static, because it might be later retrieved to print it in case of a
crash. This works with the traditional `main`, however in the pipebox
the string passed are not guaranteed to have that lifetime. This commits
moves ownership of the strings to a class that stores them to avoid this
problem.
Add another container for LLVM modules. This one stores one
`llvm::Module` per function (all modules share the same
`llvm::LLVMContext` for performance reasons).
In the constructor of `InitRevng` also call all the `llvm::initialize*`
functions. This is done to be less implementation-specific and having
these functions be called in
`LLVMPipelineRegistry.libraryInitialization`.
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}