4073 Commits

Author SHA1 Message Date
Ivan Krysak ea785998ec Minor improvements 2026-06-15 11:47:41 +02:00
Pietro Fezzardi b4aaf5814f ExitSSAPass.cpp: drop unused #include 2026-06-15 11:46:44 +02:00
Alessandro Di Federico 58c5d942a0 BitLiveness: fix BitLivenessAnnotatedWriter typo 2026-06-11 17:39:53 +02:00
Alessandro Di Federico 6a594a9133 MFP: rename namespace MFP into mfp 2026-06-11 17:39:53 +02:00
Alessandro Di Federico 841b5dab71 SegregateStackAccesses: rewrite around ExtraState
Move all per-function state and logic into a new SegregateFunctionStack
worker, so the pass class itself only holds module-wide state and the
runOnFunction body is just upgrade() + segregate(). The discovery loop
now uses the MFP ExtraState surface to capture the analysis value
before each interesting program point, replacing the splitBasicBlock
trick that introduced fake nodes only to read the lattice value at
them.

Other changes that ride along:
- StackOffsetCache memoizes getStackOffset per function.
- findAllWriters does a single sorted sweep instead of a quadratic
  scan over Ranges.
- The pipeline gains a stack-accesses-segregated artifact entry.
- Test fixtures (filecheck.ll, override.yml, segregate-stack-accesses
  configuration) are updated to match the new IR shape.
2026-06-11 17:39:53 +02:00
Alessandro Di Federico d03e62c250 MFP: add ExtraState, MFPConfiguration, variant
Three closely-coupled changes that have to land together to keep
every caller compiling:

- Introduce a per-instance ExtraState recording surface (with a
  NoExtraState default) and thread it through applyTransferFunction.
- Replace getMaximalFixedPoint's positional arg list with a single
  MFPConfiguration struct, so callers spell out only the fields they
  need.
- Replace the EntryLabels pointer with an Entry/All/vector* variant
  so callers can ask for the graph entry, every node, or a custom
  list without juggling extra arguments.

