diff --git a/include/revng/Support/IRHelpers.h b/include/revng/Support/IRHelpers.h index 442966fd5..8f1bb6f88 100644 --- a/include/revng/Support/IRHelpers.h +++ b/include/revng/Support/IRHelpers.h @@ -942,6 +942,10 @@ inline llvm::User *getUniqueUser(llvm::Value *V) { return Result; } +/// \brief Find the first call to newpc starting from \p TheInstruction +/// +llvm::CallInst *reverseNewPCTraversal(llvm::Instruction *TheInstruction); + /// \brief Find the PC which lead to generated \p TheInstruction /// /// \return a pair of integers: the first element represents the PC and the diff --git a/lib/Support/IRHelpers.cpp b/lib/Support/IRHelpers.cpp index 8ebce6369..7017ed01c 100644 --- a/lib/Support/IRHelpers.cpp +++ b/lib/Support/IRHelpers.cpp @@ -72,8 +72,7 @@ Constant *getUniqueString(Module *M, return ConstantExpr::getBitCast(NewVariable, Int8PtrTy); } -std::pair getPC(Instruction *TheInstruction) { - CallInst *NewPCCall = nullptr; +CallInst *reverseNewPCTraversal(Instruction *TheInstruction) { std::set Visited; std::queue WorkList; @@ -91,42 +90,32 @@ std::pair getPC(Instruction *TheInstruction) { auto End = BB->rend(); // Go through the instructions looking for calls to newpc - for (; I != End and NewPCCall == nullptr; I++) { - if (CallInst *Marker = getCallTo(&*I, "newpc")) { - // We found two distinct newpc leading to the requested instruction - if (NewPCCall != nullptr) - return { MetaAddress::invalid(), 0 }; - - NewPCCall = Marker; - } - } + for (; I != End; I++) + if (CallInst *Marker = getCallTo(&*I, "newpc")) + return Marker; // If we didn't find a newpc call yet, continue exploration backward - if (NewPCCall == nullptr) { - // If one of the predecessors is the dispatcher, don't explore any further - for (BasicBlock *Predecessor : predecessors(BB)) { + // If one of the predecessors is the dispatcher, don't explore any further + for (BasicBlock *Predecessor : predecessors(BB)) { + using GCBI = GeneratedCodeBasicInfo; - // Lazily detect dispatcher - using GCBI = GeneratedCodeBasicInfo; - bool PartOfDispatcher = GCBI::isPartOfRootDispatcher(Predecessor); + // Assert we didn't reach the almighty dispatcher + revng_assert(GCBI::isPartOfRootDispatcher(Predecessor) == false); - // Assert we didn't reach the almighty dispatcher - revng_assert(not(NewPCCall == nullptr and PartOfDispatcher)); - if (PartOfDispatcher) - continue; - } - - for (BasicBlock *Predecessor : predecessors(BB)) { - // Ignore already visited or empty BBs - if (!Predecessor->empty() - && Visited.find(Predecessor) == Visited.end()) { - WorkList.push(Predecessor->rbegin()); - Visited.insert(Predecessor); - } + // Ignore already visited or empty BBs + if (!Predecessor->empty() && Visited.find(Predecessor) == Visited.end()) { + WorkList.push(Predecessor->rbegin()); + Visited.insert(Predecessor); } } } + return nullptr; +} + +std::pair getPC(Instruction *TheInstruction) { + CallInst *NewPCCall = reverseNewPCTraversal(TheInstruction); + // Couldn't find the current PC if (NewPCCall == nullptr) return { MetaAddress::invalid(), 0 };