diff options
Diffstat (limited to 'clang/lib/Analysis')
4 files changed, 51 insertions, 78 deletions
diff --git a/clang/lib/Analysis/FlowSensitive/Arena.cpp b/clang/lib/Analysis/FlowSensitive/Arena.cpp index 81137e8..b043a52 100644 --- a/clang/lib/Analysis/FlowSensitive/Arena.cpp +++ b/clang/lib/Analysis/FlowSensitive/Arena.cpp @@ -22,83 +22,63 @@ canonicalFormulaPair(const Formula &LHS, const Formula &RHS) { return Res; } -template <class Key, class ComputeFunc> -const Formula &cached(llvm::DenseMap<Key, const Formula *> &Cache, Key K, - ComputeFunc &&Compute) { - auto [It, Inserted] = Cache.try_emplace(std::forward<Key>(K)); +const Formula &Arena::makeAtomRef(Atom A) { + auto [It, Inserted] = AtomRefs.try_emplace(A); if (Inserted) - It->second = Compute(); + It->second = + &Formula::create(Alloc, Formula::AtomRef, {}, static_cast<unsigned>(A)); return *It->second; } -const Formula &Arena::makeAtomRef(Atom A) { - return cached(AtomRefs, A, [&] { - return &Formula::create(Alloc, Formula::AtomRef, {}, - static_cast<unsigned>(A)); - }); -} - const Formula &Arena::makeAnd(const Formula &LHS, const Formula &RHS) { - return cached(Ands, canonicalFormulaPair(LHS, RHS), [&] { - if (&LHS == &RHS) - return &LHS; - if (LHS.kind() == Formula::Literal) - return LHS.literal() ? &RHS : &LHS; - if (RHS.kind() == Formula::Literal) - return RHS.literal() ? &LHS : &RHS; - - return &Formula::create(Alloc, Formula::And, {&LHS, &RHS}); - }); + if (&LHS == &RHS) + return LHS; + + auto [It, Inserted] = + Ands.try_emplace(canonicalFormulaPair(LHS, RHS), nullptr); + if (Inserted) + It->second = &Formula::create(Alloc, Formula::And, {&LHS, &RHS}); + return *It->second; } const Formula &Arena::makeOr(const Formula &LHS, const Formula &RHS) { - return cached(Ors, canonicalFormulaPair(LHS, RHS), [&] { - if (&LHS == &RHS) - return &LHS; - if (LHS.kind() == Formula::Literal) - return LHS.literal() ? &LHS : &RHS; - if (RHS.kind() == Formula::Literal) - return RHS.literal() ? &RHS : &LHS; - - return &Formula::create(Alloc, Formula::Or, {&LHS, &RHS}); - }); + if (&LHS == &RHS) + return LHS; + + auto [It, Inserted] = + Ors.try_emplace(canonicalFormulaPair(LHS, RHS), nullptr); + if (Inserted) + It->second = &Formula::create(Alloc, Formula::Or, {&LHS, &RHS}); + return *It->second; } const Formula &Arena::makeNot(const Formula &Val) { - return cached(Nots, &Val, [&] { - if (Val.kind() == Formula::Not) - return Val.operands()[0]; - if (Val.kind() == Formula::Literal) - return &makeLiteral(!Val.literal()); - - return &Formula::create(Alloc, Formula::Not, {&Val}); - }); + auto [It, Inserted] = Nots.try_emplace(&Val, nullptr); + if (Inserted) + It->second = &Formula::create(Alloc, Formula::Not, {&Val}); + return *It->second; } const Formula &Arena::makeImplies(const Formula &LHS, const Formula &RHS) { - return cached(Implies, std::make_pair(&LHS, &RHS), [&] { - if (&LHS == &RHS) - return &makeLiteral(true); - if (LHS.kind() == Formula::Literal) - return LHS.literal() ? &RHS : &makeLiteral(true); - if (RHS.kind() == Formula::Literal) - return RHS.literal() ? &RHS : &makeNot(LHS); - - return &Formula::create(Alloc, Formula::Implies, {&LHS, &RHS}); - }); + if (&LHS == &RHS) + return makeLiteral(true); + + auto [It, Inserted] = + Implies.try_emplace(std::make_pair(&LHS, &RHS), nullptr); + if (Inserted) + It->second = &Formula::create(Alloc, Formula::Implies, {&LHS, &RHS}); + return *It->second; } const Formula &Arena::makeEquals(const Formula &LHS, const Formula &RHS) { - return cached(Equals, canonicalFormulaPair(LHS, RHS), [&] { - if (&LHS == &RHS) - return &makeLiteral(true); - if (LHS.kind() == Formula::Literal) - return LHS.literal() ? &RHS : &makeNot(RHS); - if (RHS.kind() == Formula::Literal) - return RHS.literal() ? &LHS : &makeNot(LHS); - - return &Formula::create(Alloc, Formula::Equal, {&LHS, &RHS}); - }); + if (&LHS == &RHS) + return makeLiteral(true); + + auto [It, Inserted] = + Equals.try_emplace(canonicalFormulaPair(LHS, RHS), nullptr); + if (Inserted) + It->second = &Formula::create(Alloc, Formula::Equal, {&LHS, &RHS}); + return *It->second; } IntegerValue &Arena::makeIntLiteral(llvm::APInt Value) { diff --git a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp index 28a8595..e81048c 100644 --- a/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp +++ b/clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp @@ -141,6 +141,8 @@ DataflowAnalysisContext::joinFlowConditions(Atom FirstToken, Solver::Result DataflowAnalysisContext::querySolver( llvm::SetVector<const Formula *> Constraints) { + Constraints.insert(&arena().makeLiteral(true)); + Constraints.insert(&arena().makeNot(arena().makeLiteral(false))); return S->solve(Constraints.getArrayRef()); } @@ -211,8 +213,13 @@ void DataflowAnalysisContext::dumpFlowCondition(Atom Token, Constraints.insert(&arena().makeAtomRef(Token)); addTransitiveFlowConditionConstraints(Token, Constraints); + // TODO: have formulas know about true/false directly instead + Atom True = arena().makeLiteral(true).getAtom(); + Atom False = arena().makeLiteral(false).getAtom(); + Formula::AtomNames Names = {{False, "false"}, {True, "true"}}; + for (const auto *Constraint : Constraints) { - Constraint->print(OS); + Constraint->print(OS, &Names); OS << "\n"; } } diff --git a/clang/lib/Analysis/FlowSensitive/Formula.cpp b/clang/lib/Analysis/FlowSensitive/Formula.cpp index ef7d23f..6d22efc 100644 --- a/clang/lib/Analysis/FlowSensitive/Formula.cpp +++ b/clang/lib/Analysis/FlowSensitive/Formula.cpp @@ -17,9 +17,8 @@ namespace clang::dataflow { -const Formula &Formula::create(llvm::BumpPtrAllocator &Alloc, Kind K, - ArrayRef<const Formula *> Operands, - unsigned Value) { +Formula &Formula::create(llvm::BumpPtrAllocator &Alloc, Kind K, + ArrayRef<const Formula *> Operands, unsigned Value) { assert(Operands.size() == numOperands(K)); if (Value != 0) // Currently, formulas have values or operands, not both. assert(numOperands(K) == 0); @@ -39,7 +38,6 @@ const Formula &Formula::create(llvm::BumpPtrAllocator &Alloc, Kind K, static llvm::StringLiteral sigil(Formula::Kind K) { switch (K) { case Formula::AtomRef: - case Formula::Literal: return ""; case Formula::Not: return "!"; @@ -64,16 +62,7 @@ void Formula::print(llvm::raw_ostream &OS, const AtomNames *Names) const { switch (numOperands(kind())) { case 0: - switch (kind()) { - case AtomRef: - OS << getAtom(); - break; - case Literal: - OS << (literal() ? "true" : "false"); - break; - default: - llvm_unreachable("unhandled formula kind"); - } + OS << getAtom(); break; case 1: OS << sigil(kind()); diff --git a/clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp b/clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp index 3ef3637..ab3a810 100644 --- a/clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp +++ b/clang/lib/Analysis/FlowSensitive/WatchedLiteralsSolver.cpp @@ -322,9 +322,6 @@ CNFFormula buildCNF(const llvm::ArrayRef<const Formula *> &Vals) { switch (Val->kind()) { case Formula::AtomRef: break; - case Formula::Literal: - CNF.addClause(Val->literal() ? posLit(Var) : negLit(Var)); - break; case Formula::And: { const Variable LHS = GetVar(Val->operands()[0]); const Variable RHS = GetVar(Val->operands()[1]); |