Update every existing caller for the new signatures and switch
Liveness::GraphType to a plain Function* (with the inverse
GraphTraits selected at call sites).
2026-06-11 17:39:53 +02:00
Alessandro Di Federico c306157596 SplitStructPhis: replace HoistStructPhis
Replace the hoist-struct-phis pass with a split-struct-phis pass that
breaks struct PHI nodes into per-field PHIs instead of moving them
out, and update both pipelines to use the new name.
2026-06-11 17:39:53 +02:00
Alessandro Di Federico 4150afc33f StructInitializers: add createCall; EmitBody flag
Split createReturn into a reusable createCall that emits the
struct-initializer call without wrapping it in a return. An EmitBody
flag lets callers create the declaration but skip the body, useful
when the body would later be stripped.
2026-06-11 17:39:53 +02:00
Alessandro Di Federico 51526e9777 ABI/Layout: move YAML traits to header
The YAML traits for Layout (and friends) move into Layout.h so callers
can serialize a Layout directly without pulling in Layout.cpp's
internals. As a result StackSpan gains default-initialized fields and
its operator+ is hoisted to a free function (with the symmetric
uint64+StackSpan overload) so it works with the YAML mapping.
2026-06-11 17:39:53 +02:00
Alessandro Di Federico fbe825d66a ABI/Clifter: drop SPTAR special case in returns
Drop the SPTAR-specific special case in layoutToLLVMFunctionType: all
ModelAggregate-returning functions now use the same array-of-i8 return
type. Clifter is updated accordingly to treat any aggregate return the
same way, removing the SPTAR-specific branches that were just dead
code after the type unification.
2026-06-11 17:39:53 +02:00
Alessandro Di Federico 4daa276c45 DwarfToModelConverter: skip wide float primitives 2026-06-11 17:39:52 +02:00
Alessandro Di Federico ce6eda6836 FunctionTags: drop MemoryEffects on AddressOf pool 2026-06-11 17:39:52 +02:00
Alessandro Di Federico 1ca8239b65 ImplicitCastElision: elide casts only on integrals
For comparison operators (==, !=, <, >, <=, >=) the elision is only
sound when both operands are of integral type; otherwise we'd be
changing the kind of comparison being performed.
2026-06-11 17:39:52 +02:00
Alessandro Di Federico 8973f6e55c CliftEmitC: drop assert in emitUndefExpression 2026-06-11 17:39:52 +02:00
Alessandro Di Federico f28ca69921 Lift: drop redundant TranslateTask.complete()
The TranslateTask is immediately advanced to a new step right after,
which marks the previous step as complete automatically.
2026-06-11 17:39:52 +02:00
Alessandro Di Federico 2a2ef04ec0 Minor changes
Comment refresh, formatting and small no-op tweaks across unrelated
files.
2026-06-11 17:39:52 +02:00
Pietro Fezzardi ad18e6695c ExitSSA: make edge-splitting deterministic
Replace the stable_sort that ordered (block, value) entries by raw
BasicBlock* address in getIncomingUsesOfValuesFromBlocks with a
MapVector that groups entries by block in first-encountered
insertion order, and add a per-block stable_sort by use count
(descending). Same-block contiguity is now structural rather than
enforced by a sort, and the order in which the split basic blocks
are created and appended to the function no longer depends on
pointer values that vary across runs. The within-block ordering,
the use-count tie-breaking, and the rest of the edge-splitting
algorithm are preserved.
2026-06-03 16:33:15 +02:00
Pietro Fezzardi 1c0c28081d STS: reduce unnecessary use of llvm namespace 2026-06-03 16:33:15 +02:00
Pietro Fezzardi 197219673f STS: drop dependency from LVB in non-legacy mode
After we drop legacy mode, the only user of LocalVariableBuilder will be
SegregateStackAccesses. This is possible thanks to the fact that
dropping the legacy mode will demistify local variables and turn them
into plain allocas accessed via loads/stores. This will end the need for
a centralized place to deal with local variable creation, that is caused
by the various ad-hoc manipulations we've been doing for a long time in
legacy mode.
2026-06-03 16:33:15 +02:00
Pietro Fezzardi bbb713f548 LegacyStackAllocators: only depend on input intptr 2026-06-03 16:33:15 +02:00
Pietro Fezzardi 76b10703b1 TypeDependencyGraph: rename Mode to ModelMode 2026-06-03 16:33:15 +02:00
Pietro Fezzardi 18054eeee2 DLACollapseSingleChild: fix pointer loops
This commit fixes a situation where CollapseSingleChild could introduce
infinite loops composed entirely of pointer edges, which would end up in
making the DLA backend go out-of-memory.

This happened when collapsing a Child at offset 0 into a Parent node,
when Child had a pointer edge going to Parent.
The pointer edge needed not to be at step one, but it could possibly be
a pointer-to-pointer to Parent, at any depth.

After merging Child into Parent this would lead to a node pointing to
itself, which is a forbidden pointer loop in the graph.

