1*06c3fb27SDimitry Andric //===-- Arena.cpp ---------------------------------------------------------===// 2*06c3fb27SDimitry Andric // 3*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*06c3fb27SDimitry Andric // 7*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 8*06c3fb27SDimitry Andric 9*06c3fb27SDimitry Andric #include "clang/Analysis/FlowSensitive/Arena.h" 10*06c3fb27SDimitry Andric #include "clang/Analysis/FlowSensitive/Value.h" 11*06c3fb27SDimitry Andric 12*06c3fb27SDimitry Andric namespace clang::dataflow { 13*06c3fb27SDimitry Andric 14*06c3fb27SDimitry Andric static std::pair<const Formula *, const Formula *> 15*06c3fb27SDimitry Andric canonicalFormulaPair(const Formula &LHS, const Formula &RHS) { 16*06c3fb27SDimitry Andric auto Res = std::make_pair(&LHS, &RHS); 17*06c3fb27SDimitry Andric if (&RHS < &LHS) // FIXME: use a deterministic order instead 18*06c3fb27SDimitry Andric std::swap(Res.first, Res.second); 19*06c3fb27SDimitry Andric return Res; 20*06c3fb27SDimitry Andric } 21*06c3fb27SDimitry Andric 22*06c3fb27SDimitry Andric const Formula &Arena::makeAtomRef(Atom A) { 23*06c3fb27SDimitry Andric auto [It, Inserted] = AtomRefs.try_emplace(A); 24*06c3fb27SDimitry Andric if (Inserted) 25*06c3fb27SDimitry Andric It->second = 26*06c3fb27SDimitry Andric &Formula::create(Alloc, Formula::AtomRef, {}, static_cast<unsigned>(A)); 27*06c3fb27SDimitry Andric return *It->second; 28*06c3fb27SDimitry Andric } 29*06c3fb27SDimitry Andric 30*06c3fb27SDimitry Andric const Formula &Arena::makeAnd(const Formula &LHS, const Formula &RHS) { 31*06c3fb27SDimitry Andric if (&LHS == &RHS) 32*06c3fb27SDimitry Andric return LHS; 33*06c3fb27SDimitry Andric 34*06c3fb27SDimitry Andric auto [It, Inserted] = 35*06c3fb27SDimitry Andric Ands.try_emplace(canonicalFormulaPair(LHS, RHS), nullptr); 36*06c3fb27SDimitry Andric if (Inserted) 37*06c3fb27SDimitry Andric It->second = &Formula::create(Alloc, Formula::And, {&LHS, &RHS}); 38*06c3fb27SDimitry Andric return *It->second; 39*06c3fb27SDimitry Andric } 40*06c3fb27SDimitry Andric 41*06c3fb27SDimitry Andric const Formula &Arena::makeOr(const Formula &LHS, const Formula &RHS) { 42*06c3fb27SDimitry Andric if (&LHS == &RHS) 43*06c3fb27SDimitry Andric return LHS; 44*06c3fb27SDimitry Andric 45*06c3fb27SDimitry Andric auto [It, Inserted] = 46*06c3fb27SDimitry Andric Ors.try_emplace(canonicalFormulaPair(LHS, RHS), nullptr); 47*06c3fb27SDimitry Andric if (Inserted) 48*06c3fb27SDimitry Andric It->second = &Formula::create(Alloc, Formula::Or, {&LHS, &RHS}); 49*06c3fb27SDimitry Andric return *It->second; 50*06c3fb27SDimitry Andric } 51*06c3fb27SDimitry Andric 52*06c3fb27SDimitry Andric const Formula &Arena::makeNot(const Formula &Val) { 53*06c3fb27SDimitry Andric auto [It, Inserted] = Nots.try_emplace(&Val, nullptr); 54*06c3fb27SDimitry Andric if (Inserted) 55*06c3fb27SDimitry Andric It->second = &Formula::create(Alloc, Formula::Not, {&Val}); 56*06c3fb27SDimitry Andric return *It->second; 57*06c3fb27SDimitry Andric } 58*06c3fb27SDimitry Andric 59*06c3fb27SDimitry Andric const Formula &Arena::makeImplies(const Formula &LHS, const Formula &RHS) { 60*06c3fb27SDimitry Andric if (&LHS == &RHS) 61*06c3fb27SDimitry Andric return makeLiteral(true); 62*06c3fb27SDimitry Andric 63*06c3fb27SDimitry Andric auto [It, Inserted] = 64*06c3fb27SDimitry Andric Implies.try_emplace(std::make_pair(&LHS, &RHS), nullptr); 65*06c3fb27SDimitry Andric if (Inserted) 66*06c3fb27SDimitry Andric It->second = &Formula::create(Alloc, Formula::Implies, {&LHS, &RHS}); 67*06c3fb27SDimitry Andric return *It->second; 68*06c3fb27SDimitry Andric } 69*06c3fb27SDimitry Andric 70*06c3fb27SDimitry Andric const Formula &Arena::makeEquals(const Formula &LHS, const Formula &RHS) { 71*06c3fb27SDimitry Andric if (&LHS == &RHS) 72*06c3fb27SDimitry Andric return makeLiteral(true); 73*06c3fb27SDimitry Andric 74*06c3fb27SDimitry Andric auto [It, Inserted] = 75*06c3fb27SDimitry Andric Equals.try_emplace(canonicalFormulaPair(LHS, RHS), nullptr); 76*06c3fb27SDimitry Andric if (Inserted) 77*06c3fb27SDimitry Andric It->second = &Formula::create(Alloc, Formula::Equal, {&LHS, &RHS}); 78*06c3fb27SDimitry Andric return *It->second; 79*06c3fb27SDimitry Andric } 80*06c3fb27SDimitry Andric 81*06c3fb27SDimitry Andric IntegerValue &Arena::makeIntLiteral(llvm::APInt Value) { 82*06c3fb27SDimitry Andric auto [It, Inserted] = IntegerLiterals.try_emplace(Value, nullptr); 83*06c3fb27SDimitry Andric 84*06c3fb27SDimitry Andric if (Inserted) 85*06c3fb27SDimitry Andric It->second = &create<IntegerValue>(); 86*06c3fb27SDimitry Andric return *It->second; 87*06c3fb27SDimitry Andric } 88*06c3fb27SDimitry Andric 89*06c3fb27SDimitry Andric BoolValue &Arena::makeBoolValue(const Formula &F) { 90*06c3fb27SDimitry Andric auto [It, Inserted] = FormulaValues.try_emplace(&F); 91*06c3fb27SDimitry Andric if (Inserted) 92*06c3fb27SDimitry Andric It->second = (F.kind() == Formula::AtomRef) 93*06c3fb27SDimitry Andric ? (BoolValue *)&create<AtomicBoolValue>(F) 94*06c3fb27SDimitry Andric : &create<FormulaBoolValue>(F); 95*06c3fb27SDimitry Andric return *It->second; 96*06c3fb27SDimitry Andric } 97*06c3fb27SDimitry Andric 98*06c3fb27SDimitry Andric } // namespace clang::dataflow 99