1 /********************************************************************
2  * AUTHORS: Vijay Ganesh
3  *
4  * BEGIN DATE: November, 2005
5  *
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12 
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 THE SOFTWARE.
23 ********************************************************************/
24 
25 #ifndef STPMGR_H
26 #define STPMGR_H
27 
28 #include "stp/AST/ASTBVConst.h"
29 #include "stp/AST/ASTInterior.h"
30 #include "stp/AST/ASTNode.h"
31 #include "stp/AST/ASTSymbol.h"
32 
33 #include "stp/AST/AST.h"
34 #include "stp/AST/NodeFactory/HashingNodeFactory.h"
35 #include "stp/STPManager/UserDefinedFlags.h"
36 #include "stp/Sat/SATSolver.h"
37 #include "stp/Util/Attributes.h"
38 
39 namespace stp
40 {
41 /*
42  * STP Node Manager. Tools for managing AST nodes.
43  */
44 class STPMgr
45 {
46   friend class ASTNode;
47   friend class ASTInterior;
48   friend class ASTBVConst;
49   friend class ASTSymbol;
50   friend ASTNode HashingNodeFactory::CreateNode(const Kind kind,
51                                                 const ASTVec& back_children);
52 
53 private:
54   // Typedef for unique Interior node table.
55   typedef std::unordered_set<ASTInterior*, ASTInterior::ASTInteriorHasher,
56                              ASTInterior::ASTInteriorEqual>
57       ASTInteriorSet;
58 
59   // Typedef for unique Symbol node (leaf) table.
60   typedef std::unordered_set<ASTSymbol*, ASTSymbol::ASTSymbolHasher,
61                              ASTSymbol::ASTSymbolEqual>
62       ASTSymbolSet;
63 
64   // Typedef for unique BVConst node (leaf) table.
65   typedef std::unordered_set<ASTBVConst*, ASTBVConst::ASTBVConstHasher,
66                              ASTBVConst::ASTBVConstEqual>
67       ASTBVConstSet;
68 
69   // Unique node tables that enables common subexpression sharing
70   ASTInteriorSet _interior_unique_table;
71 
72   // Table for variable names, let names etc.
73   ASTSymbolSet _symbol_unique_table;
74 
75   // Table to uniquefy bvconst
76   ASTBVConstSet _bvconst_unique_table;
77 
78   uint8_t last_iteration;
79 
80 public:
81   HashingNodeFactory* hashingNodeFactory;
82   NodeFactory* defaultNodeFactory;
83 
84   // frequently used nodes
85   ASTNode ASTFalse, ASTTrue, ASTUndefined;
86 
87   bool soft_timeout_expired;
88 
89   // No nodes should already have the iteration number that is returned from
90   // here. This never returns zero.
getNextIteration()91   uint8_t getNextIteration()
92   {
93     if (last_iteration == 255)
94     {
95       resetIteration();
96       last_iteration = 0;
97     }
98 
99     uint8_t result = ++last_iteration;
100     assert(result != 0);
101     return result;
102   }
103 
104   // Detauls the iteration count back to zero.
resetIteration()105   void resetIteration()
106   {
107     for (ASTInteriorSet::iterator it = _interior_unique_table.begin();
108          it != _interior_unique_table.end(); it++)
109     {
110       (*it)->iteration = 0;
111     }
112 
113     for (ASTSymbolSet::iterator it = _symbol_unique_table.begin();
114          it != _symbol_unique_table.end(); it++)
115     {
116       (*it)->iteration = 0;
117     }
118 
119     for (ASTBVConstSet::iterator it = _bvconst_unique_table.begin();
120          it != _bvconst_unique_table.end(); it++)
121     {
122       (*it)->iteration = 0;
123     }
124   }
125 
getAssertLevel()126   size_t getAssertLevel() { return _asserts.size(); }
127 
128 private:
129   // Stack of Logical Context. each entry in the stack is a logical
130   // context. A logical context is a vector of assertions. The
131   // logical context is represented by a ptr to a vector of
132   // assertions in that logical context. Logical contexts are
133   // created by PUSH/POP
134   vector<ASTVec*> _asserts;
135 
136   // Memo table that tracks terms already seen
137   ASTNodeMap TermsAlreadySeenMap;
138 
139   // The query for the current logical context. BUG probably wrongly handled
140   // and gets mixed up with the state, which it shouldn't (otherwise, next
141   // query will be affected)
142   ASTNode _current_query;
143 
144   // Ptr to class that reports on the running time of various parts
145   // of the code
146   RunTimes* runTimes;
147 
148   /****************************************************************
149    * Private Member Functions                                     *
150    ****************************************************************/
151 
152   // Destructively appends back_child nodes to front_child nodes.
153   // If back_child nodes is NULL, no appending is done.  back_child
154   // nodes are not modified.  Then it returns the hashed copy of the
155   // node, which is created if necessary.
156   ASTInterior* CreateInteriorNode(Kind kind, ASTInterior* new_node,
157                                   const ASTVec& back_children = _empty_ASTVec);
158 
159   // Create unique ASTInterior node.
160   ASTInterior* LookupOrCreateInterior(ASTInterior* n);
161 
162   // Create unique ASTSymbol node.
163   ASTSymbol* LookupOrCreateSymbol(ASTSymbol& s);
164 
165   // Called whenever we want to make sure that the Symbol is
166   // declared during semantic analysis
167   bool LookupSymbol(ASTSymbol& s);
168 
169   // Called by ASTNode constructors to uniqueify ASTBVConst
170   ASTBVConst* LookupOrCreateBVConst(ASTBVConst& s);
171 
172   // Cache of zero/one/max BVConsts of different widths.
173   ASTVec zeroes;
174   ASTVec ones;
175   ASTVec max;
176 
177   // Set of new symbols introduced that replace the array read terms
178   ASTNodeSet Introduced_SymbolsSet;
179 
180   CBV CreateBVConstVal;
181 
182 public:
183   bool LookupSymbol(const char* const name);
184   bool LookupSymbol(const char* const name, ASTNode& output);
185 
186   /****************************************************************
187    * Public Flags                                                 *
188    ****************************************************************/
189   UserDefinedFlags UserFlags;
190 
191   // This flag, when true, indicates that counterexample is being
192   // checked by the counterexample checker
193   bool counterexample_checking_during_refinement;
194 
195   // This flag indicates as to whether the input has been determined
196   // to be valid or not by this tool
197   bool ValidFlag;
198 
199   // Flags indicates that counterexample will now be checked by the
200   // counterexample checker, and hence simplifyterm must switch off
201   // certain optimizations. In particular, array write optimizations
202   bool SimplifyWrites_InPlace_Flag;
203 
204   // count is used in the creation of new variables
205   unsigned int _symbol_count;
206 
207   // The value to append to the filename when saving the CNF.
208   unsigned int CNFFileNameCounter;
209 
210   /****************************************************************
211    * Public Member Functions                                      *
212    ****************************************************************/
213 
STPMgr()214   DLL_PUBLIC STPMgr()
215       : last_iteration(0), soft_timeout_expired(false), _symbol_count(0),
216         CNFFileNameCounter(0)
217   {
218     ValidFlag = false;
219     counterexample_checking_during_refinement = false;
220     SimplifyWrites_InPlace_Flag = false;
221 
222     // Need to initiate the node factories before any nodes are created.
223     hashingNodeFactory = new HashingNodeFactory(*this);
224     defaultNodeFactory = hashingNodeFactory;
225 
226     ASTFalse = CreateNode(FALSE);
227     ASTTrue = CreateNode(TRUE);
228     ASTUndefined = CreateNode(UNDEFINED);
229     runTimes = new RunTimes();
230     _current_query = ASTUndefined;
231     CreateBVConstVal = NULL;
232   }
233 
GetRunTimes(void)234   RunTimes* GetRunTimes(void) { return runTimes; }
235 
236   unsigned int NodeSize(const ASTNode& a);
237 
238   /****************************************************************
239    * Create Symbol and BVConst functions                          *
240    ****************************************************************/
241 
242   // Create and return an ASTNode for a symbol
243   ASTNode LookupOrCreateSymbol(const char* const name);
244 
245   // Create and return an ASTNode for a symbol Width is number of bits.
246   ASTNode CreateOneConst(unsigned int width);
247   ASTNode CreateTwoConst(unsigned int width);
248   ASTNode CreateMaxConst(unsigned int width);
249   ASTNode CreateZeroConst(unsigned int width);
250   DLL_PUBLIC ASTNode CreateBVConst(CBV bv, unsigned width);
251   ASTNode CreateBVConst(const char* strval, int base);
252   ASTNode CreateBVConst(std::string strval, int base, int bit_width);
253   ASTNode CreateBVConst(unsigned int width, unsigned long long int bvconst);
254   ASTNode charToASTNode(unsigned char* strval, int base, int bit_width);
255 
256   /****************************************************************
257    * Create Node functions                                        *
258    ****************************************************************/
259 
260   DLL_PUBLIC inline ASTNode
CreateSymbol(const char * const name,unsigned indexWidth,unsigned valueWidth)261   CreateSymbol(const char* const name, unsigned indexWidth, unsigned valueWidth)
262   {
263     return defaultNodeFactory->CreateSymbol(name, indexWidth, valueWidth);
264   }
265 
266   // Create and return an interior ASTNode
267   DLL_PUBLIC inline ASTNode CreateNode(stp::Kind kind,
268                                        const ASTVec& children = _empty_ASTVec)
269   {
270     return defaultNodeFactory->CreateNode(kind, children);
271   }
272 
273   DLL_PUBLIC inline ASTNode
274   CreateNode(Kind kind, const ASTNode& child0,
275              const ASTVec& back_children = _empty_ASTVec)
276   {
277     return defaultNodeFactory->CreateNode(kind, child0, back_children);
278   }
279 
280   DLL_PUBLIC inline ASTNode
281   CreateNode(Kind kind, const ASTNode& child0, const ASTNode& child1,
282              const ASTVec& back_children = _empty_ASTVec)
283   {
284     return defaultNodeFactory->CreateNode(kind, child0, child1, back_children);
285   }
286 
287   DLL_PUBLIC inline ASTNode
288   CreateNode(Kind kind, const ASTNode& child0, const ASTNode& child1,
289              const ASTNode& child2, const ASTVec& back_children = _empty_ASTVec)
290   {
291     return defaultNodeFactory->CreateNode(kind, child0, child1, child2,
292                                           back_children);
293   }
294 
295   /****************************************************************
296    * Create Term functions                                        *
297    ****************************************************************/
298 
299   // Create and return an ASTNode for a term
300   inline ASTNode CreateTerm(stp::Kind kind, unsigned int width,
301                             const ASTVec& children = _empty_ASTVec)
302   {
303     return defaultNodeFactory->CreateTerm(kind, width, children);
304   }
305 
306   inline ASTNode CreateArrayTerm(stp::Kind kind, unsigned int indexWidth,
307                                  unsigned int width,
308                                  const ASTVec& children = _empty_ASTVec)
309   {
310     return defaultNodeFactory->CreateArrayTerm(kind, indexWidth, width,
311                                                children);
312   }
313 
314   inline ASTNode CreateTerm(Kind kind, unsigned int width,
315                             const ASTNode& child0,
316                             const ASTVec& children = _empty_ASTVec)
317   {
318     return defaultNodeFactory->CreateTerm(kind, width, child0, children);
319   }
320 
321   inline ASTNode CreateTerm(Kind kind, unsigned int width,
322                             const ASTNode& child0, const ASTNode& child1,
323                             const ASTVec& children = _empty_ASTVec)
324   {
325     return defaultNodeFactory->CreateTerm(kind, width, child0, child1,
326                                           children);
327   }
328 
329   inline ASTNode CreateTerm(Kind kind, unsigned int width,
330                             const ASTNode& child0, const ASTNode& child1,
331                             const ASTNode& child2,
332                             const ASTVec& /*children*/ = _empty_ASTVec)
333   {
334     return defaultNodeFactory->CreateTerm(kind, width, child0, child1, child2);
335   }
336 
337   /****************************************************************
338    * Functions that manage logical context                        *
339    ****************************************************************/
340 
341   void Pop(void);
342   void Push(void);
343 
344   // Queries aren't maintained on a stack.
345   // Used by CVC & C-interface.
346   const ASTNode GetQuery();
347   void SetQuery(const ASTNode& q);
348 
349   const ASTVec GetAsserts();
350   const ASTVec getVectorOfAsserts();
351 
352   // add a query/assertion to the current logical context
353   void AddAssert(const ASTNode& assert);
354 
355   /****************************************************************
356    * Toplevel printing and stats functions                        *
357    ****************************************************************/
358 
359   // For printing purposes
360   // Used just by the CVC parser.
361   ASTVec ListOfDeclaredVars;
362 
363   // For printing purposes
364   // Used just via the C-interface.
365   // Note, not maintained properly wrt push/pops
366   vector<stp::ASTNode> decls;
367 
368   // Nodes seen so far
369   ASTNodeSet PLPrintNodeSet;
370 
371   // Map from ASTNodes to LetVars
372   ASTNodeMap NodeLetVarMap;
373 
374   // This is a vector which stores the Node to LetVars pairs. It
375   // allows for sorted printing, as opposed to NodeLetVarMap
376   vector<std::pair<ASTNode, ASTNode>> NodeLetVarVec;
377 
378   // A partial Map from ASTNodes to LetVars. Needed in order to
379   // correctly print shared subterms inside the LET itself
380   ASTNodeMap NodeLetVarMap1;
381 
382   // prints statistics for the ASTNode.
383   void ASTNodeStats(const char* c, const ASTNode& a);
384 
385   // Print variable to the input stream
386   void printVarDeclsToStream(ostream& os, ASTNodeSet& symbols);
387 
388   // Print assertions to the input stream
389   void printAssertsToStream(ostream& os);
390 
391   // Variables are added automatically to the introduced_symbolset. Variables
392   // in the set aren't printed out as part of the counter example.
CreateFreshVariable(int indexWidth,int valueWidth,std::string prefix)393   ASTNode CreateFreshVariable(int indexWidth, int valueWidth,
394                               std::string prefix)
395   {
396     char* d = (char*)alloca(sizeof(char) * (32 + prefix.length()));
397     sprintf(d, "%s_%d", prefix.c_str(), _symbol_count++);
398     assert(!LookupSymbol(d));
399 
400     ASTNode CurrentSymbol = CreateSymbol(d, indexWidth, valueWidth);
401     Introduced_SymbolsSet.insert(CurrentSymbol);
402     return CurrentSymbol;
403   }
404 
FoundIntroducedSymbolSet(const ASTNode & in)405   bool FoundIntroducedSymbolSet(const ASTNode& in)
406   {
407     if (Introduced_SymbolsSet.find(in) != Introduced_SymbolsSet.end())
408     {
409       return true;
410     }
411     return false;
412   }
413 
414   bool VarSeenInTerm(const ASTNode& var, const ASTNode& term);
415 
416   ASTNode NewParameterized_BooleanVar(const ASTNode& var,
417                                       const ASTNode& constant);
418 
TermsAlreadySeenMap_Clear(void)419   void TermsAlreadySeenMap_Clear(void) { TermsAlreadySeenMap.clear(); }
420 
421   // This is called before SAT solving, so only junk that isn't needed
422   // after SAT solving should be cleaned out.
ClearAllTables(void)423   void ClearAllTables(void)
424   {
425     NodeLetVarMap.clear();
426     NodeLetVarMap1.clear();
427     PLPrintNodeSet.clear();
428     TermsAlreadySeenMap.clear();
429     NodeLetVarVec.clear();
430     ListOfDeclaredVars.clear();
431   }
432 
433   DLL_PUBLIC ~STPMgr();
434 
435   // Used just via the C-Interface, to allow some nodes to be automaticaly deleted.
436   vector<stp::ASTNode*> persist;
437 
print_stats()438   void print_stats() const
439   {
440 
441     if (_interior_unique_table.size() > 0)
442     {
443       std::cerr << "Interiors:" << _interior_unique_table.size() << " of ";
444       std::cerr << sizeof(**_interior_unique_table.begin()) << " bytes each"
445                 << std::endl;
446     }
447 
448     std::map<Kind, int> freq;
449     for (auto it : _interior_unique_table)
450     {
451       freq[it->GetKind()]++;
452     }
453 
454     for (auto it : freq)
455       std::cerr << it.first << " " << it.second << std::endl;
456 
457     if (_symbol_unique_table.size() > 0)
458     {
459       std::cerr << "Symbols:" << _symbol_unique_table.size() << " of ";
460       std::cerr << sizeof(**_symbol_unique_table.begin()) << " bytes each"
461                 << std::endl;
462     }
463 
464     if (_bvconst_unique_table.size() > 0)
465     {
466       std::cerr << "BVConsts:" << _bvconst_unique_table.size() << " of ";
467       std::cerr << sizeof(**_bvconst_unique_table.begin()) << " bytes each"
468                 << std::endl;
469     }
470   }
471 };
472 
473 } // end of namespace
474 
475 #endif
476