This commit catches the pattern and prevents it to merge Child into
Parent.
2026-06-03 16:33:15 +02:00
Alessandro Di Federico bc4872f2f4 DwarfImporter: handle STT_GNU_IFUNC symbols
In DWARF, `STT_GNU_IFUNC` symbols are associated to a function prototype
returning the actual prototype.
2026-06-03 13:59:53 +02:00
Alessandro Di Federico 9e9451247b Drop --import-debug-info command-line option
The --import-debug-info CLI flag and the ImporterOptions::
AdditionalDebugInfoPaths field it populated were a side-channel that
loaded extra DWARF files outside the normal ELF dependency-resolution
path. It bypassed the symbol-aware machinery and is no longer needed.
2026-06-03 13:59:53 +02:00
Alessandro Di Federico 9596cf1151 Rework dropTypesDependingOnDefinitions 2026-06-03 13:58:33 +02:00
Andrea Gussoni 35b0da291a InlineHelpers: add post-inlining no-GEP verifier
Add `PostInlineHelpersVerifyPass`, a `ModulePass` derived class that
aborts on any `getelementptr` instruction found in any Isolated
function. `inline-helpers` is the only pass in the post-isolate chain
that could import a GEP into an Isolated function by inlining a helper
body that contains one, so the verifier is invoked at the end of
`InlineHelpersPass::runOnModule`. In this way, we early catch this
invariant on the IR.
2026-05-29 17:12:35 +02:00
Andrea Gussoni 9c8808fd9e InlineHelpers: Use revng.inline.policy metadata
Use the helper's `!revng.inline.policy` and inline at each call site
only when every critical argument is constant.
2026-05-29 17:12:35 +02:00
Andrea Gussoni f2f63dd73c PromoteCSVs: compute revng.inline.policy
When PromoteCSVs synthesizes a CSV-promoted wrapper for a helper,
compute the `!revng.inline.policy` metadata  so `InlineHelpers` sees the
static policy at the wrapper's call site.
2026-05-29 17:12:35 +02:00
Andrea Gussoni 8443f06170 DetectUninlinableHelpers: introduce pass
Introduce a pass which statically demotes some helpers from candidates
for inlining:
1) Helpers which are part of SCC on the callgraph.
2) Helpers which contains an `insertvalue`.
3) Helpers which _fail_ the `CriticalArguments` criterion.

A critical argument is defined starting from the critical operand
definition.
A critical operand is either the condition of a `switch` instruction or
the indices of a `getelementptr` instruction.
If the dataflow computing the the operand trace back to a formal
parameter of the function, that parameter will be considered critical
when attempting the inlining of the helper.

In case each condition is satisfied, the `revng.inline.policy` metadata
is attached to the function, so that it can be used at _inline_ time to
take the decision based on the critical arguments constantness.

The metadata is encoded as an `iN` integer with N = `arg_size() + 1`:
the extra most-significant bit is always zero so LLVM's signed-decimal
`iN` printer renders the value positively (avoiding e.g. `!{i2 -2}`).

The (de)serialisation primitives live in `revng/Support/IRHelpers.h`
as `serializeInliningPolicy` / `deserializeInliningPolicy` so the
runtime `revngFunctionIsolation` doesn't need to link the build-time
`revngHelperInliningAnalyses` to read the metadata back.
2026-05-29 17:12:35 +02:00
Andrea Gussoni 8103e2046c MarkInlineHelpersUpTo: introduce pass
Introduce a build-time pass that tags every QEMU helper transitively
reaching a function defined under one of the configured runtime-library
directories (currently `fpu/` only) as `revng_inline`. The intent is to
make the lift pipeline surface "leaf-level" runtime-library calls (e.g.
softfloat ops) directly in the lifted IR by inlining away every wrapper
helper that sits between QEMU's `helper_*` boundary and the leaf.

We also gate the tagging by a per-function body-size budget.

