DetectABI: inline helpers

Inline `revng_inline` helper calls into each outlined stub which is
consumed by `analyzeABI`, so the analysis can observe the reads and
writes the helper performs on the floating point registers.

The helper module is linked only once at the beginning of the pass, to
avoid double linking issues.
This commit is contained in:
Andrea Gussoni
2026-05-13 14:16:38 +02:00
committed by Alessandro Di Federico
parent 06733a9f3a
commit 6a56557177
2 changed files with 30 additions and 1 deletions
+1
View File
@@ -35,6 +35,7 @@ target_link_libraries(
revngEarlyFunctionAnalysis
revngBasicAnalyses
revngABI
revngInlineHelpers
revngSupport
revngModel
revngPipes
+29 -1
View File
@@ -30,6 +30,8 @@
#include "revng/EarlyFunctionAnalysis/DetectABI.h"
#include "revng/EarlyFunctionAnalysis/FunctionEdgeBase.h"
#include "revng/EarlyFunctionAnalysis/FunctionSummaryOracle.h"
#include "revng/InlineHelpers/InlineHelpers.h"
#include "revng/InlineHelpers/LinkHelpersToInline.h"
#include "revng/Model/Binary.h"
#include "revng/Model/NameBuilder.h"
#include "revng/Model/Pass/DeduplicateCollidingNames.h"
@@ -107,6 +109,7 @@ public:
Manager.add(new LoadModelWrapperPass(ModelWrapper(Global->get())));
Manager.add(new CollectFunctionsFromCalleesWrapperPass());
Manager.add(new ControlFlowGraphCachePass(CFGs));
Manager.add(new LinkHelpersToInlinePass());
Manager.add(new efa::DetectABIPass());
Manager.add(new CollectFunctionsFromUnusedAddressesWrapperPass());
Manager.add(new efa::DetectABIPass());
@@ -451,7 +454,7 @@ void DetectABI::analyzeABI() {
revng_log(Log, "Running ABI analyses");
LoggerIndent Indent(Log);
llvm::Task Task(2, "analyzeABI");
llvm::Task Task(3, "analyzeABI");
std::map<MetaAddress, std::unique_ptr<OutlinedFunction>> Functions;
// Create all temporary functions
@@ -463,6 +466,23 @@ void DetectABI::analyzeABI() {
Functions[Function.Entry()] = std::move(NewFunction);
}
// Inline `revng_inline`-tagged helper calls so the subsequent ABI dataflow
// analysis can observe the helpers' register reads and writes directly.
// `InlineHelpersPass` only inlines into `Isolated` functions, so we tag the
// outlined stubs as such. These stubs are temporary and are discarded with
// the cloned module once the analysis ends, so the tag never escapes.
// Helpers whose per-call critical arguments are not LLVM constants here
// survive un-inlined and are consumed as opaque calls by the analysis.
for (auto &[Entry, OutlinedFn] : Functions)
FunctionTags::Isolated.addTo(OutlinedFn->Function.get());
Task.advance("Inline helpers");
{
llvm::legacy::PassManager PM;
PM.add(new InlineHelpersPass());
PM.run(M);
}
// Push this into analyzeFunction
OpaqueRegisterUser RegisterUser(&M);
@@ -1117,6 +1137,14 @@ llvm::Error DetectABI::run(Model &Model,
revng::pipes::CFGMap CFGs("");
ControlFlowGraphCache FMC(CFGs);
// Link helper bodies once at the start of the analysis, to avoid relinking
// for every `inline-helpers` call
{
llvm::legacy::PassManager PM;
PM.add(new LinkHelpersToInlinePass());
PM.run(Module);
}
collectFunctionsFromCallees(Module, GCBI, Binary);
efa::runDetectABI(Module, GCBI, FMC, TupleModel);
collectFunctionsFromUnusedAddresses(Module, GCBI, Binary, FMC);