Commit Graph

140 Commits

Author SHA1 Message Date
Lauri Vasama 5740ac0c9c Add defer-allocas LLVM pass 2026-05-13 15:32:33 +02:00
Pietro Fezzardi e41e243d68 ArithmeticToGEP: see through Add subtrees
Make cannotBePointer recurse through an Add when both of its
operands cannot be pointers. This lets canDisambiguatePointerOperand
identify the only viable base pointer of an outer Add even when the
offset side is itself an Add (or a deeper tree of Adds) whose leaves
are all clearly-non-pointer values, e.g.

    %offset = add i64 (%a*%b), (%c*%d)
    %result = add i64 %arg, %offset

Two unit tests cover the simple two-mul case and a deeper
four-mul binary-tree variant.
2026-05-08 11:37:11 +02:00
Pietro Fezzardi 6cecbdc800 STS: adopt ModuleSlotTracker in dumpToString
The ModuleSlotTracker is owned by a new function-level
ModuleSlotTrackerAnalysis whose Result holds the MST through a
unique_ptr (MST is neither copyable nor movable, but the FAM
cache requires a movable Result). Its run method calls
incorporateFunction on the function.

AvailableExpressionsAnalysis and InstructionToSerializePicker
fetch the MST via FAM.getResult<ModuleSlotTrackerAnalysis>(F) and
forward it down to AvailableExpressionsResult and the monotone
framework, so all dumpToString calls on the logging path share
the same slot-numbering cache.
2026-05-08 11:37:11 +02:00
Pietro Fezzardi 144aa3d2bf STS: drop workaround on call uses
Drop the workaround that skipped recursion into a Use whose User
was a CallInst with that Use as an arg operand. The original
motivation no longer holds with the rest of the recent changes,
and the workaround was suppressing valid serialisation
opportunities at call sites.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi f6574a1b6c STS: remove workaround on assigns to remove
Remove the workaround that suppressed the redundant
self-assignment that the pass now occasionally introduces in
non-legacy mode.

The remaining self-assignments are not bugs but sub-optimal C
generation, so we just disable the -Wself-assign warning in the
tests.

The sub-optimal code generation comes from passes that emit local
variables (allocas) before conversion to Clift, e.g. STS and
ExitSSA (with more planned). Each of these passes generates local
variables independently and they don't know about each other; the
order between them might also be swapped in the future. The only
clean fix is to unify them into a single transformation pass that
takes the results of multiple analyses (in the LLVM sense) and
emits local variables once. We have plans to do that, and when
it's done the warning can be re-enabled.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi 20fa0164e9 STS: check early for available replacements
Hoist the "use already picked in a previous iteration" early-out
to the very start of the per-use loop in
pickInstructionForMemoryRead, so that the rest of the body never
runs for uses that are going to be replaced anyway. The check
itself is unchanged.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi 1e94ca0711 Add SplitExponentialDataflow pass
Introduce a new canonicalisation pass that forces a small set of
exponential-dataflow-prone instructions (SelectInst plus the FShl
and FShr intrinsic patterns) to be stored into a dedicated local
variable. Without this, expanding their value into C expressions
during decompilation can blow up into exponential path enumeration
on real binaries.

This is a temporary workaround. A more principled split of
pathological dataflows is planned and will replace this pass.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi 9d5ea04690 STS: don't serialize variables with 0 uses
If an instruction picked for serialisation has zero uses, skip
emitting an alloca/copy pair for it. The Clifter recognises a
zero-use instruction as a statement and turns it into an
ExpressionStatement in place, preserving the ordering as if the
local variable had been emitted, but without the cost of a real
local variable. The legacy mode keeps the previous behaviour.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi e8670de56e STS: don't recur on selected uses
When a use of `I` is going to be replaced by a copy from
SelectedAssign and `User` does not write memory, there is no need
to recur on uses of `User`: those uses will be reading from
SelectedAssign's location, so the original memory read no longer
flows through them.

This avoids a class of redundant explorations and the spurious
serialisations they used to cause.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi 058d1843e6 STS: drop special case on store pointer operands
The "skip over the Assign operand" workaround is only needed in
legacy mode, where assignments are calls to opaque functions that
the rest of the pass cannot reason about. Gate it on `IsLegacy`
so that the non-legacy code path treats the pointer operand of a
StoreInst as a regular use, which is semantic-preserving and
unblocks downstream simplifications.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi f3639d4649 Add ExtractValueToGEP pass
Add a canonicalisation pass that rewrites extractvalue from a
pointer-returning struct as an i8 GEP plus a load. Together with
ArithmeticToGEP this lets later passes consume the result through
the same GEP-based interface they use for ordinary memory accesses.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi cb5702dc04 Add ArithmeticToGEP pass
Introduce the ArithmeticToGEP canonicalisation pass. It detects
pointers (LLVM-typed pointer values, model pointers flagged by the
"revng.pointers" metadata, and pointer-tagged extract values) and
rewrites integer arithmetic computed on top of them as i8 GEPs,
followed by a ptrtoint when the original use needs an integer.

