/// \file stackanalysis.cpp /// \brief // // This file is distributed under the MIT License. See LICENSE.md for details. // // TODO: reduce copy of Element (check arguments and return values) // Standard includes #include #include #include #include #include // Boost includes #include // Local includes #include "datastructures.h" #include "debug.h" #include "ir-helpers.h" #include "jumptargetmanager.h" #include "revamb.h" #include "stackanalysis.h" #include "stackanalysis_impl.h" // We don't put using namespace llvm since it would create conflicts with the // local definition of Value using llvm::AllocaInst; using llvm::BlockAddress; using llvm::CallInst; using llvm::cast; using llvm::Constant; using llvm::ConstantInt; using llvm::DataLayout; using llvm::dyn_cast; using llvm::dyn_cast_or_null; using llvm::Function; using llvm::isa; using llvm::LoadInst; using llvm::Metadata; using llvm::MDNode; using llvm::MDString; using llvm::MDTuple; using llvm::RegisterPass; using llvm::SmallBitVector; using llvm::SmallVector; using llvm::StoreInst; using llvm::StringRef; using llvm::TerminatorInst; using llvm::UnreachableInst; using llvm::User; using namespace StackAnalysis; /// \brief Given an array of GlobalVariable/AllocaInst, returns a unique index /// for each one of them /// /// Get an index for each GlobalVariabe defined in \p M and each AllocaInst in /// the root function. /// /// \tparam N the number of elements to search /// /// \return a std::array of integers representing the index of the corresponding /// input GlobalVariable/AllocaInst, or -1 if the request object /// couldn't be found template static inline std::array getCPUIndex(const Module *M, std::array Search) { std::array Result; // Initialize results to -1 for (int32_t &Index : Result) Index = -1; // Go through global variables first int32_t I = 0; for (const GlobalVariable &GV : M->globals()) { int32_t J = 0; for (const User *U : Search) { if (U == &GV) { assert(Result[J] == -1); Result[J] = I; break; } J++; } I++; } // Look for AllocaInst at the beginning of the root function const BasicBlock *Entry = &*M->getFunction("root")->begin(); auto It = Entry->begin(); while (It != Entry->end() && isa(&*It)) { int32_t J = 0; for (const User *U : Search) { if (U == &*It) { assert(Result[J] == -1); Result[J] = I; break; } J++; } I++; It++; } return Result; } /// \brief CRTP base class for an element of the lattice /// /// \note This class is more for reference. It's unused. /// /// \tparam D the derived class. template class ElementBase { public: /// \brief The partial ordering relation bool lowerThanOrEqual(const ElementBase &RHS) const { const D &This = *static_cast(this); const D &Other = static_cast(RHS); return This.lowerThanOrEqual(Other); } /// \brief The opposite of the partial ordering operation bool greaterThan(const ElementBase &RHS) const { return !this->lowerThanOrEqual(RHS); } /// \brief The combination operator // TODO: assert monotonicity ElementBase &combine(const ElementBase &RHS) { return static_cast(this)->combine(static_cast(RHS)); } }; /// \brief CRTP base class for implementing a monotone framework /// /// This class provides the base structure to implement an analysis based on a /// monotone framework. It also provides an implementation of the MFP solution. /// /// \tparam Label the type identifying a "label" in the monotone framework, /// typically an instruction or a basic block. /// \tparam LatticeElement the type representing an element of the lattice. /// \tparam Interrupt the type describing why the analysis has been interrupted. /// \tparam D the derived class. template class MonotoneFramework { public: using LabelRange = std::vector