|
8 | 8 | #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE__ARENA_H
|
9 | 9 | #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE__ARENA_H
|
10 | 10 |
|
| 11 | +#include "clang/Analysis/FlowSensitive/Formula.h" |
11 | 12 | #include "clang/Analysis/FlowSensitive/StorageLocation.h"
|
12 | 13 | #include "clang/Analysis/FlowSensitive/Value.h"
|
13 | 14 | #include <vector>
|
14 | 15 |
|
15 | 16 | namespace clang::dataflow {
|
16 | 17 |
|
17 | 18 | /// The Arena owns the objects that model data within an analysis.
|
18 |
| -/// For example, `Value` and `StorageLocation`. |
| 19 | +/// For example, `Value`, `StorageLocation`, `Atom`, and `Formula`. |
19 | 20 | class Arena {
|
20 | 21 | public:
|
21 |
| - Arena() |
22 |
| - : TrueVal(create<AtomicBoolValue>()), |
23 |
| - FalseVal(create<AtomicBoolValue>()) {} |
| 22 | + Arena() : True(makeAtom()), False(makeAtom()) {} |
24 | 23 | Arena(const Arena &) = delete;
|
25 | 24 | Arena &operator=(const Arena &) = delete;
|
26 | 25 |
|
@@ -56,74 +55,91 @@ class Arena {
|
56 | 55 | .get());
|
57 | 56 | }
|
58 | 57 |
|
59 |
| - /// Returns a boolean value that represents the conjunction of `LHS` and |
60 |
| - /// `RHS`. Subsequent calls with the same arguments, regardless of their |
61 |
| - /// order, will return the same result. If the given boolean values represent |
62 |
| - /// the same value, the result will be the value itself. |
63 |
| - BoolValue &makeAnd(BoolValue &LHS, BoolValue &RHS); |
64 |
| - |
65 |
| - /// Returns a boolean value that represents the disjunction of `LHS` and |
66 |
| - /// `RHS`. Subsequent calls with the same arguments, regardless of their |
67 |
| - /// order, will return the same result. If the given boolean values represent |
68 |
| - /// the same value, the result will be the value itself. |
69 |
| - BoolValue &makeOr(BoolValue &LHS, BoolValue &RHS); |
70 |
| - |
71 |
| - /// Returns a boolean value that represents the negation of `Val`. Subsequent |
72 |
| - /// calls with the same argument will return the same result. |
73 |
| - BoolValue &makeNot(BoolValue &Val); |
74 |
| - |
75 |
| - /// Returns a boolean value that represents `LHS => RHS`. Subsequent calls |
76 |
| - /// with the same arguments, will return the same result. If the given boolean |
77 |
| - /// values represent the same value, the result will be a value that |
78 |
| - /// represents the true boolean literal. |
79 |
| - BoolValue &makeImplies(BoolValue &LHS, BoolValue &RHS); |
80 |
| - |
81 |
| - /// Returns a boolean value that represents `LHS <=> RHS`. Subsequent calls |
82 |
| - /// with the same arguments, regardless of their order, will return the same |
83 |
| - /// result. If the given boolean values represent the same value, the result |
84 |
| - /// will be a value that represents the true boolean literal. |
85 |
| - BoolValue &makeEquals(BoolValue &LHS, BoolValue &RHS); |
| 58 | + /// Creates a BoolValue wrapping a particular formula. |
| 59 | + /// |
| 60 | + /// Passing in the same formula will result in the same BoolValue. |
| 61 | + /// FIXME: Interning BoolValues but not other Values is inconsistent. |
| 62 | + /// Decide whether we want Value interning or not. |
| 63 | + BoolValue &makeBoolValue(const Formula &); |
| 64 | + |
| 65 | + /// Creates a fresh atom and wraps in in an AtomicBoolValue. |
| 66 | + /// FIXME: For now, identical-address AtomicBoolValue <=> identical atom. |
| 67 | + /// Stop relying on pointer identity and remove this guarantee. |
| 68 | + AtomicBoolValue &makeAtomValue() { |
| 69 | + return cast<AtomicBoolValue>(makeBoolValue(makeAtomRef(makeAtom()))); |
| 70 | + } |
| 71 | + |
| 72 | + /// Creates a fresh Top boolean value. |
| 73 | + TopBoolValue &makeTopValue() { |
| 74 | + // No need for deduplicating: there's no way to create aliasing Tops. |
| 75 | + return create<TopBoolValue>(makeAtomRef(makeAtom())); |
| 76 | + } |
86 | 77 |
|
87 | 78 | /// Returns a symbolic integer value that models an integer literal equal to
|
88 | 79 | /// `Value`. These literals are the same every time.
|
89 | 80 | /// Integer literals are not typed; the type is determined by the `Expr` that
|
90 | 81 | /// an integer literal is associated with.
|
91 | 82 | IntegerValue &makeIntLiteral(llvm::APInt Value);
|
92 | 83 |
|
93 |
| - /// Returns a symbolic boolean value that models a boolean literal equal to |
94 |
| - /// `Value`. These literals are the same every time. |
95 |
| - AtomicBoolValue &makeLiteral(bool Value) const { |
96 |
| - return Value ? TrueVal : FalseVal; |
| 84 | + // Factories for boolean formulas. |
| 85 | + // Formulas are interned: passing the same arguments return the same result. |
| 86 | + // For commutative operations like And/Or, interning ignores order. |
| 87 | + // Simplifications are applied: makeOr(X, X) => X, etc. |
| 88 | + |
| 89 | + /// Returns a formula for the conjunction of `LHS` and `RHS`. |
| 90 | + const Formula &makeAnd(const Formula &LHS, const Formula &RHS); |
| 91 | + |
| 92 | + /// Returns a formula for the disjunction of `LHS` and `RHS`. |
| 93 | + const Formula &makeOr(const Formula &LHS, const Formula &RHS); |
| 94 | + |
| 95 | + /// Returns a formula for the negation of `Val`. |
| 96 | + const Formula &makeNot(const Formula &Val); |
| 97 | + |
| 98 | + /// Returns a formula for `LHS => RHS`. |
| 99 | + const Formula &makeImplies(const Formula &LHS, const Formula &RHS); |
| 100 | + |
| 101 | + /// Returns a formula for `LHS <=> RHS`. |
| 102 | + const Formula &makeEquals(const Formula &LHS, const Formula &RHS); |
| 103 | + |
| 104 | + /// Returns a formula for the variable A. |
| 105 | + const Formula &makeAtomRef(Atom A); |
| 106 | + |
| 107 | + /// Returns a formula for a literal true/false. |
| 108 | + const Formula &makeLiteral(bool Value) { |
| 109 | + return makeAtomRef(Value ? True : False); |
97 | 110 | }
|
98 | 111 |
|
| 112 | + /// Returns a new atomic boolean variable, distinct from any other. |
| 113 | + Atom makeAtom() { return static_cast<Atom>(NextAtom++); }; |
| 114 | + |
99 | 115 | /// Creates a fresh flow condition and returns a token that identifies it. The
|
100 | 116 | /// token can be used to perform various operations on the flow condition such
|
101 | 117 | /// as adding constraints to it, forking it, joining it with another flow
|
102 | 118 | /// condition, or checking implications.
|
103 |
| - AtomicBoolValue &makeFlowConditionToken() { |
104 |
| - return create<AtomicBoolValue>(); |
105 |
| - } |
| 119 | + Atom makeFlowConditionToken() { return makeAtom(); } |
106 | 120 |
|
107 | 121 | private:
|
| 122 | + llvm::BumpPtrAllocator Alloc; |
| 123 | + |
108 | 124 | // Storage for the state of a program.
|
109 | 125 | std::vector<std::unique_ptr<StorageLocation>> Locs;
|
110 | 126 | std::vector<std::unique_ptr<Value>> Vals;
|
111 | 127 |
|
112 | 128 | // Indices that are used to avoid recreating the same integer literals and
|
113 | 129 | // composite boolean values.
|
114 | 130 | llvm::DenseMap<llvm::APInt, IntegerValue *> IntegerLiterals;
|
115 |
| - llvm::DenseMap<std::pair<BoolValue *, BoolValue *>, ConjunctionValue *> |
116 |
| - ConjunctionVals; |
117 |
| - llvm::DenseMap<std::pair<BoolValue *, BoolValue *>, DisjunctionValue *> |
118 |
| - DisjunctionVals; |
119 |
| - llvm::DenseMap<BoolValue *, NegationValue *> NegationVals; |
120 |
| - llvm::DenseMap<std::pair<BoolValue *, BoolValue *>, ImplicationValue *> |
121 |
| - ImplicationVals; |
122 |
| - llvm::DenseMap<std::pair<BoolValue *, BoolValue *>, BiconditionalValue *> |
123 |
| - BiconditionalVals; |
124 |
| - |
125 |
| - AtomicBoolValue &TrueVal; |
126 |
| - AtomicBoolValue &FalseVal; |
| 131 | + using FormulaPair = std::pair<const Formula *, const Formula *>; |
| 132 | + llvm::DenseMap<FormulaPair, const Formula *> Ands; |
| 133 | + llvm::DenseMap<FormulaPair, const Formula *> Ors; |
| 134 | + llvm::DenseMap<const Formula *, const Formula *> Nots; |
| 135 | + llvm::DenseMap<FormulaPair, const Formula *> Implies; |
| 136 | + llvm::DenseMap<FormulaPair, const Formula *> Equals; |
| 137 | + llvm::DenseMap<Atom, const Formula *> AtomRefs; |
| 138 | + |
| 139 | + llvm::DenseMap<const Formula *, BoolValue *> FormulaValues; |
| 140 | + unsigned NextAtom = 0; |
| 141 | + |
| 142 | + Atom True, False; |
127 | 143 | };
|
128 | 144 |
|
129 | 145 | } // namespace clang::dataflow
|
|
0 commit comments