diff --git a/include/revng/BasicAnalyses/GeneratedCodeBasicInfo.h b/include/revng/BasicAnalyses/GeneratedCodeBasicInfo.h index 1bd555c26..581763a21 100644 --- a/include/revng/BasicAnalyses/GeneratedCodeBasicInfo.h +++ b/include/revng/BasicAnalyses/GeneratedCodeBasicInfo.h @@ -57,7 +57,8 @@ public: PCRegSize(0), RootFunction(nullptr), MetaAddressStruct(nullptr), - PCH() {} + PCH(), + RootParsed(false) {} void run(llvm::Module &M); @@ -226,6 +227,8 @@ public: buildDispatcher(T &Targets, llvm::IRBuilder<> &Builder, llvm::BasicBlock *Default = nullptr) { + parseRoot(); + ProgramCounterHandler::DispatcherTargets TargetsPairs; TargetsPairs.reserve(Targets.size()); for (MetaAddress MA : Targets) @@ -244,7 +247,9 @@ public: /// \brief Return the basic block associated to \p PC /// /// Returns nullptr if the PC doesn't have a basic block (yet) - llvm::BasicBlock *getBlockAt(MetaAddress PC) const { + llvm::BasicBlock *getBlockAt(MetaAddress PC) { + parseRoot(); + auto It = JumpTargets.find(PC); if (It == JumpTargets.end()) return nullptr; @@ -263,15 +268,15 @@ public: return getPCFromNewPC(getJumpTargetBlock(BB)); } - bool isJump(llvm::BasicBlock *BB) const { - return isJump(BB->getTerminator()); - } + bool isJump(llvm::BasicBlock *BB) { return isJump(BB->getTerminator()); } /// \brief Return true if \p T represents a jump in the input assembly /// /// Return true if \p T targets include only dispatcher-related basic blocks /// and jump targets. - bool isJump(llvm::Instruction *T) const { + bool isJump(llvm::Instruction *T) { + parseRoot(); + revng_assert(T->getParent()->getParent() == RootFunction); revng_assert(T != nullptr); revng_assert(T->isTerminator()); @@ -323,11 +328,20 @@ public: llvm::map_iterator(End, GetSecond)); } - llvm::BasicBlock *anyPC() const { return AnyPC; } + llvm::BasicBlock *anyPC() { + parseRoot(); + return AnyPC; + } - llvm::BasicBlock *unexpectedPC() const { return UnexpectedPC; } + llvm::BasicBlock *unexpectedPC() { + parseRoot(); + return UnexpectedPC; + } - llvm::BasicBlock *dispatcher() const { return Dispatcher; } + llvm::BasicBlock *dispatcher() { + parseRoot(); + return Dispatcher; + } const llvm::ArrayRef csvs() const { return CSVs; } @@ -414,9 +428,12 @@ public: } }; - SuccessorsList getSuccessors(llvm::BasicBlock *BB) const; + SuccessorsList getSuccessors(llvm::BasicBlock *BB); - llvm::Function *root() const { return RootFunction; } + llvm::Function *root() { + parseRoot(); + return RootFunction; + } llvm::SmallVector, 4> blocksByPCRange(MetaAddress Start, MetaAddress End); @@ -452,6 +469,7 @@ public: } private: + void parseRoot(); void initializePCToBlockCache(); private: @@ -509,6 +527,7 @@ private: using PCToBlockMap = std::multimap; PCToBlockMap PCToBlockCache; std::map DTMap; + bool RootParsed = false; }; template<> diff --git a/lib/BasicAnalyses/GeneratedCodeBasicInfo.cpp b/lib/BasicAnalyses/GeneratedCodeBasicInfo.cpp index a9630bdde..3fcc674ee 100644 --- a/lib/BasicAnalyses/GeneratedCodeBasicInfo.cpp +++ b/lib/BasicAnalyses/GeneratedCodeBasicInfo.cpp @@ -26,16 +26,13 @@ using RegisterGCBI = RegisterPass; static RegisterGCBI X("gcbi", "Generated Code Basic Info", true, true); void GeneratedCodeBasicInfo::run(Module &M) { - Function &F = *M.getFunction("root"); + RootFunction = M.getFunction("root"); NewPC = M.getFunction("newpc"); - if (NewPC != nullptr) { + if (NewPC != nullptr) MetaAddressStruct = cast(NewPC->arg_begin()->getType()); - } revng_log(PassesLog, "Starting GeneratedCodeBasicInfo"); - RootFunction = &F; - const char *MDName = "revng.input.architecture"; NamedMDNode *InputArchMD = M.getOrInsertNamedMetadata(MDName); auto *Tuple = dyn_cast(InputArchMD->getOperand(0)); @@ -65,7 +62,26 @@ void GeneratedCodeBasicInfo::run(Module &M) { Type *PCType = PC->getType()->getPointerElementType(); PCRegSize = M.getDataLayout().getTypeAllocSize(PCType); - for (BasicBlock &BB : F) { + if (auto *NamedMD = M.getNamedMetadata("revng.csv")) { + auto *Tuple = cast(NamedMD->getOperand(0)); + for (const MDOperand &Operand : Tuple->operands()) { + if (Operand.get() == nullptr) + continue; + + auto *CSV = cast(QMD.extract(Operand.get())); + CSVs.push_back(CSV); + } + } + + revng_log(PassesLog, "Ending GeneratedCodeBasicInfo"); +} + +void GeneratedCodeBasicInfo::parseRoot() { + if (RootParsed) + return; + RootParsed = true; + + for (BasicBlock &BB : *RootFunction) { if (!BB.empty()) { switch (getType(&BB)) { case BlockType::RootDispatcherBlock: @@ -90,7 +106,7 @@ void GeneratedCodeBasicInfo::run(Module &M) { case BlockType::JumpTargetBlock: { auto *Call = cast(&*BB.begin()); - revng_assert(Call->getCalledFunction()->getName() == "newpc"); + revng_assert(Call->getCalledFunction() == NewPC); JumpTargets[MetaAddress::fromConstant(Call->getArgOperand(0))] = &BB; break; } @@ -104,23 +120,14 @@ void GeneratedCodeBasicInfo::run(Module &M) { } } } - - if (auto *NamedMD = M.getNamedMetadata("revng.csv")) { - auto *Tuple = cast(NamedMD->getOperand(0)); - for (const MDOperand &Operand : Tuple->operands()) { - if (Operand.get() == nullptr) - continue; - - auto *CSV = cast(QMD.extract(Operand.get())); - CSVs.push_back(CSV); - } - } - - revng_log(PassesLog, "Ending GeneratedCodeBasicInfo"); } GeneratedCodeBasicInfo::SuccessorsList -GeneratedCodeBasicInfo::getSuccessors(BasicBlock *BB) const { +GeneratedCodeBasicInfo::getSuccessors(BasicBlock *BB) { + parseRoot(); + + revng_assert(BB->getParent() == RootFunction); + SuccessorsList Result; df_iterator_default_set Visited;