For each obvious pointer the pass also walks backwards through Add
chains and disambiguates the pointer operand of each Add when the
other operand cannot be a pointer, so the rewrite extends to integer
arithmetic that only later flows into a pointer use.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi 6f76be8a0a STS: always use LLVM type for allocas
Drop the special case in serializeToLocalVariable that, for
struct-typed values, allocated `[N x i8]` of the struct's data-layout
size instead of an alloca of the struct type itself. The Clifter now
handles arbitrary alloca element types directly, so we can just use
the value's LLVM type.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi f7ff76551f STS: use LLVM AliasAnalysis
In non-legacy mode, replace the hand-written aliasing checks in
AEMFP::mayClobber with the answer of LLVM's AAManager, queried
through an AliasAnalysis * threaded into the framework. Legacy mode
keeps its previous logic, since it operates on calls to opaque
copy/assign functions that LLVM AA cannot reason about.

The pass now registers and consumes AAManager via the
FunctionAnalysisManager, with the usual GlobalsAA / module-proxy
cross-registration so that local AA can fall back to GlobalsAA
without crashing.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi ef77ad5ae9 STS: fold transfer function into AEMFP
Make AEMFP::mayClobber and AEMFP::applyTransferFunctionImpl proper
members instead of free functions taking the framework state as a
parameter. This removes a fair amount of boilerplate around passing
the AliasAnalysis pointer along, and keeps all the logic that
operates on the lattice in one place.

No behavioural change.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi 63cdca4e55 STS: switch to new PassManager
Convert SwitchToStatements to a new-PassManager FunctionPass and
introduce two function-level analyses,
AvailableExpressionsAnalysis and InstructionToSerializePicker,
backed by AnalysisInfoMixin. The non-legacy production entry point
now sets up an FAM, registers GlobalsAA proxies and runs the pass
through a FunctionPassManager; the legacy entry point keeps using
the legacy FunctionPass wrapper.

The pass also exposes a registerCallbacks hook so the upcoming unit
tests can load it from `revng opt -passes=switch-to-statements-test`
without dragging the model along.
2026-05-08 11:37:09 +02:00
Pietro Fezzardi 0cef8bd4ce STS: fold MFP result into AEResult class
Replace the loose ResultMap typedef with the
MFP::MFIResultMap<AEMFP<IsLegacy>> alias and keep the maximal fixed
point result inside AvailableExpressionsResult, so callers of
AEResult can fetch availability-at-a-point without reaching into a
separate map.

This is a structural step toward turning available-expressions
discovery into a real new-PassManager analysis.
2026-05-08 11:37:09 +02:00
Pietro Fezzardi a1bae709b6 STS: rename MFP framework class
Rename the AvailableExpressionsAnalysis class to
AvailableExpressionsMonotoneFramework (with the AEMFP alias)
because it does not satisfy the LLVM AnalysisInfoMixin contract;
keeping the "Analysis" name would clash with the actual
new-PassManager analysis introduced in a follow-up commit.
2026-05-08 11:37:09 +02:00
Pietro Fezzardi 81fd1a8b22 STS: use LLVM memory-access predicates
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.
2026-05-08 11:37:09 +02:00
Pietro Fezzardi a5c4973b77 STS: add operand access helpers
Add a set of templated helpers for getting the pointer/value
operands and operand-uses of copy and assign instructions. The
helpers exist because the legacy mode represents copies and
assignments as calls to opaque functions while the non-legacy mode
uses LoadInst and StoreInst directly: with these helpers the rest
of the pass can be written once and parameterised on IsLegacy.

The helpers are pure additions; nothing uses them yet.
2026-05-08 11:37:09 +02:00
Pietro Fezzardi 5e60091dab STS: rename FunctionPass wrapper
Rename the legacy FunctionPass wrapper class from
SwitchToStatements to SwitchToStatementsPass to free the
SwitchToStatements name for the upcoming new-PassManager pass that
will replace it.
2026-05-08 11:37:09 +02:00
Pietro Fezzardi 8ee6edfd15 Restructure LocalVariableBuilder
Reorganise LocalVariableBuilder so that the legacy and non-legacy
code paths are separated into two specialisations, and so that the
non-legacy specialisation does not need a model::Binary to operate.

