Commit Graph

1429 Commits

Author SHA1 Message Date
Alessandro Di Federico 9c86833004 Introduce forceFallthroughAfterHelper
`forceFallthroughAfterHelper` handles the situation where there isn't a
PC-store between a call to an helper and to `exitTB`, in this case, we
force a branch to the fallthrough PC.

This commit also simplifies `InstructionTranslator::translateCall`:
remove jump to the dispatcher after a call to an helper in case the PC
was saved and it has changed. We don't really need to do this, QEMU will
generate a call to `exitTB` has necessary or
`forceFallthroughAfterHelper` will take care of the thing.
2016-08-20 03:10:48 +02:00
Alessandro Di Federico d3a6442af2 Factor out and improve visitSuccessors
* The function now can take a `std::set` of basic blocks to ignore.
* The visitor function has now several options on how to proceed, and
  can express them through its return value.
* A serious bug in the implementation was also fixed.
2016-08-20 03:10:48 +02:00
Alessandro Di Federico ecdfab70a9 OSRA: don't propagate dead stores
Sometimes QEMU writes to register that are never used afterwards,
typically the `cmp` instruction sets several CPU flags which might be
ignored.

This becomes a problem when comparison are performed since they affect
the signedness of a BoundedValue. With this patch, we ignore their
effect if we can prove it's a dead store.
2016-08-20 03:10:48 +02:00
Alessandro Di Federico 7d55f3dd6b Handle multiple stores reaching a load
With this patch we basically handle a load as a sort of phi-node, since
we keep track of all the store/loads reaching a certain load, along with
their OSR, so that we can come up with smarter merging policies and
obtain more precise information.

This commit also introduce a change that leads to consider loads as
stores during propagation.  This heavily simplifies the store
propagation logic by considering load instruction as aliasing, and by,
consequently, propagating load (along with stores). This removes
completely the need for the concept of "conflicts".
2016-08-20 03:10:48 +02:00
Alessandro Di Federico 25aeb144eb Introduce isa_with_op
`isa_with_op` is like `dyn_cast` on steroids: it also check the type of
the operands.
2016-08-20 03:10:48 +02:00
Alessandro Di Federico 7ea0eafea6 If operandsByType fails, return a nullptr tuple 2016-08-20 03:10:48 +02:00
Alessandro Di Federico d0f5944133 Factor out reusable data structures 2016-08-20 03:10:48 +02:00
Alessandro Di Federico 430a7261b3 Introduce SimplifyComparisonPass
This pass helps us handling instructions like ARM's `blt` which compute
the result of the comparison by bit-fiddling with the bit sign of the
operands of a subtraction.

