diff --git a/include/phasar/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.h b/include/phasar/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.h index 81f7bd7655..e73bfceca0 100644 --- a/include/phasar/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.h @@ -19,6 +19,7 @@ #include "phasar/PhasarLLVM/DataFlowSolver/IfdsIde/EdgeFunctionComposer.h" #include "phasar/PhasarLLVM/DataFlowSolver/IfdsIde/IDETabulationProblem.h" #include "phasar/PhasarLLVM/Domain/AnalysisDomain.h" +#include "phasar/PhasarLLVM/Utils/LatticeDomain.h" namespace llvm { class Instruction; @@ -31,7 +32,7 @@ namespace psr { struct IDELinearConstantAnalysisDomain : public LLVMAnalysisDomainDefault { // int64_t corresponds to llvm's type of constant integer - using l_t = int64_t; + using l_t = LatticeDomain; }; class LLVMBasedICFG; @@ -176,10 +177,10 @@ class IDELinearConstantAnalysis public std::enable_shared_from_this { private: const unsigned GenConstantId; - const l_t IntConst; + const int64_t IntConst; public: - explicit GenConstant(l_t IntConst); + explicit GenConstant(int64_t IntConst); l_t computeTarget(l_t Source) override; @@ -253,7 +254,7 @@ class IDELinearConstantAnalysis * @param rop right operand * @return Result of binary operation */ - static l_t executeBinOperation(unsigned Op, l_t Lop, l_t Rop); + static l_t executeBinOperation(unsigned Op, l_t LVal, l_t RVal); static char opToChar(unsigned Op); diff --git a/include/phasar/PhasarLLVM/Utils/LatticeDomain.h b/include/phasar/PhasarLLVM/Utils/LatticeDomain.h index 53d740000f..3df8a6c26f 100644 --- a/include/phasar/PhasarLLVM/Utils/LatticeDomain.h +++ b/include/phasar/PhasarLLVM/Utils/LatticeDomain.h @@ -10,11 +10,15 @@ #ifndef PHASAR_PHASARLLVM_UTILS_LATTICEDOMAIN_H #define PHASAR_PHASARLLVM_UTILS_LATTICEDOMAIN_H -#include "llvm/Support/ErrorHandling.h" - #include +#include #include +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +#include "phasar/Utils/TypeTraits.h" + namespace psr { /// Represents the infimum of the lattice: @@ -22,8 +26,11 @@ namespace psr { /// the lattice. struct Top {}; -static inline std::ostream &operator<<(std::ostream &OS, - [[maybe_unused]] const Top &T) { +inline std::ostream &operator<<(std::ostream &OS, Top /*unused*/) { + return OS << "Top"; +} + +inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Top /*unused*/) { return OS << "Top"; } @@ -32,43 +39,96 @@ static inline std::ostream &operator<<(std::ostream &OS, /// of the lattice. struct Bottom {}; -static inline std::ostream &operator<<(std::ostream &OS, - [[maybe_unused]] const Bottom &B) { +inline std::ostream &operator<<(std::ostream &OS, Bottom /*unused*/) { return OS << "Bottom"; } -/// A easy shorthand to construct a complete lattice of L. -template using LatticeDomain = std::variant; +inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Bottom /*unused*/) { + return OS << "Bottom"; +} +/// A easy shorthand to construct a complete lattice of L. template +struct LatticeDomain : public std::variant { + using std::variant::variant; + + [[nodiscard]] inline bool isBottom() const noexcept { + return std::holds_alternative(*this); + } + [[nodiscard]] inline bool isTop() const noexcept { + return std::holds_alternative(*this); + } + [[nodiscard]] inline L *getValueOrNull() noexcept { + return std::get_if(this); + } + [[nodiscard]] inline const L *getValueOrNull() const noexcept { + return std::get_if(this); + } +}; + +template () + << std::declval())>> inline std::ostream &operator<<(std::ostream &OS, const LatticeDomain &LD) { - if (auto T = std::get_if(&LD)) { - return OS << *T; + if (LD.isBottom()) { + return OS << "Bottom"; } - if (auto B = std::get_if(&LD)) { - return OS << *B; + if (LD.isTop()) { + return OS << "Top"; } - return OS << std::get(LD); + + const auto *Val = LD.getValueOrNull(); + assert(Val && "Only alternative remaining is L"); + return OS << *Val; +} + +template () + << std::declval())>> +inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const LatticeDomain &LD) { + if (LD.isBottom()) { + return OS << "Bottom"; + } + if (LD.isTop()) { + return OS << "Top"; + } + + const auto *Val = LD.getValueOrNull(); + assert(Val && "Only alternative remaining is L"); + return OS << *Val; } template inline bool operator==(const LatticeDomain &Lhs, const LatticeDomain &Rhs) { - if (std::holds_alternative(Lhs) && std::holds_alternative(Rhs)) { - return true; + if (Lhs.index() != Rhs.index()) { + return false; } - if (std::holds_alternative(Lhs) && - std::holds_alternative(Rhs)) { - return true; + if (auto LhsPtr = Lhs.getValueOrNull()) { + /// No need to check whether Lhs is an L; the indices are already the same + return *LhsPtr == *Rhs.getValueOrNull(); } - if (auto *LhsPtr = std::get_if(&Lhs)) { - if (auto *RhsPtr = std::get_if(&Rhs)) { - return *LhsPtr == *RhsPtr; - } + return true; +} + +template < + typename L, typename LL, + typename = std::void_t() == std::declval())>> +inline bool operator==(const LL &Lhs, const LatticeDomain Rhs) { + if (auto RVal = Rhs.getValueOrNull()) { + return Lhs == *RVal; } return false; } +template < + typename L, typename LL, + typename = std::void_t() == std::declval())>> +inline bool operator==(const LatticeDomain Lhs, const LL &Rhs) { + return Rhs == Lhs; +} + template inline bool operator!=(const LatticeDomain &Lhs, const LatticeDomain &Rhs) { @@ -78,26 +138,24 @@ inline bool operator!=(const LatticeDomain &Lhs, template inline bool operator<(const LatticeDomain &Lhs, const LatticeDomain &Rhs) { - // Top < (Lhs::L < Rhs::L) < Bottom - if (std::holds_alternative(Rhs)) { + /// Top < (Lhs::L < Rhs::L) < Bottom + if (Rhs.isTop()) { return false; } - if (std::holds_alternative(Lhs)) { + if (Lhs.isTop()) { return true; } - - if (auto *LhsPtr = std::get_if(&Lhs)) { - if (auto *RhsPtr = std::get_if(&Rhs)) { + if (auto LhsPtr = Lhs.getValueOrNull()) { + if (auto RhsPtr = Rhs.getValueOrNull()) { return *LhsPtr < *RhsPtr; } } - - if (std::holds_alternative(Rhs)) { - return !std::holds_alternative(Lhs); - } - if (std::holds_alternative(Lhs)) { + if (Lhs.isBottom()) { return false; } + if (Rhs.isBottom()) { + return true; + } llvm_unreachable("All comparision cases should be handled above."); } diff --git a/include/phasar/Utils/TypeTraits.h b/include/phasar/Utils/TypeTraits.h index 1cf2754848..5bacd954a6 100644 --- a/include/phasar/Utils/TypeTraits.h +++ b/include/phasar/Utils/TypeTraits.h @@ -13,6 +13,7 @@ #include #include #include +#include #include "llvm/Support/raw_ostream.h" @@ -109,6 +110,15 @@ constexpr bool is_std_hashable_v = detail::is_std_hashable::value; // NOLINT template constexpr bool is_llvm_hashable_v = // NOLINT detail::is_llvm_hashable::value; + +template struct is_variant : std::false_type {}; // NOLINT + +template +struct is_variant> : std::true_type {}; // NOLINT + +template +inline constexpr bool is_variant_v = is_variant::value; // NOLINT + // NOLINTEND(readability-identifier-naming) } // namespace psr diff --git a/lib/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.cpp b/lib/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.cpp index 41faaef951..664d69caf2 100644 --- a/lib/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.cpp +++ b/lib/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.cpp @@ -9,6 +9,7 @@ // #include #include +#include #include #include "llvm/IR/AbstractCallSite.h" @@ -31,11 +32,11 @@ #include "phasar/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis.h" #include "phasar/PhasarLLVM/Pointer/LLVMPointsToInfo.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" +#include "phasar/PhasarPass/Options.h" #include "phasar/Utils/LLVMIRToSrc.h" #include "phasar/Utils/LLVMShorthands.h" #include "phasar/Utils/Logger.h" -using namespace std; using namespace psr; namespace psr { @@ -44,11 +45,10 @@ unsigned IDELinearConstantAnalysis::CurrGenConstantId = 0; // NOLINT unsigned IDELinearConstantAnalysis::CurrLCAIDId = 0; // NOLINT unsigned IDELinearConstantAnalysis::CurrBinaryId = 0; // NOLINT -const IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::TOP = - numeric_limits::min(); +const IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::TOP = Top{}; const IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::BOTTOM = - numeric_limits::max(); + Bottom{}; IDELinearConstantAnalysis::IDELinearConstantAnalysis( const ProjectIRDB *IRDB, const LLVMTypeHierarchy *TH, @@ -60,99 +60,83 @@ IDELinearConstantAnalysis::IDELinearConstantAnalysis( } IDELinearConstantAnalysis::~IDELinearConstantAnalysis() { - IDELinearConstantAnalysis::CurrGenConstantId = 0; - IDELinearConstantAnalysis::CurrLCAIDId = 0; - IDELinearConstantAnalysis::CurrBinaryId = 0; + CurrGenConstantId = 0; + CurrLCAIDId = 0; + CurrBinaryId = 0; } // Start formulating our analysis by specifying the parts required for IFDS IDELinearConstantAnalysis::FlowFunctionPtrType -IDELinearConstantAnalysis::getNormalFlowFunction( - IDELinearConstantAnalysis::n_t Curr, - IDELinearConstantAnalysis::n_t /*Succ*/) { +IDELinearConstantAnalysis::getNormalFlowFunction(n_t Curr, n_t /*Succ*/) { if (const auto *Alloca = llvm::dyn_cast(Curr)) { if (Alloca->getAllocatedType()->isIntegerTy()) { - return make_shared>(Alloca, - getZeroValue()); + return std::make_shared>(Alloca, getZeroValue()); } } // Check store instructions. Store instructions override previous value // of their pointer operand, i.e., kills previous fact (= pointer operand). if (const auto *Store = llvm::dyn_cast(Curr)) { - IDELinearConstantAnalysis::d_t ValueOp = Store->getValueOperand(); + d_t ValueOp = Store->getValueOperand(); // Case I: Storing a constant integer. if (llvm::isa(ValueOp)) { // return Identity::getInstance(); - return make_shared>( - Store, [this](IDELinearConstantAnalysis::d_t Source) { - return Source == getZeroValue(); - }); + return std::make_shared>( + Store, [this](d_t Source) { return Source == getZeroValue(); }); } // Case II: Storing an integer typed value. if (ValueOp->getType()->isIntegerTy()) { - return make_shared>( - Store, [Store](IDELinearConstantAnalysis::d_t Source) { - return Source == Store->getValueOperand(); - }); + return std::make_shared>( + Store, + [Store](d_t Source) { return Source == Store->getValueOperand(); }); } } // check load instructions if (const auto *Load = llvm::dyn_cast(Curr)) { // only consider i32 load if (Load->getPointerOperandType()->getPointerElementType()->isIntegerTy()) { - return make_shared>( - Load, [Load](IDELinearConstantAnalysis::d_t Source) { - return Source == Load->getPointerOperand(); - }); + return std::make_shared>(Load, [Load](d_t Source) { + return Source == Load->getPointerOperand(); + }); } } // check for binary operations: add, sub, mul, udiv/sdiv, urem/srem if (llvm::isa(Curr)) { auto *Lop = Curr->getOperand(0); auto *Rop = Curr->getOperand(1); - return make_shared>( - Curr, [this, Lop, Rop](IDELinearConstantAnalysis::d_t Source) { - return (Lop == Source && llvm::isa(Rop)) || - (Rop == Source && llvm::isa(Lop)) || - (Source == getZeroValue() && - !llvm::isa(Lop) && - !llvm::isa(Rop)); - }); + return std::make_shared>(Curr, [this, Lop, Rop](d_t Source) { + /// Intentionally include nonlinear operations here for being able to + /// explicitly set them to BOTTOM in the edge function + return (Lop == Source) || (Rop == Source) || + (isZeroValue(Source) && llvm::isa(Lop) && + llvm::isa(Rop)); + }); } - return Identity::getInstance(); + return Identity::getInstance(); } IDELinearConstantAnalysis::FlowFunctionPtrType -IDELinearConstantAnalysis::getCallFlowFunction( - IDELinearConstantAnalysis::n_t CallSite, - IDELinearConstantAnalysis::f_t DestFun) { - - // std::cout << "found call at: " << llvmIRToString(CallSite) << '\n'; - +IDELinearConstantAnalysis::getCallFlowFunction(n_t CallSite, f_t DestFun) { // Map the actual parameters into the formal parameters if (const auto *CS = llvm::dyn_cast(CallSite)) { struct LCAFF : FlowFunction { - vector Actuals; - vector Formals; + std::vector Actuals; + std::vector Formals; const llvm::Function *DestFun; - LCAFF(const llvm::CallBase *CallSite, - IDELinearConstantAnalysis::f_t DestFun) - : DestFun(DestFun) { - // Set up the actual parameters + LCAFF(const llvm::CallBase *CallSite, f_t DestFun) : DestFun(DestFun) { + // std::set up the actual parameters for (unsigned Idx = 0; Idx < CallSite->getNumArgOperands(); ++Idx) { Actuals.push_back(CallSite->getArgOperand(Idx)); } - // Set up the formal parameters + // std::set up the formal parameters for (unsigned Idx = 0; Idx < DestFun->arg_size(); ++Idx) { Formals.push_back(getNthFunctionArgument(DestFun, Idx)); } } - set - computeTargets(IDELinearConstantAnalysis::d_t Source) override { + std::set computeTargets(d_t Source) override { // std::cout << "call call-ff with: " << llvmIRToString(Source) << '\n'; - set Res; + std::set Res; for (unsigned Idx = 0; Idx < Actuals.size(); ++Idx) { if (Source == Actuals[Idx]) { // Check for C-style varargs: idx >= destFun->arg_size() @@ -185,13 +169,13 @@ IDELinearConstantAnalysis::getCallFlowFunction( } // Special case: Check if function is called with integer literals as // parameter (in case of varargs ignore) - if (LLVMZeroValue::getInstance()->isLLVMZeroValue(Source) && + if (LLVMZeroValue::isLLVMZeroValue(Source) && Idx < DestFun->arg_size() && llvm::isa(Actuals[Idx])) { Res.insert(Formals[Idx]); // corresponding formal } } - if (!LLVMZeroValue::getInstance()->isLLVMZeroValue(Source) && + if (!LLVMZeroValue::isLLVMZeroValue(Source) && llvm::isa(Source)) { Res.insert(Source); } @@ -200,89 +184,76 @@ IDELinearConstantAnalysis::getCallFlowFunction( }; if (!DestFun->isDeclaration()) { - return make_shared(CS, DestFun); + return std::make_shared(CS, DestFun); } } // Pass everything else as identity - return Identity::getInstance(); + return Identity::getInstance(); } IDELinearConstantAnalysis::FlowFunctionPtrType -IDELinearConstantAnalysis::getRetFlowFunction( - IDELinearConstantAnalysis::n_t CallSite, - IDELinearConstantAnalysis::f_t /*CalleeFun*/, - IDELinearConstantAnalysis::n_t ExitInst, - IDELinearConstantAnalysis::n_t /*RetSite*/) { +IDELinearConstantAnalysis::getRetFlowFunction(n_t CallSite, f_t /*CalleeFun*/, + n_t ExitInst, n_t /*RetSite*/) { // Handle the case: %x = call i32 ... if (CallSite->getType()->isIntegerTy()) { const auto *Return = llvm::dyn_cast(ExitInst); auto *ReturnValue = Return ? Return->getReturnValue() : nullptr; if (ReturnValue) { - struct LCAFF : FlowFunction { - IDELinearConstantAnalysis::n_t CallSite; - IDELinearConstantAnalysis::d_t ReturnValue; - LCAFF(IDELinearConstantAnalysis::n_t CS, - IDELinearConstantAnalysis::d_t RetVal) - : CallSite(CS), ReturnValue(RetVal) {} - set - computeTargets(IDELinearConstantAnalysis::d_t Source) override { - set Res; + struct LCAFF : FlowFunction { + n_t CallSite; + d_t ReturnValue; + LCAFF(n_t CS, d_t RetVal) : CallSite(CS), ReturnValue(RetVal) {} + std::set computeTargets(d_t Source) override { + std::set Res; // Collect return value fact if (Source == ReturnValue) { Res.insert(CallSite); } // Return value is integer literal - if (LLVMZeroValue::getInstance()->isLLVMZeroValue(Source) && + if (LLVMZeroValue::isLLVMZeroValue(Source) && llvm::isa(ReturnValue)) { Res.insert(CallSite); } - if (!LLVMZeroValue::getInstance()->isLLVMZeroValue(Source) && + if (!LLVMZeroValue::isLLVMZeroValue(Source) && llvm::isa(Source)) { Res.insert(Source); } return Res; } }; - return make_shared(CallSite, ReturnValue); + return std::make_shared(CallSite, ReturnValue); } } // All other facts except GlobalVariables are killed at this point - return make_shared>( - [](IDELinearConstantAnalysis::d_t Source) { - return !llvm::isa(Source); - }); + return std::make_shared>( + [](d_t Source) { return !llvm::isa(Source); }); } IDELinearConstantAnalysis::FlowFunctionPtrType -IDELinearConstantAnalysis::getCallToRetFlowFunction( - IDELinearConstantAnalysis::n_t /*CallSite*/, - IDELinearConstantAnalysis::n_t /*RetSite*/, set Callees) { +IDELinearConstantAnalysis::getCallToRetFlowFunction(n_t /*CallSite*/, + n_t /*RetSite*/, + std::set Callees) { for (const auto *Callee : Callees) { if (!ICF->getStartPointsOf(Callee).empty()) { - return make_shared>( - [this](IDELinearConstantAnalysis::d_t Source) { - return !isZeroValue(Source) && - llvm::isa(Source); - }); + return std::make_shared>([this](d_t Source) { + return !isZeroValue(Source) && llvm::isa(Source); + }); } } - return Identity::getInstance(); + return Identity::getInstance(); } IDELinearConstantAnalysis::FlowFunctionPtrType -IDELinearConstantAnalysis::getSummaryFlowFunction( - IDELinearConstantAnalysis::n_t /*CallSite*/, - IDELinearConstantAnalysis::f_t /*DestFun*/) { +IDELinearConstantAnalysis::getSummaryFlowFunction(n_t /*CallSite*/, + f_t /*DestFun*/) { return nullptr; } InitialSeeds IDELinearConstantAnalysis::initialSeeds() { - InitialSeeds - Seeds; + InitialSeeds Seeds; // The analysis' entry points std::set EntryPointFuns; @@ -291,7 +262,7 @@ IDELinearConstantAnalysis::initialSeeds() { EntryPointFuns.insert(IRDB->getFunctionDefinition(EntryPoint)); } - // Set initial seeds at the required entry points and generate global + // std::set initial seeds at the required entry points and generate global // integer-typed variables using generalized initial seeds for (const auto *EntryPointFun : EntryPointFuns) { Seeds.addSeed(&EntryPointFun->front().front(), getZeroValue(), @@ -321,32 +292,27 @@ IDELinearConstantAnalysis::createZeroValue() const { return LLVMZeroValue::getInstance(); } -bool IDELinearConstantAnalysis::isZeroValue( - IDELinearConstantAnalysis::d_t Fact) const { - return LLVMZeroValue::getInstance()->isLLVMZeroValue(Fact); +bool IDELinearConstantAnalysis::isZeroValue(d_t Fact) const { + return LLVMZeroValue::isLLVMZeroValue(Fact); } // In addition provide specifications for the IDE parts -shared_ptr> -IDELinearConstantAnalysis::getNormalEdgeFunction( - IDELinearConstantAnalysis::n_t Curr, - IDELinearConstantAnalysis::d_t CurrNode, - IDELinearConstantAnalysis::n_t /*Succ*/, - IDELinearConstantAnalysis::d_t SuccNode) { +std::shared_ptr> +IDELinearConstantAnalysis::getNormalEdgeFunction(n_t Curr, d_t CurrNode, + n_t /*Succ*/, d_t SuccNode) { // ALL_BOTTOM for zero value if ((isZeroValue(CurrNode) && isZeroValue(SuccNode)) || (llvm::isa(Curr) && isZeroValue(CurrNode))) { LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << "Case: Zero value."); LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << ' '); - return make_shared>( - IDELinearConstantAnalysis::BOTTOM); + return std::make_shared>(BOTTOM); } // Check store instruction if (const auto *Store = llvm::dyn_cast(Curr)) { - IDELinearConstantAnalysis::d_t PointerOperand = Store->getPointerOperand(); - IDELinearConstantAnalysis::d_t ValueOperand = Store->getValueOperand(); + d_t PointerOperand = Store->getPointerOperand(); + d_t ValueOperand = Store->getValueOperand(); if (PointerOperand == SuccNode) { // Case I: Storing a constant integer. if (isZeroValue(CurrNode) && llvm::isa(ValueOperand)) { @@ -355,14 +321,14 @@ IDELinearConstantAnalysis::getNormalEdgeFunction( LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << ' '); const auto *CI = llvm::dyn_cast(ValueOperand); auto IntConst = CI->getSExtValue(); - return make_shared(IntConst); + return std::make_shared(IntConst); } // Case II: Storing an integer typed value. if (CurrNode != SuccNode && ValueOperand->getType()->isIntegerTy()) { LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << "Case: Storing an integer typed value."); LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << ' '); - return make_shared(); + return std::make_shared(); } } } @@ -373,38 +339,36 @@ IDELinearConstantAnalysis::getNormalEdgeFunction( LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << "Case: Loading an integer typed value."); LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << ' '); - return make_shared(); + return std::make_shared(); } } // Check for binary operations add, sub, mul, udiv/sdiv and urem/srem - if (Curr == SuccNode && llvm::isa(Curr)) { + if (Curr == SuccNode && CurrNode != SuccNode && + llvm::isa(Curr)) { LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << "Case: Binary operation."); LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << ' '); unsigned OP = Curr->getOpcode(); auto *Lop = Curr->getOperand(0); auto *Rop = Curr->getOperand(1); // For non linear constant computation we propagate bottom - if (CurrNode == ZeroValue && !llvm::isa(Lop) && - !llvm::isa(Rop)) { - return make_shared>( - IDELinearConstantAnalysis::BOTTOM); + if ((CurrNode == Lop && !llvm::isa(Rop)) || + (CurrNode == Rop && !llvm::isa(Lop))) { + return std::make_shared>(BOTTOM); } - return make_shared(OP, Lop, Rop, - CurrNode); + + return std::make_shared(OP, Lop, Rop, CurrNode); } LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << "Case: Edge identity."); LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << ' '); - return EdgeIdentity::getInstance(); + return EdgeIdentity::getInstance(); } -shared_ptr> -IDELinearConstantAnalysis::getCallEdgeFunction( - IDELinearConstantAnalysis::n_t CallSite, - IDELinearConstantAnalysis::d_t SrcNode, - IDELinearConstantAnalysis::f_t /*DestinationFunction*/, - IDELinearConstantAnalysis::d_t DestNode) { +std::shared_ptr> +IDELinearConstantAnalysis::getCallEdgeFunction(n_t CallSite, d_t SrcNode, + f_t /*DestinationFunction*/, + d_t DestNode) { // Case: Passing constant integer as parameter if (isZeroValue(SrcNode) && !isZeroValue(DestNode)) { if (const auto *A = llvm::dyn_cast(DestNode)) { @@ -412,49 +376,44 @@ IDELinearConstantAnalysis::getCallEdgeFunction( const auto *Actual = CS->getArgOperand(getFunctionArgumentNr(A)); if (const auto *CI = llvm::dyn_cast(Actual)) { auto IntConst = CI->getSExtValue(); - return make_shared(IntConst); + return std::make_shared(IntConst); } } } return EdgeIdentity::getInstance(); } -shared_ptr> -IDELinearConstantAnalysis::getReturnEdgeFunction( - IDELinearConstantAnalysis::n_t /*CallSite*/, - IDELinearConstantAnalysis::f_t /*CalleeFunction*/, - IDELinearConstantAnalysis::n_t ExitStmt, - IDELinearConstantAnalysis::d_t ExitNode, - IDELinearConstantAnalysis::n_t /*RetSite*/, - IDELinearConstantAnalysis::d_t RetNode) { +std::shared_ptr> +IDELinearConstantAnalysis::getReturnEdgeFunction(n_t /*CallSite*/, + f_t /*CalleeFunction*/, + n_t ExitStmt, d_t ExitNode, + n_t /*RetSite*/, d_t RetNode) { // Case: Returning constant integer if (isZeroValue(ExitNode) && !isZeroValue(RetNode)) { const auto *Return = llvm::cast(ExitStmt); auto *ReturnValue = Return->getReturnValue(); if (auto *CI = llvm::dyn_cast_or_null(ReturnValue)) { auto IntConst = CI->getSExtValue(); - return make_shared(IntConst); + return std::make_shared(IntConst); } } - return EdgeIdentity::getInstance(); + return EdgeIdentity::getInstance(); } -shared_ptr> -IDELinearConstantAnalysis::getCallToRetEdgeFunction( - IDELinearConstantAnalysis::n_t /*CallSite*/, - IDELinearConstantAnalysis::d_t /*CallNode*/, - IDELinearConstantAnalysis::n_t /*RetSite*/, - IDELinearConstantAnalysis::d_t /*RetSiteNode*/, - set /*Callees*/) { - return EdgeIdentity::getInstance(); +std::shared_ptr> +IDELinearConstantAnalysis::getCallToRetEdgeFunction(n_t /*CallSite*/, + d_t /*CallNode*/, + n_t /*RetSite*/, + d_t /*RetSiteNode*/, + std::set /*Callees*/) { + return EdgeIdentity::getInstance(); } -shared_ptr> -IDELinearConstantAnalysis::getSummaryEdgeFunction( - IDELinearConstantAnalysis::n_t /*CallSite*/, - IDELinearConstantAnalysis::d_t /*CallNode*/, - IDELinearConstantAnalysis::n_t /*RetSite*/, - IDELinearConstantAnalysis::d_t /*RetSiteNode*/) { +std::shared_ptr> +IDELinearConstantAnalysis::getSummaryEdgeFunction(n_t /*CallSite*/, + d_t /*CallNode*/, + n_t /*RetSite*/, + d_t /*RetSiteNode*/) { return nullptr; } @@ -466,59 +425,52 @@ IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::bottomElement() { return BOTTOM; } -IDELinearConstantAnalysis::l_t -IDELinearConstantAnalysis::join(IDELinearConstantAnalysis::l_t Lhs, - IDELinearConstantAnalysis::l_t Rhs) { - if ((Rhs == Lhs) || (Lhs == TOP && Rhs != BOTTOM)) { +IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::join(l_t Lhs, + l_t Rhs) { + if (Rhs == Lhs || Lhs == TOP) { return Rhs; } - if (Rhs == TOP && Lhs != BOTTOM) { + if (Rhs == TOP) { return Lhs; } return BOTTOM; } -shared_ptr> +std::shared_ptr> IDELinearConstantAnalysis::allTopFunction() { - return make_shared>(TOP); + return std::make_shared>(TOP); } -shared_ptr> +std::shared_ptr> IDELinearConstantAnalysis::LCAEdgeFunctionComposer::composeWith( - shared_ptr> SecondFunction) { - if (auto *AB = dynamic_cast *>( - SecondFunction.get())) { + std::shared_ptr> SecondFunction) { + if (dynamic_cast *>(SecondFunction.get())) { return this->shared_from_this(); } - if (auto *EI = dynamic_cast *>( - SecondFunction.get())) { + if (dynamic_cast *>(SecondFunction.get())) { return this->shared_from_this(); } - if (auto *LCAID = dynamic_cast(SecondFunction.get())) { + if (dynamic_cast(SecondFunction.get())) { return this->shared_from_this(); } return F->composeWith(G->composeWith(SecondFunction)); } -shared_ptr> +std::shared_ptr> IDELinearConstantAnalysis::LCAEdgeFunctionComposer::joinWith( - shared_ptr> OtherFunction) { + std::shared_ptr> OtherFunction) { if (OtherFunction.get() == this || OtherFunction->equal_to(this->shared_from_this())) { return this->shared_from_this(); } - if (auto *AT = dynamic_cast *>( - OtherFunction.get())) { + if (dynamic_cast *>(OtherFunction.get())) { return this->shared_from_this(); } - return make_shared>( - IDELinearConstantAnalysis::BOTTOM); + return std::make_shared>(BOTTOM); } -IDELinearConstantAnalysis::GenConstant::GenConstant( - IDELinearConstantAnalysis::l_t IntConst) - : GenConstantId(++IDELinearConstantAnalysis::CurrGenConstantId), - IntConst(IntConst) {} +IDELinearConstantAnalysis::GenConstant::GenConstant(int64_t IntConst) + : GenConstantId(++CurrGenConstantId), IntConst(IntConst) {} IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::GenConstant::computeTarget( @@ -526,102 +478,101 @@ IDELinearConstantAnalysis::GenConstant::computeTarget( return IntConst; } -shared_ptr> +std::shared_ptr> IDELinearConstantAnalysis::GenConstant::composeWith( - shared_ptr> SecondFunction) { - if (auto *AB = dynamic_cast *>( - SecondFunction.get())) { + std::shared_ptr> SecondFunction) { + if (dynamic_cast *>(SecondFunction.get())) { return this->shared_from_this(); } - if (auto *EI = dynamic_cast *>( - SecondFunction.get())) { + if (dynamic_cast *>(SecondFunction.get())) { return this->shared_from_this(); } - if (auto *LSVI = dynamic_cast(SecondFunction.get())) { + if (dynamic_cast(SecondFunction.get())) { return this->shared_from_this(); } - return make_shared( - this->shared_from_this(), SecondFunction); + + auto Res = SecondFunction->computeTarget(IntConst); + + if (Res == TOP) { + return std::make_shared>(TOP); + } + if (Res == BOTTOM) { + return std::make_shared>(BOTTOM); + } + + return std::make_shared(std::get(Res)); } -shared_ptr> +std::shared_ptr> IDELinearConstantAnalysis::GenConstant::joinWith( - shared_ptr> OtherFunction) { + std::shared_ptr> OtherFunction) { if (OtherFunction.get() == this || OtherFunction->equal_to(this->shared_from_this())) { return this->shared_from_this(); } - if (auto *AT = dynamic_cast *>( - OtherFunction.get())) { + if (dynamic_cast *>(OtherFunction.get())) { return this->shared_from_this(); } - return make_shared>( - IDELinearConstantAnalysis::BOTTOM); + return std::make_shared>(BOTTOM); } bool IDELinearConstantAnalysis::GenConstant::equal_to( - shared_ptr> Other) const { - if (auto *GC = - dynamic_cast(Other.get())) { + std::shared_ptr> Other) const { + if (auto *GC = dynamic_cast(Other.get())) { return (GC->IntConst == this->IntConst); } return this == Other.get(); } -void IDELinearConstantAnalysis::GenConstant::print(ostream &OS, +void IDELinearConstantAnalysis::GenConstant::print(std::ostream &OS, bool /*IsForDebug*/) const { OS << IntConst << " (EF:" << GenConstantId << ')'; } IDELinearConstantAnalysis::LCAIdentity::LCAIdentity() - : LCAIDId(++IDELinearConstantAnalysis::CurrLCAIDId) {} + : LCAIDId(++CurrLCAIDId) {} IDELinearConstantAnalysis::l_t -IDELinearConstantAnalysis::LCAIdentity::computeTarget( - IDELinearConstantAnalysis::l_t Source) { +IDELinearConstantAnalysis::LCAIdentity::computeTarget(l_t Source) { return Source; } -shared_ptr> +std::shared_ptr> IDELinearConstantAnalysis::LCAIdentity::composeWith( - shared_ptr> SecondFunction) { + std::shared_ptr> SecondFunction) { return SecondFunction; } -shared_ptr> +std::shared_ptr> IDELinearConstantAnalysis::LCAIdentity::joinWith( - shared_ptr> OtherFunction) { + std::shared_ptr> OtherFunction) { if (OtherFunction.get() == this || OtherFunction->equal_to(this->shared_from_this())) { return this->shared_from_this(); } - if (auto *AT = dynamic_cast *>( - OtherFunction.get())) { + if (dynamic_cast *>(OtherFunction.get())) { return this->shared_from_this(); } - return make_shared>( - IDELinearConstantAnalysis::BOTTOM); + return std::make_shared>(BOTTOM); } bool IDELinearConstantAnalysis::LCAIdentity::equal_to( - shared_ptr> Other) const { + std::shared_ptr> Other) const { return this == Other.get(); } -void IDELinearConstantAnalysis::LCAIdentity::print(ostream &OS, +void IDELinearConstantAnalysis::LCAIdentity::print(std::ostream &OS, bool /*IsForDebug*/) const { OS << "Id (EF:" << LCAIDId << ')'; } -IDELinearConstantAnalysis::BinOp::BinOp(const unsigned Op, - IDELinearConstantAnalysis::d_t Lop, - IDELinearConstantAnalysis::d_t Rop, - IDELinearConstantAnalysis::d_t CurrNode) - : EdgeFunctionID(++IDELinearConstantAnalysis::CurrBinaryId), Op(Op), - Lop(Lop), Rop(Rop), CurrNode(CurrNode) {} +IDELinearConstantAnalysis::BinOp::BinOp(const unsigned Op, d_t Lop, d_t Rop, + d_t CurrNode) + : EdgeFunctionID(++CurrBinaryId), Op(Op), Lop(Lop), Rop(Rop), + CurrNode(CurrNode) {} -IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::BinOp::computeTarget( - IDELinearConstantAnalysis::l_t Source) { +IDELinearConstantAnalysis::l_t +IDELinearConstantAnalysis::BinOp::computeTarget(l_t Source) { LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << "Left Op : " << llvmIRToString(Lop)); LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) @@ -630,74 +581,70 @@ IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::BinOp::computeTarget( << "Curr Node : " << llvmIRToString(CurrNode)); LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << ' '); - if (LLVMZeroValue::getInstance()->isLLVMZeroValue(CurrNode) && + if (LLVMZeroValue::isLLVMZeroValue(CurrNode) && llvm::isa(Lop) && llvm::isa(Rop)) { - const auto *Lic = llvm::dyn_cast(Lop); - const auto *Ric = llvm::dyn_cast(Rop); - return IDELinearConstantAnalysis::executeBinOperation( - Op, Lic->getSExtValue(), Ric->getSExtValue()); + const auto *Lic = llvm::cast(Lop); + const auto *Ric = llvm::cast(Rop); + return executeBinOperation(Op, Lic->getSExtValue(), Ric->getSExtValue()); } if (Source == BOTTOM) { return BOTTOM; } if (Lop == CurrNode && llvm::isa(Rop)) { - const auto *Ric = llvm::dyn_cast(Rop); - return IDELinearConstantAnalysis::executeBinOperation(Op, Source, - Ric->getSExtValue()); + const auto *Ric = llvm::cast(Rop); + return executeBinOperation(Op, Source, Ric->getSExtValue()); } if (Rop == CurrNode && llvm::isa(Lop)) { - const auto *Lic = llvm::dyn_cast(Lop); - return IDELinearConstantAnalysis::executeBinOperation( - Op, Lic->getSExtValue(), Source); + const auto *Lic = llvm::cast(Lop); + return executeBinOperation(Op, Lic->getSExtValue(), Source); } - throw runtime_error("Only linear constant propagation can be specified!"); + + throw std::runtime_error( + "Only linear constant propagation can be specified!"); } -shared_ptr> +std::shared_ptr> IDELinearConstantAnalysis::BinOp::composeWith( - shared_ptr> SecondFunction) { - if (auto *AB = dynamic_cast *>( - SecondFunction.get())) { + std::shared_ptr> SecondFunction) { + if (dynamic_cast *>(SecondFunction.get())) { return this->shared_from_this(); } - if (auto *EI = dynamic_cast *>( - SecondFunction.get())) { + if (dynamic_cast *>(SecondFunction.get())) { return this->shared_from_this(); } - if (auto *LSVI = dynamic_cast( - SecondFunction.get())) { + if (dynamic_cast(SecondFunction.get())) { return this->shared_from_this(); } - return make_shared( - this->shared_from_this(), SecondFunction); + if (dynamic_cast(SecondFunction.get())) { + return SecondFunction; + } + return std::make_shared(this->shared_from_this(), + SecondFunction); } -shared_ptr> +std::shared_ptr> IDELinearConstantAnalysis::BinOp::joinWith( - shared_ptr> OtherFunction) { + std::shared_ptr> OtherFunction) { if (OtherFunction.get() == this || OtherFunction->equal_to(this->shared_from_this())) { return this->shared_from_this(); } - if (auto *AT = dynamic_cast *>( - OtherFunction.get())) { + if (dynamic_cast *>(OtherFunction.get())) { return this->shared_from_this(); } - return make_shared>( - IDELinearConstantAnalysis::BOTTOM); + return std::make_shared>(BOTTOM); } bool IDELinearConstantAnalysis::BinOp::equal_to( - shared_ptr> Other) const { - if (auto *BOP = - dynamic_cast(Other.get())) { + std::shared_ptr> Other) const { + if (auto *BOP = dynamic_cast(Other.get())) { return BOP->Op == this->Op && BOP->Lop == this->Lop && BOP->Rop == this->Rop; } return this == Other.get(); } -void IDELinearConstantAnalysis::BinOp::print(ostream &OS, +void IDELinearConstantAnalysis::BinOp::print(std::ostream &OS, bool /*IsForDebug*/) const { if (const auto *LIC = llvm::dyn_cast(Lop)) { OS << LIC->getSExtValue(); @@ -713,125 +660,124 @@ void IDELinearConstantAnalysis::BinOp::print(ostream &OS, } char IDELinearConstantAnalysis::opToChar(const unsigned Op) { - char OpAsChar; switch (Op) { case llvm::Instruction::Add: - OpAsChar = '+'; - break; + return '+'; case llvm::Instruction::Sub: - OpAsChar = '-'; - break; + return '-'; case llvm::Instruction::Mul: - OpAsChar = '*'; - break; + return '*'; case llvm::Instruction::UDiv: case llvm::Instruction::SDiv: - OpAsChar = '/'; - break; + return '/'; case llvm::Instruction::URem: case llvm::Instruction::SRem: - OpAsChar = '%'; - break; + return '%'; + case llvm::Instruction::And: + return '&'; + case llvm::Instruction::Or: + return '|'; + case llvm::Instruction::Xor: + return '^'; default: - OpAsChar = ' '; - break; + return ' '; } - return OpAsChar; } bool IDELinearConstantAnalysis::isEntryPoint( const std::string &FunctionName) const { - return std::find(EntryPoints.begin(), EntryPoints.end(), FunctionName) != - EntryPoints.end(); + return EntryPoints.count(FunctionName); } -IDELinearConstantAnalysis::l_t IDELinearConstantAnalysis::executeBinOperation( - const unsigned Op, IDELinearConstantAnalysis::l_t Lop, - IDELinearConstantAnalysis::l_t Rop) { +IDELinearConstantAnalysis::l_t +IDELinearConstantAnalysis::executeBinOperation(const unsigned Op, l_t LVal, + l_t RVal) { + + auto *LopPtr = std::get_if(&LVal); + auto *RopPtr = std::get_if(&RVal); + + if (!LopPtr || !RopPtr) { + return BOTTOM; + } + + auto Lop = *LopPtr; + auto Rop = *RopPtr; // default initialize with BOTTOM (all information) - IDELinearConstantAnalysis::l_t Res = BOTTOM; + int64_t Res; switch (Op) { case llvm::Instruction::Add: if (llvm::AddOverflow(Lop, Rop, Res)) { - Res = TOP; + return BOTTOM; } - break; + return Res; case llvm::Instruction::Sub: if (llvm::SubOverflow(Lop, Rop, Res)) { - Res = TOP; + return BOTTOM; } - break; + return Res; case llvm::Instruction::Mul: if (llvm::MulOverflow(Lop, Rop, Res)) { - Res = TOP; + return BOTTOM; } - break; + return Res; case llvm::Instruction::UDiv: case llvm::Instruction::SDiv: - if (Lop == std::numeric_limits::min() && + if (Lop == std::numeric_limits::min() && Rop == -1) { // Would produce and overflow, as the complement of min is // not representable in a signed type. return TOP; } - if (Rop == 0) { // Division by zero is UB, so we return TOP - return TOP; + if (Rop == 0) { // Division by zero is UB, so we return Bot + return BOTTOM; } - Res = Lop / Rop; - break; + return Lop / Rop; case llvm::Instruction::URem: case llvm::Instruction::SRem: - if (Rop == 0) { // Division by zero is UB, so we return TOP - return TOP; + if (Rop == 0) { // Division by zero is UB, so we return Bot + return BOTTOM; } - Res = Lop % Rop; - break; - + return Lop % Rop; + + case llvm::Instruction::And: + return Lop & Rop; + case llvm::Instruction::Or: + return Lop | Rop; + case llvm::Instruction::Xor: + return Lop ^ Rop; default: LOG_IF_ENABLE(BOOST_LOG_SEV(lg::get(), DEBUG) << "Operation not supported by " "IDELinearConstantAnalysis::" "executeBinOperation()"); - break; + return BOTTOM; } - return Res; } -void IDELinearConstantAnalysis::printNode( - ostream &OS, IDELinearConstantAnalysis::n_t Stmt) const { +void IDELinearConstantAnalysis::printNode(std::ostream &OS, n_t Stmt) const { OS << llvmIRToString(Stmt); } -void IDELinearConstantAnalysis::printDataFlowFact( - ostream &OS, IDELinearConstantAnalysis::d_t Fact) const { +void IDELinearConstantAnalysis::printDataFlowFact(std::ostream &OS, + d_t Fact) const { OS << llvmIRToShortString(Fact); } -void IDELinearConstantAnalysis::printFunction( - ostream &OS, IDELinearConstantAnalysis::f_t Func) const { +void IDELinearConstantAnalysis::printFunction(std::ostream &OS, + f_t Func) const { OS << Func->getName().str(); } -void IDELinearConstantAnalysis::printEdgeFact( - ostream &OS, IDELinearConstantAnalysis::l_t L) const { - if (L == BOTTOM) { - OS << "Bottom"; - } else if (L == TOP) { - OS << "Top"; - } else { - OS << std::to_string(L); - } +void IDELinearConstantAnalysis::printEdgeFact(std::ostream &OS, l_t L) const { + OS << L; } void IDELinearConstantAnalysis::emitTextReport( - const SolverResults &SR, - std::ostream &OS) { + const SolverResults &SR, std::ostream &OS) { OS << "\n====================== IDE-Linear-Constant-Analysis Report " "======================\n"; if (!IRDB->debugInfoAvailable()) { @@ -848,7 +794,7 @@ void IDELinearConstantAnalysis::emitTextReport( if (!Results.empty()) { OS << "At IR statement: " << NtoString(Stmt) << '\n'; for (auto Res : Results) { - if (Res.second != IDELinearConstantAnalysis::BOTTOM) { + if (Res.second != BOTTOM) { OS << " Fact: " << DtoString(Res.first) << "\n Value: " << LtoString(Res.second) << '\n'; } @@ -873,10 +819,9 @@ void IDELinearConstantAnalysis::emitTextReport( } void IDELinearConstantAnalysis::stripBottomResults( - std::unordered_map &Res) { + std::unordered_map &Res) { for (auto It = Res.begin(); It != Res.end();) { - if (It->second == IDELinearConstantAnalysis::BOTTOM) { + if (It->second == BOTTOM) { It = Res.erase(It); } else { ++It; @@ -885,11 +830,7 @@ void IDELinearConstantAnalysis::stripBottomResults( } IDELinearConstantAnalysis::lca_results_t -IDELinearConstantAnalysis::getLCAResults( - SolverResults - SR) { +IDELinearConstantAnalysis::getLCAResults(SolverResults SR) { std::map> AggResults; std::cout << "\n==== Computing LCA Results ====\n"; for (const auto *F : ICF->getAllFunctions()) { diff --git a/lib/PhasarLLVM/DataFlowSolver/Mono/Problems/InterMonoSolverTest.cpp b/lib/PhasarLLVM/DataFlowSolver/Mono/Problems/InterMonoSolverTest.cpp index 2c72c07a24..f13f4b48c7 100644 --- a/lib/PhasarLLVM/DataFlowSolver/Mono/Problems/InterMonoSolverTest.cpp +++ b/lib/PhasarLLVM/DataFlowSolver/Mono/Problems/InterMonoSolverTest.cpp @@ -67,7 +67,7 @@ InterMonoSolverTest::callFlow(InterMonoSolverTest::n_t CallSite, const InterMonoSolverTest::mono_container_t &In) { cout << "InterMonoSolverTest::callFlow()\n"; InterMonoSolverTest::mono_container_t Result; - Result.setUnion(In); + Result = Result.setUnion(In); if (const auto *const Call = llvm::dyn_cast(CallSite)) { Result.insert(Call); } diff --git a/unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysisTest.cpp index 44af1ab3d7..81868542e8 100644 --- a/unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysisTest.cpp @@ -23,8 +23,8 @@ class IDELinearConstantAnalysisTest : public ::testing::Test { unittest::PathToLLTestFiles + "linear_constant/"; // Function - Line Nr - Variable - Value - using LCACompactResult_t = - std::tuple; + using LCACompactResult_t = std::tuple; std::unique_ptr IRDB; void SetUp() override { boost::log::core::get()->set_logging_enabled(false); } @@ -256,6 +256,8 @@ TEST_F(IDELinearConstantAnalysisTest, HandleBranchTest_05) { GroundTruth.emplace("main", 6, "j", 10); GroundTruth.emplace("main", 6, "i", 42); GroundTruth.emplace("main", 8, "j", 10); + // The computation j + 32 gives the same value (42) that i had before: + GroundTruth.emplace("main", 8, "i", 42); compareResults(Results, GroundTruth); } @@ -277,6 +279,8 @@ TEST_F(IDELinearConstantAnalysisTest, HandleBranchTest_07) { GroundTruth.emplace("main", 6, "j", 10); GroundTruth.emplace("main", 6, "i", 30); GroundTruth.emplace("main", 8, "j", 10); + // The computation j + 20 gives the same value (30) that i had before: + GroundTruth.emplace("main", 8, "i", 30); compareResults(Results, GroundTruth); } @@ -750,7 +754,7 @@ TEST_F(IDELinearConstantAnalysisTest, HandleAddOverflow) { auto Results = doAnalysis("overflow_add_cpp_dbg.ll"); std::set GroundTruth; GroundTruth.emplace("main", 6, "i", 9223372036854775806); - GroundTruth.emplace("main", 6, "j", IDELinearConstantAnalysis::TOP); + // GroundTruth.emplace("main", 6, "j", IDELinearConstantAnalysis::TOP); compareResults(Results, GroundTruth); } @@ -758,7 +762,7 @@ TEST_F(IDELinearConstantAnalysisTest, HandleSubOverflow) { auto Results = doAnalysis("overflow_sub_cpp_dbg.ll"); std::set GroundTruth; GroundTruth.emplace("main", 6, "i", -9223372036854775807); - GroundTruth.emplace("main", 6, "j", IDELinearConstantAnalysis::TOP); + // GroundTruth.emplace("main", 6, "j", IDELinearConstantAnalysis::TOP); compareResults(Results, GroundTruth); } @@ -766,7 +770,7 @@ TEST_F(IDELinearConstantAnalysisTest, HandleMulOverflow) { auto Results = doAnalysis("overflow_mul_cpp_dbg.ll"); std::set GroundTruth; GroundTruth.emplace("main", 6, "i", 9223372036854775806); - GroundTruth.emplace("main", 6, "j", IDELinearConstantAnalysis::TOP); + // GroundTruth.emplace("main", 6, "j", IDELinearConstantAnalysis::TOP); compareResults(Results, GroundTruth); } @@ -774,8 +778,8 @@ TEST_F(IDELinearConstantAnalysisTest, HandleDivOverflowForMinIntDivByOne) { auto Results = doAnalysis("overflow_div_min_by_neg_one_cpp_dbg.ll"); std::set GroundTruth; GroundTruth.emplace("main", 6, "i", -9223372036854775807); - GroundTruth.emplace("main", 6, "j", IDELinearConstantAnalysis::TOP); - GroundTruth.emplace("main", 6, "k", IDELinearConstantAnalysis::TOP); + // GroundTruth.emplace("main", 6, "j", IDELinearConstantAnalysis::TOP); + // GroundTruth.emplace("main", 6, "k", IDELinearConstantAnalysis::TOP); compareResults(Results, GroundTruth); } @@ -785,7 +789,7 @@ TEST_F(IDELinearConstantAnalysisTest, HandleDivisionByZero) { auto Results = doAnalysis("ub_division_by_zero_cpp_dbg.ll"); std::set GroundTruth; GroundTruth.emplace("main", 4, "i", 42); - GroundTruth.emplace("main", 4, "j", IDELinearConstantAnalysis::TOP); + // GroundTruth.emplace("main", 4, "j", IDELinearConstantAnalysis::TOP); compareResults(Results, GroundTruth); } @@ -793,7 +797,7 @@ TEST_F(IDELinearConstantAnalysisTest, HandleModuloByZero) { auto Results = doAnalysis("ub_modulo_by_zero_cpp_dbg.ll"); std::set GroundTruth; GroundTruth.emplace("main", 4, "i", 42); - GroundTruth.emplace("main", 4, "j", IDELinearConstantAnalysis::TOP); + // GroundTruth.emplace("main", 4, "j", IDELinearConstantAnalysis::TOP); compareResults(Results, GroundTruth); } diff --git a/unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis_DotTest.cpp b/unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis_DotTest.cpp index f882fd3b30..31dde3d372 100644 --- a/unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis_DotTest.cpp +++ b/unittests/PhasarLLVM/DataFlowSolver/IfdsIde/Problems/IDELinearConstantAnalysis_DotTest.cpp @@ -24,8 +24,8 @@ class IDELinearConstantAnalysisTest : public ::testing::Test { const std::set EntryPoints = {"main"}; // Function - Line Nr - Variable - Value - using LCACompactResult_t = - std::tuple; + using LCACompactResult_t = std::tuple; std::unique_ptr IRDB; void SetUp() override { boost::log::core::get()->set_logging_enabled(false); } @@ -251,6 +251,7 @@ TEST_F(IDELinearConstantAnalysisTest, HandleBranchTest_05) { GroundTruth.emplace("main", 6, "j", 10); GroundTruth.emplace("main", 6, "i", 42); GroundTruth.emplace("main", 8, "j", 10); + GroundTruth.emplace("main", 8, "i", 42); compareResults(Results, GroundTruth); } @@ -272,6 +273,7 @@ TEST_F(IDELinearConstantAnalysisTest, HandleBranchTest_07) { GroundTruth.emplace("main", 6, "j", 10); GroundTruth.emplace("main", 6, "i", 30); GroundTruth.emplace("main", 8, "j", 10); + GroundTruth.emplace("main", 8, "i", 30); compareResults(Results, GroundTruth); }