This is a prerequisite for using LocalVariableBuilder from passes
that do not know about the model, e.g. unit tests for the new-PM
SwitchToStatements and the upcoming non-legacy decompilation
pipeline.
2026-05-08 11:37:09 +02:00
Pietro Fezzardi 762e3e9def Better RecursivelyDeleteTriviallyDeadInstructions 2026-04-10 15:27:24 +02:00
Pietro Fezzardi 23bd3f6c46 ExitSSA: don't declare to preserve the CFG 2026-04-10 15:27:24 +02:00
Pietro Fezzardi cc441ccd5c ExitSSA: fix insertion point past PHIs
Before this commit, the insertion point for load instructions was being
set before a PHINode, causing the IR to temporarily fail verification.
The effect of this logic bug did not propagate outside the pass, because
all PHINodes are removed at the end of the pass, but it made debugging
harder.

This commit fixes the problem by always setting the insert point after
all the PHINodes.
2026-04-10 15:27:24 +02:00
Pietro Fezzardi 59f91dcfc0 MakeModelGEP: drop unnecessary includes 2026-04-10 15:27:24 +02:00
Ivan Krysak 278b898793 llvm-to-clift -> clifter 2026-03-27 07:05:44 +00:00
Lauri Vasama 60e1684127 Generalize CommentPlacementHelper 2026-02-13 08:41:39 +02:00
Alessandro Di Federico 0bf97a9e68 getPointerSizedInteger: use model::Architecture
No need to get model::Binary.
2025-12-22 11:34:47 +01:00
Giacomo Vercesi 1632aeac73 Comment run* function with inlinable content
Add `TODO` comments to piperuns' `run*` functions that will have content
inlined once the old pipeline is removed.
2025-12-10 16:16:14 +01:00
Giacomo Vercesi 08154335e3 Add SwitchToStatements to pypeline 2025-12-10 16:16:14 +01:00
Giacomo Vercesi 3a08f8713b Add SimplifySwitch to pypeline 2025-12-10 15:05:53 +01:00
Alessandro Di Federico c883bed765 Drop Logger's StaticEnabled feature 2025-10-31 17:25:03 +01:00
Alessandro Di Federico 1429b526ab Introduce libtcg
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.
2025-10-31 17:25:03 +01:00
Lauri Vasama 086dc9fbc9 Remove RecursiveCoroutine operator*
* Add rc_eval to force evaluation.
2025-10-31 17:23:52 +01:00
Alessandro Di Federico 5a0a01794d PrettyIntFormattingPass: improve ImmArg handling 2025-10-29 15:10:18 +01:00
Alessandro Di Federico 118e916b6a HoistStructPhis: various improvements 2025-10-24 18:25:14 +02:00
Alessandro Di Federico ed3fc26166 MaterializedValue: handle loading mutable data 2025-10-24 18:20:54 +02:00
Alessandro Di Federico 4fb6b5f4e1 Minor changes 2025-10-24 18:20:48 +02:00
Pietro Fezzardi e32e224572 Treat llvm.fshl and llvm.fshr as statements
This forces all such instructions to get their value stored into a local
variable in SwitchToStatements.
The reason for doing this is that they often contribute to the formation
of pathological dataflows, causing exponential path explosion when
expanded into C expressions during decompilation.
Serializing their value into a dedicated local variable breaks such an
exponential path explosion.

This is a temporary workaround, that we've already put in place for
SelectInst too, and that will be replaced in the future by a more
principled approach for splitting pathological dataflows that lead to
exponential path esplosion.
2025-10-24 15:34:12 +02:00
Alessandro Di Federico f8bd4c3bac Move around some files in preparation for libtcg
* 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}
2025-10-24 15:34:11 +02:00
Ivan Krysak 2ba5ca3e3d Suppress selected IRBuilder checks 2025-10-21 19:17:37 +03:00
Ivan Krysak 3561c2b907 Adopt IRBuilder wrapper 2025-10-21 19:17:01 +03:00
Ivan Krysak 9e9e08a5bf Minor improvements 2025-10-21 16:28:20 +03:00
Pietro Fezzardi 4e4f194b4a SwitchToStatements: fix noAlias when writeOnly
This commit fixes a bug in the `noAlias` function, that failed to detect
two aliasing accesses when the second was writeOnly (so it did not read
memory).

That causes the transfer function of the Available Expression analysis
in SwitchToStatements to wrongly see some expressions as available,
because of the undetected aliasing write that would otherwise overwrite
the available expression.
2025-10-17 15:00:36 +02:00
Ivan Krysak 2b194ace78 Adopt ModuleSlotTracker-aware dumpToString
Sadly, it can only be easily taken advantage of in non-IR-modifying
passes, but even just this is better than nothing.
2025-09-10 17:44:02 +02:00
Ivan Krysak 374ee341fa Remove an unused logger 2025-09-10 17:44:02 +02:00
Ivan Krysak f4227dba42 Adopt isDebugLocationInvalid 2025-09-10 17:44:02 +02:00
Pietro Fezzardi 03e0de9458 Improve debug info propagation in legacy pipeline 2025-09-10 17:44:02 +02:00
Ivan Krysak 957d861918 HoistStructPhis: preserve debug information 2025-09-10 17:44:01 +02:00