Introduce LegacySegregateStackAccessesPipe
This commit restructures the SegregateStackAccesses pass and
SegregateStackAccessesPipe so that they can have 2 modes of operations:
1. Legacy, with the same behavior as the old version, injecting local
variables as custom llvm::Functions representing opcodes, such as
LocalVariable, AddressOf, StackFrameAllocator, and CallStackArguments
allocator.
2. Non-legacy, that is meant to operate with the new LocalVariableHelper
to inject local variables as regular alloca instructions, with
additional metadata to discriminate among them.
This commit renames the old SegregateStackAccessesPipe to
LegacySegregateStackAccessesPipe.
It then re-uses the old SegregateStackAccessesPipe name for a new pipe,
meant to work in non-legacy mode.
The pipeline definition YAML file is updated to keep using the legacy
version for now.
For now the implementation is still the same.
This commit changes the prototype of getCopeType, so that it now takes 2
arguments.
1. The llvm::Type returned by the Copy function. This can be any scalar
llvm::Type.
2. The llvm::type of the argument representing the reference to the
value being copied. This should be a pointer-sized integer, where
pointer-sized means with the same size of a pointer in the
architecture in the input binary.
The second argument is not strictly necessary for now, because the whole
decompilation framework expects a binary with a single architecture,
hence a well defined unambiguous pointer size.
This will be used fully only when we start supporting multiple binaries.
Whenever that happens, if we haven't already fully dropped the Copy
helper function we will have to update the associated
OpaqueFunctionsPool to a type pair as key: the return type and the type
of the argument.
This is preliminary to unifying the creation and handling of local
variable declarations, to simplify switching over to local variables
represented by plain allocas.
Before this commit, the DLA frontend wasn't initializing the size of
stack types properly, nor tracking the fact that they are not scalar.
These 2 problems were causing stack types to be merged with other types
in the DLA pipeline, possibly even scalar types and in some situations
changing the size of the stack type.
All these consequences were just wrong and need to be avoided because
they break assumptions of the DLA pipeline, leading to crashes in the
DLA backend, when trying update the model to integrate DLA's results.
This commit prevents all the mentioned wrong manipulation of stack
types, simply by correctly assigning an the size of the stack type from
the beginning, and marking it as non scalar.
Yield is not return. There is no need to verify the types being yielded.
f; is a valid expression statement, even when f is a function. In this
case a function is yielded, but that is fine.
Introduce the Enforce Single Exit pass, whose task is to normalize a
generic `ScopeGraph`, which may have multiple exit blocks (and/or
infinite loop regions), in order to have a single `sink_block` as exit
block.
This is done by adding a new entry block, a `sink_block`, and some
`scope_closer` edges (which are visible only on the `ScopeGraph`) that
enforce the property.
This is done taking inspiration from how the internally the
`PostDominatorTree` pass construct the temporary graph on which the post
dominance information is computed on.
Some unit tests are added in order to verify that the pass works as
expected.
Introduce the `ScopeCloser` and `GotoTarget` annotations in the IR, and
the relative necessary machinery, needed to handle scope closer and goto
edges for the new backend.
A specialization of the `llvm::GraphTraits`, called `ScopeGraph`, that
is able to handle both the above mentioned annotations is provided.
For the `llvm::GraphTraits` implementation, we introduce the
`GeneratorIterator` class, which uses a coroutine to store the status of
the iteration.
A debug logger pass is added, so that we are able to test the
functionality with `FileCheck`.
This commit ensures that parts of the model that must point to code
(specifically `Binary::EntryPoint`, `Binary::ExtraCodeAddresses` and
`Function::Entry`) actually point to a segment mapped as +x.
On the C++ side of revng it is important that LLVM's signal handlers are
registered within the initialization of `revng::InitRevng`, as this
allows downstream users (e.g. `revng daemon`) to preserve its signal
handlers before setting up the C++ infrastructure. In
`Tracing/Runner.cpp` there's `CommandHandler` which is statically
initialized and called `llvm::sys::AddSignalHandler`, this happened at
`dlopen` time, breaking the promise outlined above. Rework the code so
that the function is called lazily instead of statically.