7705 Commits

Author SHA1 Message Date
Pietro Fezzardi b8f10c2738 Clifter: drop type caches
Now that we need the llvm::DataLayout for e.g. computing pointer
sizes, caching pointer types becomes risky: different DataLayouts
coming from different LLVM Modules could disagree on the pointer
size, and securing against this would require clearing the caches
at every call to import.

Given that the caches in practice were not caching operations that
are supposed to be slow, just drop all the type caches to simplify
the codebase.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi 6ecbbbbb37 Clifter: use llvm::DataLayout for pointer size
Replace the standalone PointerSize field with a pointer to the
function's llvm::DataLayout, and read the pointer size off the
DataLayout when needed. This keeps the importer aligned with what
LLVM thinks the pointer size is, instead of relying on an external
source of truth that may go stale.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi 51c5131554 Clifter.h: include Function.h instead of Module.h
The Clifter public header only needs llvm::Function, not the full
llvm::Module definition, so drop the Module.h include. This
shaves a non-trivial amount of compile time off the translation
units that depend on Clifter.h without pulling in Module.h
themselves.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi 00db5561e3 Clifter: use llvm::DataLayout for helper structs
Use llvm::DataLayout to compute helper struct layouts in the
Clifter, mirroring what HelpersToHeader does. The layout query
replaces a couple of hand-rolled offset/size computations and
keeps the importer in sync with what LLVM and the helpers header
believe about each helper struct.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi 93d6e76b5b HelpersToHeader: use DataLayout for helper structs
When emitting the header for QEMU/revng helper struct types, use
the LLVM DataLayout to walk the StructType, so that field offsets
and the overall struct size match what LLVM actually produces. The
old code printed fields in declaration order without consulting
the layout, which broke whenever the struct included padding.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi 13fc8b0930 Strip dead prototypes before emitting C
Run -strip-dead-prototypes as part of the LLVM-pass list invoked
just before the Clifter, so that all unused helpers are stripped
away. In particular, this prevents some LLVM intrinsics that
return structs containing i1 (e.g. the overflow intrinsics) from
ending up in the C output and tripping later passes.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi a546be1386 CBackend: emit array assignments
Teach CliftToCEmitter how to emit assignments and bitcasts whose
target type is an array, by emitting calls to the new
assign_array and bit_cast_to_array macros. The shape of the call
encodes the element type and the number of elements, which is what
the macros need to expand correctly.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi 0251ddd37d Add assign_array and bit_cast_to_array
assign_array is necessary as a fallback for when the decompiled C
code may need assignments among array types. bit_cast_to_array is
necessary because when the target type of a bitcast is an array
the regular bit_cast macro is not enough.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi 3bf02e6f60 Unify implementation of bit_cast, requiring typeof
Rework primitive-types.h so that the various bit_cast macros share
a single implementation based on `typeof`/`__typeof__`. As a
consequence both keywords are added to the model's reserved-name
set so that user identifiers cannot collide with them.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi bcc9935023 Clifter: generate opaque types for arrays
When importing an llvm::ArrayType, emit a Clift StructType with the
OpaqueType rank in its handle and a single i8 array field of the
right byte size, instead of a real array type. This avoids
exposing C array types as rvalues in the generated code, which is
a foot-gun because array rvalues immediately decay to pointers,
and provides a single name (via the existing OpaqueType infra) for
arrays of equal byte size.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi c96765412b Clifter: support byte-based GEPs
Rework the GEP-importing logic to handle the i8-typed,
byte-strided GEPs produced by ArithmeticToGEP (and natively used
elsewhere) in addition to the structured ones it already supported.
Indices are now interpreted as byte offsets and the importer walks
the model type tree at byte granularity to materialise the right
sequence of field/element accesses.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi 4f04d3c58d Drop !revng.variable_type metadata
Drop the !revng.variable_type metadata and the matching helpers,
along with the only place in the Clifter that still consumed them.
After the previous LVB cleanup nothing emits this metadata, and the
model variable type can be reconstructed from the alloca's array
type alone.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi 80a33109eb Print opaque types in model header
Emit forward declarations and definitions of the opaque-array
artificial structs from the C model header (and from the helpers
header). Definitions are gated on a new DefineOpaqueTypes flag
threaded through PTMLHeaderBuilder::printModelHeader so that the
helpers header keeps emitting only the declarations.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi 2f692127f9 OpaqueType: model verification and name import
Teach Clift's verify-against-model and ImportDescriptiveInfo
visitors about types whose handle has the OpaqueType rank: the
verifier rejects non-struct types with such handles, and the name
importer fills in the type's mutable name with
NameBuilder::opaqueTypeName based on the wrapped byte size.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi 21063f1844 NameBuilder: support opaque types
Teach NameBuilder and ModelCBuilder how to produce names and
references for opaque-array types: NameBuilder gains
opaqueTypeName(ByteSize), ModelCBuilder gains the matching
reference and definition tags. Both rely on the new
Configuration::OpaqueTypePrefix.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi 306e8a93f1 Add OpaqueTypePrefix to model schema
Add an OpaqueTypePrefix string to the model configuration with
default `opaque_type_`. This is used to build the C name of the
artificial structs that wrap model array types and keeps the prefix
configurable alongside the other artificial-name prefixes.
2026-05-08 11:37:10 +02:00
Pietro Fezzardi 5a429d6f52 Add OpaqueType ranks
Define a new "opaque-type" rank in revng/Pipes/Ranks.h, keyed by
the byte size of the wrapped type. This rank is used by upcoming
commits to identify the artificial structs that wrap model array
types in Clift.
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 9111f127dd STS: add unit tests
Add an llvm-lit test suite for the new-PassManager
SwitchToStatements pass, exercised via
`revng opt -passes=switch-to-statements-test` (registered by the
pass's registerCallbacks hook). The tests cover load/store
serialisation, side-effecting calls and a few representative
patterns where an instruction must be picked for serialisation
because its memory read is no longer available at one of its uses.
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 f71200ae00 Segregate: emit "revng.pointers" metadata
Extend SegregateStackAccessesPass to attach the "revng.pointers"
metadata on every llvm::Function it rewrites, and on every CallInst
it produces.

The metadata represents, in a model-agnostic way, which arguments
and return values of a call or function (both formal and actual)
are pointer-typed in the model. Later passes consume this so that
they can stay model-agnostic.
2026-05-08 11:37:09 +02:00
Pietro Fezzardi dc3f3f9c48 Add helpers for "revng.pointers" metadata
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.
2026-05-08 11:37:09 +02:00
Pietro Fezzardi 24ed2597e2 LVB: don't emit !revng.variable_type metadata
createLocalVariable no longer attaches the !revng.variable_type
metadata to the alloca. The model variable type can be reconstructed
from the array-typed alloca alone, so the metadata is redundant. The
metadata itself will be dropped from the codebase in a follow-up
commit.
2026-05-08 11:37:09 +02:00
Pietro Fezzardi 513b51e82d LVB: use NonDebugInfoCheckingIRBuilder
Switch the IRBuilder used by createCallStackArgumentVariable and
createStackFrameVariable to revng::NonDebugInfoCheckingIRBuilder, in
line with the rest of the LocalVariableBuilder code paths. There is
no functional change for builds that already attach debug info, just
a stricter check on builds where it is unexpectedly missing.
2026-05-08 11:37:09 +02:00
Pietro Fezzardi 197bdd346d FieldAccessReplacement: fix type of array indices
When emitting the synthesized integer index for an access whose
LinearCombination contains a variable, use the variable's own type
for the constant `[0]` immediate (and for the rest of the index
arithmetic) instead of always using a generic pointer-sized integer.
With model-sized pointers in the picture the two integer widths can
differ, and using the wrong one trips Clift's type checking
downstream.
2026-05-08 11:37:09 +02:00
Pietro Fezzardi 9700f1ab5e Merge branch 'feature/clift-implicit-cast-elision' 2026-05-04 11:35:39 +02:00
Lauri Vasama a46b3eead9 Remove x86-64 reduce-c-casts test 2026-05-04 10:49:08 +03:00
Lauri Vasama 90a327b10f Add clifter-input debug artifact 2026-05-04 10:49:07 +03:00
Lauri Vasama c7e3a12657 Add implicit cast elision pass 2026-05-04 10:49:07 +03:00
Lauri Vasama 15df286a6f Implement clift.implicit support in the backend 2026-05-04 10:49:06 +03:00
Lauri Vasama ed20fd5cd9 Collapse casts after legalization 2026-05-04 10:49:06 +03:00
Lauri Vasama ad0c466d6d Remove revng/Support/CTarget.h 2026-05-04 10:49:06 +03:00
Lauri Vasama 04fe27b8e9 Migrate Clift users to CDataModel 2026-05-04 10:49:03 +03:00
Lauri Vasama dd4e452f96 Add data model import pipes 2026-05-04 10:48:16 +03:00
Lauri Vasama f6d2eaea4b Add Clift DataModelAttr 2026-05-04 10:48:03 +03:00
Lauri Vasama 9c5338913d Add TargetABI field in the model 2026-05-04 10:48:03 +03:00
Lauri Vasama 0ab9f769dd Add CDataModel in ABI definition 2026-05-02 17:21:47 +03:00
Lauri Vasama 27fb305c5a Add revng/Support/CDataModel
This structure describes the data model used by a C ABI.
2026-04-30 15:09:16 +03:00
Lauri Vasama 9bd76c71f9 Split up Clift optimization pipe 2026-04-30 15:09:16 +03:00
Lauri Vasama 7f2bf61d10 Move cast collapsing rewrite to a separate set 2026-04-30 15:09:16 +03:00