The pass is run in the pipeline building the `libtcg-helpers-full-*.bc`
artifacts.
2026-05-29 17:12:35 +02:00
Andrea Gussoni 04a275d91b FixHelpers: switch on env-relative offsets
Fix the `switch` emitted by `fix-helpers` so that we express the address
as a `env`-relative offset.
2026-05-29 17:12:35 +02:00
Andrea Gussoni 76fedfb249 Clifter: remove abbreviation and use alignTo
Remove an abbreviation and use `llvm::alignTo` to compute the
alignment.
2026-05-29 17:12:35 +02:00
Andrea Gussoni ada6ef50f2 HelpersToHeader: remove _PACKED handling
Uniform the `struct` emission to use the `_PACKED` version, and use
`llvm::alignTo` to compute the alignment.
2026-05-29 17:12:35 +02:00
Andrea Gussoni 530ce317c1 ABI: use llvm::alignToPowerOf2
`llvm::alignToPowerOf2` covers the same semantics of the dropped
`alignedOffset` method, including the power of 2 assertion.
2026-05-29 17:12:35 +02:00
Alessandro Di Federico ebad6c458e IsolateFunction: keep all register CSVs 2026-05-29 15:20:26 +02:00
Lauri Vasama b078f2c809 Fix C label output around hidden statements 2026-05-25 09:00:41 +02:00
Lauri Vasama 5c9a7b4207 Fix C output around hidden casts
```
// before
(var_0.x)[1];

// after
var_0.x[1];
```
2026-05-25 09:00:41 +02:00
Lauri Vasama e30a09644e Introduce hoist-variable-initializers pass 2026-05-25 09:00:41 +02:00
Lauri Vasama d3dcc70c0c Implement cast elision for variable initializers 2026-05-25 09:00:41 +02:00
Lauri Vasama afaff540ed Implement Clift local variable self-assignment
Local variable initializer regions can now have a block argument
representing the local variable being initialized.
2026-05-25 09:00:41 +02:00
Lauri Vasama 3064653e37 Add StatementOpInterface::getBlockArgumentVariable
Translates a mlir::BlockArgument to an mlir::Value more directly
representing the entity or expression to which the block argument
refers, or null if not applicable for the statement in question.
2026-05-25 09:00:41 +02:00
Lauri Vasama 7fe96c2c9a Improve clift::isLvalueExpression 2026-05-25 09:00:41 +02:00
Lauri Vasama 23e06b5212 Erase requires in tighten-variable-scopes 2026-05-25 09:00:41 +02:00
Lauri Vasama ddcaa1fad2 Improve defer-allocas
* Discover deferrable allocas in a separate pass before applying changes
  in order to avoid double work.
* Defer allocas to just before the first user or the terminator, if no
  user exists in the target block.
* Move allocas when the target block is the same as the original block.
2026-05-25 09:00:41 +02:00
Giacomo Vercesi 2fabd9c400 pypeline: split Pipe.invalidate in two
Split the `invalidate` method in two phases: in `invalidateCheck` it
just checks if the model diff warrants the execution of the actual
`invalidate` method, which requires fetching the custom invalidation
data from storage. The actual `invalidation` method remains the same.
This should make invalidation faster for storage providers that store
the invalidation remotely.
2026-05-22 09:04:35 +02:00
Giacomo Vercesi bff8b19ca7 Fix Model.identifier in the C++ implementation
Due to a missing `&` the identifier returned was `r` instead of `revng`.
2026-05-22 09:04:35 +02:00
Alessandro Di Federico e0f62fe566 ELFImporter: use .{,gnu.}hash for symbols count 2026-05-15 11:27:51 +02:00
Alessandro Di Federico 49e3b9b28b ELFImporter: consider STT_GNU_IFUNC 2026-05-15 11:27:34 +02:00
Alessandro Di Federico cc28786000 DwarfToModelConverter: match existing functions
Unfortunately, in DWARF, there's no widespread indicator on whether a
function is regular ARM or Thumb. Therefore, in this commit, instead of
blindly creating a new function, we first check if, in the model, we
already have a function at that address.

This means that, if we have a Thumb function in DWARF, but it doesn't
already exist in the model, we will import as regular ARM, which is
wrong.
Specifically, this can happen with `revng model import debug-info`.
2026-05-15 11:27:34 +02:00
Alessandro Di Federico e41c5780ce ELFLDDTree: get exported symbols via ELFImporter
We used to use dynamic_symbol_begin which does not use segments (uses
sections) and also tampers with `st_value` for ARM symbols.

This commit makes it reuse the more accurate logic implemented in
ELFImporter.
2026-05-15 11:27:33 +02:00