The idea is to have a series of known boolean expressions using `a`, `b'
and `c` as variables (e.g. the boolean expression corresponding to
"signed greater than") and compare their truth table against the one
being analyzed. In case of match, the comparison can be simplified.
2016-08-20 03:10:48 +02:00
Alessandro Di Federico 56c37f6cf6 Force execution of pinJTS 2016-08-20 03:10:47 +02:00
Alessandro Di Federico ba54372759 Check for "sum jumps" more often 2016-08-20 03:10:47 +02:00
Alessandro Di Federico acf7063aa6 Fix bugs in JumpTargetManager::getPC 2016-08-20 03:10:47 +02:00
Alessandro Di Federico f473731b0f Temporaly disable assertion 2016-08-20 03:10:47 +02:00
Alessandro Di Federico 23818e9da4 OSRA: handle register-relative memory accesses
Introduce the `MemoryAccess` class which represents the source of a
`LoadInst` or the destination of a `StoreInst` for which we want to
propagate an OSR.

This patch handles more elegantly the propagation and introduces support
for propagating OSRs through register + offset memory accesses, in
particular stack pointer- (or base pointer-)relative memory accesses,
which are common in unoptimized code and that led to miss some cases
that we otherwise handle correctly.
2016-08-20 03:10:47 +02:00
Alessandro Di Federico c0dbb6c5e7 Introduce pinning of potential jump targets
`TranslateDirectBranchesPass` now optionally depends on `SETPass`. This
allows us to reuse information obtained by SET and OSRA to pin potential
jump targets we detected to an `exitTB` call. In practice this means
that before a call to `exitTB` a conditional branch or a switch is
present to check if the destination of the jump is one of those we
expected, and if not, go to the dispatcher if the estimated destinations
were marked as approximate, or fail otherwise. Since this feature is
currently WIP, we never fail, we always go the dispatcher instead.

Since the amount of successors might grow during the iterative discovery
process, record the amount of successors as a `exitTB` argument.

* New `exitTB` argument: estimated number of successors.
* Move the code of the old implementation of the pass to the
  `pinConstantStore` function.
* Update routine for cleanup of post-exitTB instructions.
* `findNextExitTB`: more reliable implementation of the search for the
  next call to `exitTB`.
* Keep a reference to the basic block handling the failure of the
  dispatcher's switch, so we can use it to report failure of our jump
  target estimation.
2016-08-20 03:10:47 +02:00
Alessandro Di Federico 45dc6b3197 SET: track possible destinations of jumps
* `handleInstructionWithOSRA`: isolate usage of OSRA and increase its
  priority in SET.
* Let SET expose, for each store to the PC (i.e. a jump), the
  (approximate or exact) list of destination it can have.
* Extend the OperationsStack to explicitly track all the possible values
  that can be assumed by the instruction currently being analyzed. Note
  that before this patch we were only tracking possible jump targets by
  feeding them to JTM. The tracked values can be approximate or not,
  depending on the situation, and OperationsStack keeps track of this.
* Clean up some leftovers from the isolation of `SET` from `SETPass`.
2016-08-20 03:10:47 +02:00
Alessandro Di Federico 7d4e95b45e Associate BoundedValue to constant OSRs
The current modeling of constant OSRs prevent their merging on basic
blocks. This was due to the fact they had no `BoundedValue`
associated. This patch fixes this by representing them as:

    [120 + 0 * x, with x = (null, ?)]

instead of:

    [120 + 0 * x, with x = null]
2016-08-20 03:10:47 +02:00
Alessandro Di Federico 08be097123 Fix typos, add an assert, spread some const-ness 2016-08-20 03:10:47 +02:00
Alessandro Di Federico 4547b4731f Drop leftovers from weakness 2016-08-20 03:10:47 +02:00
Alessandro Di Federico 0ca6087018 Reorganize the iterative BB discovery process
The iteartive basic block discovery process has been reorganized to
minimize the amount of passes we run (in particular SROA, constant
propagation and early CSE) and to proceed until we don't "pin" any new
branch instruction, and not only until we're not able to discover any
new basic block.

The logging output has also been reworked to be more informative.
2016-08-20 03:10:47 +02:00
Alessandro Di Federico 041ea8726d Introduce predecessors and successors 2016-08-20 03:10:47 +02:00
Alessandro Di Federico 89697ff34e Reorganize SET
* Isolate the SET algorithm from the SETPass
* Isolate the processing of an instruction in a function to be able to
  use returns to easily signal if we were able to handle the instruction
  or if we gave up
* Add some documentation
2016-08-20 03:10:47 +02:00
Alessandro Di Federico b3fb106d41 Handle change of an OSR's associated value
Enqueue users of an instruction if the value associated to its OSR
changes.
2016-08-20 03:10:46 +02:00
Alessandro Di Federico e39ae91a37 Improve OSRA's handling of overtaken values
Keep a map to associate overtaken and overtaker load/store values, and
keep it valid for the whole analysis.
2016-08-20 03:10:46 +02:00
Alessandro Di Federico e986148e41 Prevent leak of cloned Instructions
SET needs to create clones of instructions, which are not inserted in
any basic block, therefore we have to manually handle their
lifetime. This patch delegates this role to the `OperationsStack`: when
an element is being popped from the stack the OS checks if it belongs to
a basic block and if it doesn't, it deletes it.
2016-08-20 03:10:46 +02:00
Alessandro Di Federico ffa4639b08 Workaround for BBs including other BBs 2016-08-20 03:10:46 +02:00
Alessandro Di Federico a997a0525a Use opcode names in basic block statistics 2016-08-20 03:10:46 +02:00
Alessandro Di Federico 1a5fc0f519 Introduce collection of basic block statistics
Let revamb produce a CSV file containing statistics about the translated
input basic blocks for further analysis (e.g., identify false
positives).
2016-08-20 03:10:46 +02:00
Alessandro Di Federico 8d34cecb90 Catch undefined behavior due to excessive shift 2016-08-20 03:10:46 +02:00
Alessandro Di Federico eb8e589a4d Don't access boundedValue if it's not available 2016-08-20 03:10:46 +02:00
Alessandro Di Federico 4dd3638a46 Fix overflow when we check membership to a segment
Checking if a range of addresses belong to a segment should be
implemented by checking if the start and end address belong to the
address, the `Start <= Address && Address + Size < End` approach leads
to subtle errors when `Address` is close to the maximum representable
value due to an overflow.
2016-08-20 03:10:46 +02:00
Alessandro Di Federico dbb462a9a5 Fix issues in release builds
Mainly fixes due to the absence of asserts.
2016-08-20 03:10:46 +02:00
Alessandro Di Federico 994f518e14 Use ld.bfd linker as linker by default 2016-08-20 03:10:46 +02:00
Alessandro Di Federico 4e04f0eed5 Copy run-time files to build directory 2016-08-20 03:10:46 +02:00
Alessandro Di Federico db030d6757 Downgrade to CMake 2.8 2016-08-20 03:10:45 +02:00
Alessandro Di Federico d57b222ca2 Fix return type while translating bswap 2016-08-20 03:10:45 +02:00
Alessandro Di Federico 710954ee51 Use a single, shared, cast for local temporaries 2016-08-20 03:10:45 +02:00
Alessandro Di Federico da2b42901b Reset temporaries for each new input instruction 2016-08-20 03:10:45 +02:00
Alessandro Di Federico 0ae9999be6 Improve LLVM IR annotations
Reduce the amount of "\n" and do not print again the original
instruction unless the last instruction that had a decoration, if any,
was associated with a different instruction.
2016-08-20 03:10:45 +02:00
Alessandro Di Federico ff52a06c74 Unify return values for opcode translations
Now `CodeGenerator::translate`, `CodeGenerator::translateCall` and
`CodeGenerator::newInstruction` all return
`CodeGenerator::TranslationResult` which covers all the possible results
that the caller needs to handle such abort, stop translation, force a
new basic block or simply proceed.

This patch also prevents reading a PTC temporary that has never been
written (typically due to a mistranslation) by emitting an abort.
2016-08-20 03:10:45 +02:00
Alessandro Di Federico 329fcb3707 Introduce tracing support 2016-08-20 03:10:45 +02:00
Alessandro Di Federico 0d035a93e1 Introduce clang support: fixes and cleanup 2016-08-20 03:10:45 +02:00
Alessandro Di Federico 6acc701b54 Documentation and some refactoring 2016-08-20 03:10:45 +02:00
Alessandro Di Federico 57721ff851 Isolate SET
* Rename `JumpTargetsFromConstantsPass` to `SET`
* Move `SET` to set.{cpp,h}
* Remove some useless includes
2016-08-20 03:10:45 +02:00
Alessandro Di Federico fbca5bba2e Import OSRA and update SET
* Import OSRA
* Improve the SET (aka `JumpTargetFromConstants`) by introducing the
  `OperationsStack` class.
* Review `harvest` logic
* Allow to disable OSRA (along with the sumjump heuristic)
* Take the core of `getNextPC` out of it and move it to `getPC`, a
  function returning both the current and the next PC. Also, fix a bug
  when reaching the beginning of a basic block.
* Detect "reliable" jump targets: a "reliable" jump target is a jump
  target obtained from a store to a PC but it's not a fallthrough jump.
2016-08-20 03:10:39 +02:00
Alessandro Di Federico 670ca9d990 Remove the specila handling of null-jumps 2016-04-14 16:10:13 +02:00
Alessandro Di Federico 1ca682e3d1 Implement "unvisit" logic for SET 2016-04-14 16:10:13 +02:00
Alessandro Di Federico b74f09cad4 support.c: introduce unknownPC plus fixes
`unknownPC` is an extern function we expect to be linked to the output
which is called when we have to crash due to an unexpected jump target.

* Remove unused references to register variables, now only need the
  stack pointer
* Fix bug in how the auxiliary values were pushed on the stack.
* Push 0 HW_CAPs
* Implement some glib's functions
2016-04-14 16:10:13 +02:00
Alessandro Di Federico 7fa391381b Perform aggressive specialization on helpers
Since one of our requirements is to have all the accesses to the CPU
state explicit, we used to modify the helper functions depending on the
parameters used to call them. This was fine when we were supporting a
reduced set of helpers, but now this is not acceptable since the calling
code can call helpers in different ways. We circumvent the problem by
creating a distinct function specialization for call.
2016-04-14 16:10:13 +02:00
Alessandro Di Federico cda7bbd94e Extend support for partial CPU state reads/writes
This patch implements `VariableManager::storeToCPUStateOffset` and
`VariableManager::loadFromCPUStateOffset`, which handle in a single
point all the accesses by offset to the CPU state.

* `getTypeAtOffset`: introduce a feature to easily debug how we compute
  which field is at a specified offset in the CPU state (`--debug
  type-at-offset`).
* Let `getTypeAtOffset` and its wrappers return the offset inside a
  field of the CPU state (useful when accessing the third byte of an
  integer).
* Use a dedicated class for the `CorrectCPUStateUsage` worklist
2016-04-14 16:10:13 +02:00
Alessandro Di Federico 74ed2abd53 Implement a set of helpers for Constant unboxing 2016-04-14 16:10:13 +02:00