diff --git a/lib/StackAnalysis/StackAnalysis.cpp b/lib/StackAnalysis/StackAnalysis.cpp index 83a7df21f..9b7083faf 100644 --- a/lib/StackAnalysis/StackAnalysis.cpp +++ b/lib/StackAnalysis/StackAnalysis.cpp @@ -843,6 +843,39 @@ void commitToModel(GeneratedCodeBasicInfo &GCBI, revng_check(TheBinary.verify(true)); } +static void +combineCrossCallSites(MetaAddress EntryPC, FunctionSummary &Summary) { + using namespace ABIAnalyses; + using RegState = model::RegisterState::Values; + + for (auto &[PC, CallSites] : Summary.ABIResults.CallSites) { + if (PC == EntryPC) { + for (auto &[FuncArg, CSArg] : + zipmap_range(Summary.ABIResults.ArgumentsRegisters, + CallSites.ArgumentsRegisters)) { + auto *CSV = FuncArg == nullptr ? CSArg->first : FuncArg->first; + auto RSFArg = FuncArg == nullptr ? RegState::Maybe : FuncArg->second; + auto RSCSArg = CSArg == nullptr ? RegState::Maybe : CSArg->second; + + Summary.ABIResults.ArgumentsRegisters[CSV] = combine(RSFArg, RSCSArg); + } + } + } +} + +/// Perform cross-call site propagation +static void interproceduralPropagation(const std::vector &Functions, + FunctionAnalysisResults &Properties) { + for (auto &J : Functions) { + auto CurrentEntryPC = getBasicBlockPC(J.Entry); + for (auto &K : Functions) { + auto &Summary = Properties.at(getBasicBlockPC(K.Entry)); + + combineCrossCallSites(CurrentEntryPC, Summary); + } + } +} + /// Elect a final stack offset to tell whether the function is leaving /// the stack pointer higher than it was at the function entry. static std::optional electFSO(const auto &MaybeReturns) { @@ -2063,6 +2096,9 @@ bool StackAnalysis::runOnModule(Module &M) { if (VerifyLog.isEnabled()) revng_assert(llvm::verifyModule(M, &llvm::dbgs()) == false); + // Propagate results between call-sites and functions + interproceduralPropagation(Functions, Properties); + // Initialize the cache where all the results will be accumulated Cache TheCache(&F, &GCBI);