Before this patch the dispatcher area was created all at once at a final
stage, however it's useful also while translating, since it keeps all the
code reachable, which is particularly important to be able to build a
exhaustive dominator tree.
* Create the dispatcher area when a new instance of `JumpTargetManager`
is created.
* Create a fake conditional branch to the dispatcher at the beginning of
the `root` function.
* Incrementally build the dispatcher's switch case in
`JumpTargetManager::getBlockAt`.
* Use `llvm::object` framework to obtain useful information from the ELF
binary such as pointer size and endianess.
* Introduce `CodeGenerator::importGlobalData`: import global (read-only
and writeable data) from the input binary directly into the generated
module.
* Introduce the `--linking-info` parameter: path to a CSV file where
sections containing global data extracted from the input binary are
listed with their name, start and end address.
* Expand the `Architecture` class with constructors and support accessor
methods.
`cpu_loop_exit` is used by QEMU to get back control from the translated
code while running an helper. Here we complete the inversion of the
hierarchy by transforming calls to `cpu_loop_exit` into calls to our
customized `cpu_loop`, which will handle syscalls and the like.
Since originally `cpu_loop_exit` was a noreturn function, we also need to
ensure that the semantic of its usage is preserved. We do this by setting
a global variable (`cpu_loop_exiting`) right after the call to
`cpu_loop_exit` and forcing the whole call stack to return immediately
if it's true.
* Introduce `CpuLoopExitPass`: replace all the calls to
`cpu_loop_exit` with a call to `cpu_loop`, a store true to
`cpu_loop_exiting` and a return. Then take all the callers and make
them return if `cpu_loop_exiting` is set. Once we get to the translated
function just reset `cpu_loop_exiting` to false.
* Introduce `VariableManager::computeEnvAddress`: generate code to
compute the offset of env . This computation is useful when
reference to the CPU state must be arificially introduced. This code
will be flattened by `CorrectCPUStateUsagePass` later.
`cpu_loop` is the main program loop used by QEMU during emulation. Here
we are interested in transforming it in a simple handler of exceptions
(e.g. signals and syscalls).
* Introduce `CpuLoopFunctionPass`: remove the outermost backedge in
`cpu_loop` and replace the call to cpu_*_exec with the exception index.
* Implement the support function `find_unique` which returns the only
element in a range satisfying a predicate, or, otherwise, asserts.
* Expand the function to replace with no-op or abort
* Factor out the code to replace function bodies (replaceFunction and
replaceFunctionWithRet)
* Replace functions before linking, directly in the helper module
* Move initialization and management of the structure describing the CPU
state (CPUStateType) into variablemanager.cpp.
* Support parts of CPU state outside "env" (e.g. the MIPSCPU
structure). Now "env" has an offset into the possibly larger CPU state
which we have to take into account where appropriate (see
VariableManager::envOffset).
* Link the helpers module into the generated module, including only what
is needed.
* Create some "no-op" or "abort" function corresponding to QEMU functions
not included in the helper module (e.g. logging and abort functions).
* Implement the CorrectCPUStateUsagePass pass, which starts from the
"env" global variable and looks for all its usages recursively, keeping
track of where pointers are pointing into the CPU state data structure,
and replaces all the load/stores with the global variable corresponding
to that specific field of the CPU state.
* After the linking phase, run SROA, the pass to adjust the CPU usage and
DCE.
* Let global variables have common linkage.