]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
Update libucl to git version 8d3b186
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / include / clang / Analysis / Analyses / ThreadSafetyTraverse.h
1 //===- ThreadSafetyTraverse.h ----------------------------------*- C++ --*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines a framework for doing generic traversals and rewriting
11 // operations over the Thread Safety TIL.
12 //
13 // UNDER CONSTRUCTION.  USE AT YOUR OWN RISK.
14 //
15 //===----------------------------------------------------------------------===//
16
17 #ifndef LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H
18 #define LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H
19
20 #include "ThreadSafetyTIL.h"
21
22 namespace clang {
23 namespace threadSafety {
24 namespace til {
25
26 // Defines an interface used to traverse SExprs.  Traversals have been made as
27 // generic as possible, and are intended to handle any kind of pass over the
28 // AST, e.g. visiters, copying, non-destructive rewriting, destructive
29 // (in-place) rewriting, hashing, typing, etc.
30 //
31 // Traversals implement the functional notion of a "fold" operation on SExprs.
32 // Each SExpr class provides a traverse method, which does the following:
33 //   * e->traverse(v):
34 //       // compute a result r_i for each subexpression e_i
35 //       for (i = 1..n)  r_i = v.traverse(e_i);
36 //       // combine results into a result for e,  where X is the class of e
37 //       return v.reduceX(*e, r_1, .. r_n).
38 //
39 // A visitor can control the traversal by overriding the following methods:
40 //   * v.traverse(e):
41 //       return v.traverseByCase(e), which returns v.traverseX(e)
42 //   * v.traverseX(e):   (X is the class of e)
43 //       return e->traverse(v).
44 //   * v.reduceX(*e, r_1, .. r_n):
45 //       compute a result for a node of type X
46 //
47 // The reduceX methods control the kind of traversal (visitor, copy, etc.).
48 // They are defined in derived classes.
49 //
50 // Class R defines the basic interface types (R_SExpr).
51 template <class Self, class R>
52 class Traversal {
53 public:
54   Self *self() { return static_cast<Self *>(this); }
55
56   // Traverse an expression -- returning a result of type R_SExpr.
57   // Override this method to do something for every expression, regardless
58   // of which kind it is.
59   typename R::R_SExpr traverse(SExprRef &E, typename R::R_Ctx Ctx) {
60     return traverse(E.get(), Ctx);
61   }
62
63   typename R::R_SExpr traverse(SExpr *E, typename R::R_Ctx Ctx) {
64     return traverseByCase(E, Ctx);
65   }
66
67   // Helper method to call traverseX(e) on the appropriate type.
68   typename R::R_SExpr traverseByCase(SExpr *E, typename R::R_Ctx Ctx) {
69     switch (E->opcode()) {
70 #define TIL_OPCODE_DEF(X)                                                   \
71     case COP_##X:                                                           \
72       return self()->traverse##X(cast<X>(E), Ctx);
73 #include "ThreadSafetyOps.def"
74 #undef TIL_OPCODE_DEF
75     }
76   }
77
78 // Traverse e, by static dispatch on the type "X" of e.
79 // Override these methods to do something for a particular kind of term.
80 #define TIL_OPCODE_DEF(X)                                                   \
81   typename R::R_SExpr traverse##X(X *e, typename R::R_Ctx Ctx) {            \
82     return e->traverse(*self(), Ctx);                                       \
83   }
84 #include "ThreadSafetyOps.def"
85 #undef TIL_OPCODE_DEF
86 };
87
88
89 // Base class for simple reducers that don't much care about the context.
90 class SimpleReducerBase {
91 public:
92   enum TraversalKind {
93     TRV_Normal,
94     TRV_Decl,
95     TRV_Lazy,
96     TRV_Type
97   };
98
99   // R_Ctx defines a "context" for the traversal, which encodes information
100   // about where a term appears.  This can be used to encoding the
101   // "current continuation" for CPS transforms, or other information.
102   typedef TraversalKind R_Ctx;
103
104   // Create context for an ordinary subexpression.
105   R_Ctx subExprCtx(R_Ctx Ctx) { return TRV_Normal; }
106
107   // Create context for a subexpression that occurs in a declaration position
108   // (e.g. function body).
109   R_Ctx declCtx(R_Ctx Ctx) { return TRV_Decl; }
110
111   // Create context for a subexpression that occurs in a position that
112   // should be reduced lazily.  (e.g. code body).
113   R_Ctx lazyCtx(R_Ctx Ctx) { return TRV_Lazy; }
114
115   // Create context for a subexpression that occurs in a type position.
116   R_Ctx typeCtx(R_Ctx Ctx) { return TRV_Type; }
117 };
118
119
120 // Base class for traversals that rewrite an SExpr to another SExpr.
121 class CopyReducerBase : public SimpleReducerBase {
122 public:
123   // R_SExpr is the result type for a traversal.
124   // A copy or non-destructive rewrite returns a newly allocated term.
125   typedef SExpr *R_SExpr;
126   typedef BasicBlock *R_BasicBlock;
127
128   // Container is a minimal interface used to store results when traversing
129   // SExprs of variable arity, such as Phi, Goto, and SCFG.
130   template <class T> class Container {
131   public:
132     // Allocate a new container with a capacity for n elements.
133     Container(CopyReducerBase &S, unsigned N) : Elems(S.Arena, N) {}
134
135     // Push a new element onto the container.
136     void push_back(T E) { Elems.push_back(E); }
137
138     SimpleArray<T> Elems;
139   };
140
141   CopyReducerBase(MemRegionRef A) : Arena(A) {}
142
143 protected:
144   MemRegionRef Arena;
145 };
146
147
148 // Implements a traversal that makes a deep copy of an SExpr.
149 // The default behavior of reduce##X(...) is to create a copy of the original.
150 // Subclasses can override reduce##X to implement non-destructive rewriting
151 // passes.
152 template<class Self>
153 class CopyReducer : public Traversal<Self, CopyReducerBase>,
154                     public CopyReducerBase {
155 public:
156   CopyReducer(MemRegionRef A) : CopyReducerBase(A) {}
157
158 public:
159   R_SExpr reduceNull() {
160     return nullptr;
161   }
162   // R_SExpr reduceFuture(...)  is never used.
163
164   R_SExpr reduceUndefined(Undefined &Orig) {
165     return new (Arena) Undefined(Orig);
166   }
167   R_SExpr reduceWildcard(Wildcard &Orig) {
168     return new (Arena) Wildcard(Orig);
169   }
170
171   R_SExpr reduceLiteral(Literal &Orig) {
172     return new (Arena) Literal(Orig);
173   }
174   template<class T>
175   R_SExpr reduceLiteralT(LiteralT<T> &Orig) {
176     return new (Arena) LiteralT<T>(Orig);
177   }
178   R_SExpr reduceLiteralPtr(LiteralPtr &Orig) {
179     return new (Arena) LiteralPtr(Orig);
180   }
181
182   R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) {
183     return new (Arena) Function(Orig, Nvd, E0);
184   }
185   R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) {
186     return new (Arena) SFunction(Orig, Nvd, E0);
187   }
188   R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) {
189     return new (Arena) Code(Orig, E0, E1);
190   }
191   R_SExpr reduceField(Field &Orig, R_SExpr E0, R_SExpr E1) {
192     return new (Arena) Field(Orig, E0, E1);
193   }
194
195   R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) {
196     return new (Arena) Apply(Orig, E0, E1);
197   }
198   R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) {
199     return new (Arena) SApply(Orig, E0, E1);
200   }
201   R_SExpr reduceProject(Project &Orig, R_SExpr E0) {
202     return new (Arena) Project(Orig, E0);
203   }
204   R_SExpr reduceCall(Call &Orig, R_SExpr E0) {
205     return new (Arena) Call(Orig, E0);
206   }
207
208   R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) {
209     return new (Arena) Alloc(Orig, E0);
210   }
211   R_SExpr reduceLoad(Load &Orig, R_SExpr E0) {
212     return new (Arena) Load(Orig, E0);
213   }
214   R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) {
215     return new (Arena) Store(Orig, E0, E1);
216   }
217   R_SExpr reduceArrayIndex(ArrayIndex &Orig, R_SExpr E0, R_SExpr E1) {
218     return new (Arena) ArrayIndex(Orig, E0, E1);
219   }
220   R_SExpr reduceArrayAdd(ArrayAdd &Orig, R_SExpr E0, R_SExpr E1) {
221     return new (Arena) ArrayAdd(Orig, E0, E1);
222   }
223   R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) {
224     return new (Arena) UnaryOp(Orig, E0);
225   }
226   R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) {
227     return new (Arena) BinaryOp(Orig, E0, E1);
228   }
229   R_SExpr reduceCast(Cast &Orig, R_SExpr E0) {
230     return new (Arena) Cast(Orig, E0);
231   }
232
233   R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> &Bbs) {
234     return nullptr;  // FIXME: implement CFG rewriting
235   }
236   R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container<Variable *> &As,
237                                 Container<Variable *> &Is, R_SExpr T) {
238     return nullptr;  // FIXME: implement CFG rewriting
239   }
240   R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) {
241     return new (Arena) Phi(Orig, std::move(As.Elems));
242   }
243   R_SExpr reduceGoto(Goto &Orig, BasicBlock *B) {
244     return new (Arena) Goto(Orig, B, 0);  // FIXME: set index
245   }
246   R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) {
247     return new (Arena) Branch(O, C, B0, B1, 0, 0);  // FIXME: set indices
248   }
249
250   R_SExpr reduceIdentifier(Identifier &Orig) {
251     return new (Arena) Identifier(Orig);
252   }
253   R_SExpr reduceIfThenElse(IfThenElse &Orig, R_SExpr C, R_SExpr T, R_SExpr E) {
254     return new (Arena) IfThenElse(Orig, C, T, E);
255   }
256   R_SExpr reduceLet(Let &Orig, Variable *Nvd, R_SExpr B) {
257     return new (Arena) Let(Orig, Nvd, B);
258   }
259
260   // Create a new variable from orig, and push it onto the lexical scope.
261   Variable *enterScope(Variable &Orig, R_SExpr E0) {
262     return new (Arena) Variable(Orig, E0);
263   }
264   // Exit the lexical scope of orig.
265   void exitScope(const Variable &Orig) {}
266
267   void enterCFG(SCFG &Cfg) {}
268   void exitCFG(SCFG &Cfg) {}
269   void enterBasicBlock(BasicBlock &BB) {}
270   void exitBasicBlock(BasicBlock &BB) {}
271
272   // Map Variable references to their rewritten definitions.
273   Variable *reduceVariableRef(Variable *Ovd) { return Ovd; }
274
275   // Map BasicBlock references to their rewritten definitions.
276   BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; }
277 };
278
279
280 class SExprCopier : public CopyReducer<SExprCopier> {
281 public:
282   typedef SExpr *R_SExpr;
283
284   SExprCopier(MemRegionRef A) : CopyReducer(A) { }
285
286   // Create a copy of e in region a.
287   static SExpr *copy(SExpr *E, MemRegionRef A) {
288     SExprCopier Copier(A);
289     return Copier.traverse(E, TRV_Normal);
290   }
291 };
292
293
294
295 // Base class for visit traversals.
296 class VisitReducerBase : public SimpleReducerBase {
297 public:
298   // A visitor returns a bool, representing success or failure.
299   typedef bool R_SExpr;
300   typedef bool R_BasicBlock;
301
302   // A visitor "container" is a single bool, which accumulates success.
303   template <class T> class Container {
304   public:
305     Container(VisitReducerBase &S, unsigned N) : Success(true) {}
306     void push_back(bool E) { Success = Success && E; }
307
308     bool Success;
309   };
310 };
311
312
313 // Implements a traversal that visits each subexpression, and returns either
314 // true or false.
315 template <class Self>
316 class VisitReducer : public Traversal<Self, VisitReducerBase>,
317                      public VisitReducerBase {
318 public:
319   VisitReducer() {}
320
321 public:
322   R_SExpr reduceNull() { return true; }
323   R_SExpr reduceUndefined(Undefined &Orig) { return true; }
324   R_SExpr reduceWildcard(Wildcard &Orig) { return true; }
325
326   R_SExpr reduceLiteral(Literal &Orig) { return true; }
327   template<class T>
328   R_SExpr reduceLiteralT(LiteralT<T> &Orig) { return true; }
329   R_SExpr reduceLiteralPtr(Literal &Orig) { return true; }
330
331   R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) {
332     return Nvd && E0;
333   }
334   R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) {
335     return Nvd && E0;
336   }
337   R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) {
338     return E0 && E1;
339   }
340   R_SExpr reduceField(Field &Orig, R_SExpr E0, R_SExpr E1) {
341     return E0 && E1;
342   }
343   R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) {
344     return E0 && E1;
345   }
346   R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) {
347     return E0 && E1;
348   }
349   R_SExpr reduceProject(Project &Orig, R_SExpr E0) { return E0; }
350   R_SExpr reduceCall(Call &Orig, R_SExpr E0) { return E0; }
351   R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) { return E0; }
352   R_SExpr reduceLoad(Load &Orig, R_SExpr E0) { return E0; }
353   R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) { return E0 && E1; }
354   R_SExpr reduceArrayIndex(Store &Orig, R_SExpr E0, R_SExpr E1) {
355     return E0 && E1;
356   }
357   R_SExpr reduceArrayAdd(Store &Orig, R_SExpr E0, R_SExpr E1) {
358     return E0 && E1;
359   }
360   R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) { return E0; }
361   R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) {
362     return E0 && E1;
363   }
364   R_SExpr reduceCast(Cast &Orig, R_SExpr E0) { return E0; }
365
366   R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> Bbs) {
367     return Bbs.Success;
368   }
369   R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container<Variable *> &As,
370                                 Container<Variable *> &Is, R_SExpr T) {
371     return (As.Success && Is.Success && T);
372   }
373   R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) {
374     return As.Success;
375   }
376   R_SExpr reduceGoto(Goto &Orig, BasicBlock *B) {
377     return true;
378   }
379   R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) {
380     return C;
381   }
382
383   R_SExpr reduceIdentifier(Identifier &Orig) {
384     return true;
385   }
386   R_SExpr reduceIfThenElse(IfThenElse &Orig, R_SExpr C, R_SExpr T, R_SExpr E) {
387     return C && T && E;
388   }
389   R_SExpr reduceLet(Let &Orig, Variable *Nvd, R_SExpr B) {
390     return Nvd && B;
391   }
392
393   Variable *enterScope(Variable &Orig, R_SExpr E0) { return &Orig; }
394   void exitScope(const Variable &Orig) {}
395   void enterCFG(SCFG &Cfg) {}
396   void exitCFG(SCFG &Cfg) {}
397   void enterBasicBlock(BasicBlock &BB) {}
398   void exitBasicBlock(BasicBlock &BB) {}
399
400   Variable   *reduceVariableRef  (Variable *Ovd)   { return Ovd; }
401   BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; }
402
403 public:
404   bool traverse(SExpr *E, TraversalKind K = TRV_Normal) {
405     Success = Success && this->traverseByCase(E);
406     return Success;
407   }
408
409   static bool visit(SExpr *E) {
410     Self Visitor;
411     return Visitor.traverse(E, TRV_Normal);
412   }
413
414 private:
415   bool Success;
416 };
417
418
419 // Basic class for comparison operations over expressions.
420 template <typename Self>
421 class Comparator {
422 protected:
423   Self *self() { return reinterpret_cast<Self *>(this); }
424
425 public:
426   bool compareByCase(SExpr *E1, SExpr* E2) {
427     switch (E1->opcode()) {
428 #define TIL_OPCODE_DEF(X)                                                     \
429     case COP_##X:                                                             \
430       return cast<X>(E1)->compare(cast<X>(E2), *self());
431 #include "ThreadSafetyOps.def"
432 #undef TIL_OPCODE_DEF
433     }
434   }
435 };
436
437
438 class EqualsComparator : public Comparator<EqualsComparator> {
439 public:
440   // Result type for the comparison, e.g. bool for simple equality,
441   // or int for lexigraphic comparison (-1, 0, 1).  Must have one value which
442   // denotes "true".
443   typedef bool CType;
444
445   CType trueResult() { return true; }
446   bool notTrue(CType ct) { return !ct; }
447
448   bool compareIntegers(unsigned i, unsigned j)       { return i == j; }
449   bool compareStrings (StringRef s, StringRef r)     { return s == r; }
450   bool comparePointers(const void* P, const void* Q) { return P == Q; }
451
452   bool compare(SExpr *E1, SExpr* E2) {
453     if (E1->opcode() != E2->opcode())
454       return false;
455     return compareByCase(E1, E2);
456   }
457
458   // TODO -- handle alpha-renaming of variables
459   void enterScope(Variable* V1, Variable* V2) { }
460   void leaveScope() { }
461
462   bool compareVariableRefs(Variable* V1, Variable* V2) {
463     return V1 == V2;
464   }
465
466   static bool compareExprs(SExpr *E1, SExpr* E2) {
467     EqualsComparator Eq;
468     return Eq.compare(E1, E2);
469   }
470 };
471
472
473 // Pretty printer for TIL expressions
474 template <typename Self, typename StreamType>
475 class PrettyPrinter {
476 private:
477   bool Verbose;  // Print out additional information
478   bool Cleanup;  // Omit redundant decls.
479
480 public:
481   PrettyPrinter(bool V = false, bool C = true) : Verbose(V), Cleanup(C) { }
482
483   static void print(SExpr *E, StreamType &SS) {
484     Self printer;
485     printer.printSExpr(E, SS, Prec_MAX);
486   }
487
488 protected:
489   Self *self() { return reinterpret_cast<Self *>(this); }
490
491   void newline(StreamType &SS) {
492     SS << "\n";
493   }
494
495   // TODO: further distinguish between binary operations.
496   static const unsigned Prec_Atom = 0;
497   static const unsigned Prec_Postfix = 1;
498   static const unsigned Prec_Unary = 2;
499   static const unsigned Prec_Binary = 3;
500   static const unsigned Prec_Other = 4;
501   static const unsigned Prec_Decl = 5;
502   static const unsigned Prec_MAX = 6;
503
504   // Return the precedence of a given node, for use in pretty printing.
505   unsigned precedence(SExpr *E) {
506     switch (E->opcode()) {
507       case COP_Future:     return Prec_Atom;
508       case COP_Undefined:  return Prec_Atom;
509       case COP_Wildcard:   return Prec_Atom;
510
511       case COP_Literal:    return Prec_Atom;
512       case COP_LiteralPtr: return Prec_Atom;
513       case COP_Variable:   return Prec_Atom;
514       case COP_Function:   return Prec_Decl;
515       case COP_SFunction:  return Prec_Decl;
516       case COP_Code:       return Prec_Decl;
517       case COP_Field:      return Prec_Decl;
518
519       case COP_Apply:      return Prec_Postfix;
520       case COP_SApply:     return Prec_Postfix;
521       case COP_Project:    return Prec_Postfix;
522
523       case COP_Call:       return Prec_Postfix;
524       case COP_Alloc:      return Prec_Other;
525       case COP_Load:       return Prec_Postfix;
526       case COP_Store:      return Prec_Other;
527       case COP_ArrayIndex: return Prec_Postfix;
528       case COP_ArrayAdd:   return Prec_Postfix;
529
530       case COP_UnaryOp:    return Prec_Unary;
531       case COP_BinaryOp:   return Prec_Binary;
532       case COP_Cast:       return Prec_Unary;
533
534       case COP_SCFG:       return Prec_Decl;
535       case COP_BasicBlock: return Prec_MAX;
536       case COP_Phi:        return Prec_Atom;
537       case COP_Goto:       return Prec_Atom;
538       case COP_Branch:     return Prec_Atom;
539
540       case COP_Identifier: return Prec_Atom;
541       case COP_IfThenElse: return Prec_Other;
542       case COP_Let:        return Prec_Decl;
543     }
544     return Prec_MAX;
545   }
546
547   void printBlockLabel(StreamType & SS, BasicBlock *BB, unsigned index) {
548     if (!BB) {
549       SS << "BB_null";
550       return;
551     }
552     SS << "BB_";
553     SS << BB->blockID();
554     SS << ":";
555     SS << index;
556   }
557
558   void printSExpr(SExpr *E, StreamType &SS, unsigned P) {
559     if (!E) {
560       self()->printNull(SS);
561       return;
562     }
563     if (self()->precedence(E) > P) {
564       // Wrap expr in () if necessary.
565       SS << "(";
566       self()->printSExpr(E, SS, Prec_MAX);
567       SS << ")";
568       return;
569     }
570
571     switch (E->opcode()) {
572 #define TIL_OPCODE_DEF(X)                                                  \
573     case COP_##X:                                                          \
574       self()->print##X(cast<X>(E), SS);                                    \
575       return;
576 #include "ThreadSafetyOps.def"
577 #undef TIL_OPCODE_DEF
578     }
579   }
580
581   void printNull(StreamType &SS) {
582     SS << "#null";
583   }
584
585   void printFuture(Future *E, StreamType &SS) {
586     self()->printSExpr(E->maybeGetResult(), SS, Prec_Atom);
587   }
588
589   void printUndefined(Undefined *E, StreamType &SS) {
590     SS << "#undefined";
591   }
592
593   void printWildcard(Wildcard *E, StreamType &SS) {
594     SS << "_";
595   }
596
597   template<class T>
598   void printLiteralT(LiteralT<T> *E, StreamType &SS) {
599     SS << E->value();
600   }
601
602   void printLiteralT(LiteralT<uint8_t> *E, StreamType &SS) {
603     SS << "'" << E->value() << "'";
604   }
605
606   void printLiteral(Literal *E, StreamType &SS) {
607     if (E->clangExpr()) {
608       SS << getSourceLiteralString(E->clangExpr());
609       return;
610     }
611     else {
612       ValueType VT = E->valueType();
613       switch (VT.Base) {
614       case ValueType::BT_Void: {
615         SS << "void";
616         return;
617       }
618       case ValueType::BT_Bool: {
619         if (E->as<bool>().value())
620           SS << "true";
621         else
622           SS << "false";
623         return;
624       }
625       case ValueType::BT_Int: {
626         switch (VT.Size) {
627         case ValueType::ST_8:
628           if (VT.Signed)
629             printLiteralT(&E->as<int8_t>(), SS);
630           else
631             printLiteralT(&E->as<uint8_t>(), SS);
632           return;
633         case ValueType::ST_16:
634           if (VT.Signed)
635             printLiteralT(&E->as<int16_t>(), SS);
636           else
637             printLiteralT(&E->as<uint16_t>(), SS);
638           return;
639         case ValueType::ST_32:
640           if (VT.Signed)
641             printLiteralT(&E->as<int32_t>(), SS);
642           else
643             printLiteralT(&E->as<uint32_t>(), SS);
644           return;
645         case ValueType::ST_64:
646           if (VT.Signed)
647             printLiteralT(&E->as<int64_t>(), SS);
648           else
649             printLiteralT(&E->as<uint64_t>(), SS);
650           return;
651         default:
652           break;
653         }
654         break;
655       }
656       case ValueType::BT_Float: {
657         switch (VT.Size) {
658         case ValueType::ST_32:
659           printLiteralT(&E->as<float>(), SS);
660           return;
661         case ValueType::ST_64:
662           printLiteralT(&E->as<double>(), SS);
663           return;
664         default:
665           break;
666         }
667         break;
668       }
669       case ValueType::BT_String: {
670         SS << "\"";
671         printLiteralT(&E->as<StringRef>(), SS);
672         SS << "\"";
673         return;
674       }
675       case ValueType::BT_Pointer: {
676         SS << "#ptr";
677         return;
678       }
679       case ValueType::BT_ValueRef: {
680         SS << "#vref";
681         return;
682       }
683       }
684     }
685     SS << "#lit";
686   }
687
688   void printLiteralPtr(LiteralPtr *E, StreamType &SS) {
689     SS << E->clangDecl()->getNameAsString();
690   }
691
692   void printVariable(Variable *V, StreamType &SS, bool IsVarDecl = false) {
693     if (!IsVarDecl && Cleanup) {
694       SExpr* E = getCanonicalVal(V);
695       if (E != V) {
696         printSExpr(E, SS, Prec_Atom);
697         return;
698       }
699     }
700     if (V->kind() == Variable::VK_LetBB)
701       SS << V->name() << V->getBlockID() << "_" << V->getID();
702     else
703       SS << V->name() << V->getID();
704   }
705
706   void printFunction(Function *E, StreamType &SS, unsigned sugared = 0) {
707     switch (sugared) {
708       default:
709         SS << "\\(";   // Lambda
710         break;
711       case 1:
712         SS << "(";     // Slot declarations
713         break;
714       case 2:
715         SS << ", ";    // Curried functions
716         break;
717     }
718     self()->printVariable(E->variableDecl(), SS, true);
719     SS << ": ";
720     self()->printSExpr(E->variableDecl()->definition(), SS, Prec_MAX);
721
722     SExpr *B = E->body();
723     if (B && B->opcode() == COP_Function)
724       self()->printFunction(cast<Function>(B), SS, 2);
725     else {
726       SS << ")";
727       self()->printSExpr(B, SS, Prec_Decl);
728     }
729   }
730
731   void printSFunction(SFunction *E, StreamType &SS) {
732     SS << "@";
733     self()->printVariable(E->variableDecl(), SS, true);
734     SS << " ";
735     self()->printSExpr(E->body(), SS, Prec_Decl);
736   }
737
738   void printCode(Code *E, StreamType &SS) {
739     SS << ": ";
740     self()->printSExpr(E->returnType(), SS, Prec_Decl-1);
741     SS << " -> ";
742     self()->printSExpr(E->body(), SS, Prec_Decl);
743   }
744
745   void printField(Field *E, StreamType &SS) {
746     SS << ": ";
747     self()->printSExpr(E->range(), SS, Prec_Decl-1);
748     SS << " = ";
749     self()->printSExpr(E->body(), SS, Prec_Decl);
750   }
751
752   void printApply(Apply *E, StreamType &SS, bool sugared = false) {
753     SExpr *F = E->fun();
754     if (F->opcode() == COP_Apply) {
755       printApply(cast<Apply>(F), SS, true);
756       SS << ", ";
757     } else {
758       self()->printSExpr(F, SS, Prec_Postfix);
759       SS << "(";
760     }
761     self()->printSExpr(E->arg(), SS, Prec_MAX);
762     if (!sugared)
763       SS << ")$";
764   }
765
766   void printSApply(SApply *E, StreamType &SS) {
767     self()->printSExpr(E->sfun(), SS, Prec_Postfix);
768     if (E->isDelegation()) {
769       SS << "@(";
770       self()->printSExpr(E->arg(), SS, Prec_MAX);
771       SS << ")";
772     }
773   }
774
775   void printProject(Project *E, StreamType &SS) {
776     self()->printSExpr(E->record(), SS, Prec_Postfix);
777     SS << ".";
778     SS << E->slotName();
779   }
780
781   void printCall(Call *E, StreamType &SS) {
782     SExpr *T = E->target();
783     if (T->opcode() == COP_Apply) {
784       self()->printApply(cast<Apply>(T), SS, true);
785       SS << ")";
786     }
787     else {
788       self()->printSExpr(T, SS, Prec_Postfix);
789       SS << "()";
790     }
791   }
792
793   void printAlloc(Alloc *E, StreamType &SS) {
794     SS << "new ";
795     self()->printSExpr(E->dataType(), SS, Prec_Other-1);
796   }
797
798   void printLoad(Load *E, StreamType &SS) {
799     self()->printSExpr(E->pointer(), SS, Prec_Postfix);
800     SS << "^";
801   }
802
803   void printStore(Store *E, StreamType &SS) {
804     self()->printSExpr(E->destination(), SS, Prec_Other-1);
805     SS << " := ";
806     self()->printSExpr(E->source(), SS, Prec_Other-1);
807   }
808
809   void printArrayIndex(ArrayIndex *E, StreamType &SS) {
810     self()->printSExpr(E->array(), SS, Prec_Postfix);
811     SS << "[";
812     self()->printSExpr(E->index(), SS, Prec_MAX);
813     SS << "]";
814   }
815
816   void printArrayAdd(ArrayAdd *E, StreamType &SS) {
817     self()->printSExpr(E->array(), SS, Prec_Postfix);
818     SS << " + ";
819     self()->printSExpr(E->index(), SS, Prec_Atom);
820   }
821
822   void printUnaryOp(UnaryOp *E, StreamType &SS) {
823     SS << getUnaryOpcodeString(E->unaryOpcode());
824     self()->printSExpr(E->expr(), SS, Prec_Unary);
825   }
826
827   void printBinaryOp(BinaryOp *E, StreamType &SS) {
828     self()->printSExpr(E->expr0(), SS, Prec_Binary-1);
829     SS << " " << getBinaryOpcodeString(E->binaryOpcode()) << " ";
830     self()->printSExpr(E->expr1(), SS, Prec_Binary-1);
831   }
832
833   void printCast(Cast *E, StreamType &SS) {
834     SS << "%";
835     self()->printSExpr(E->expr(), SS, Prec_Unary);
836   }
837
838   void printSCFG(SCFG *E, StreamType &SS) {
839     SS << "CFG {\n";
840     for (auto BBI : *E) {
841       printBasicBlock(BBI, SS);
842     }
843     SS << "}";
844     newline(SS);
845   }
846
847   void printBasicBlock(BasicBlock *E, StreamType &SS) {
848     SS << "BB_" << E->blockID() << ":";
849     if (E->parent())
850       SS << " BB_" << E->parent()->blockID();
851     newline(SS);
852     for (auto *A : E->arguments()) {
853       SS << "let ";
854       self()->printVariable(A, SS, true);
855       SS << " = ";
856       self()->printSExpr(A->definition(), SS, Prec_MAX);
857       SS << ";";
858       newline(SS);
859     }
860     for (auto *I : E->instructions()) {
861       if (I->definition()->opcode() != COP_Store) {
862         SS << "let ";
863         self()->printVariable(I, SS, true);
864         SS << " = ";
865       }
866       self()->printSExpr(I->definition(), SS, Prec_MAX);
867       SS << ";";
868       newline(SS);
869     }
870     SExpr *T = E->terminator();
871     if (T) {
872       self()->printSExpr(T, SS, Prec_MAX);
873       SS << ";";
874       newline(SS);
875     }
876     newline(SS);
877   }
878
879   void printPhi(Phi *E, StreamType &SS) {
880     SS << "phi(";
881     if (E->status() == Phi::PH_SingleVal)
882       self()->printSExpr(E->values()[0], SS, Prec_MAX);
883     else {
884       unsigned i = 0;
885       for (auto V : E->values()) {
886         if (i++ > 0)
887           SS << ", ";
888         self()->printSExpr(V, SS, Prec_MAX);
889       }
890     }
891     SS << ")";
892   }
893
894   void printGoto(Goto *E, StreamType &SS) {
895     SS << "goto ";
896     printBlockLabel(SS, E->targetBlock(), E->index());
897   }
898
899   void printBranch(Branch *E, StreamType &SS) {
900     SS << "branch (";
901     self()->printSExpr(E->condition(), SS, Prec_MAX);
902     SS << ") ";
903     printBlockLabel(SS, E->thenBlock(), E->thenIndex());
904     SS << " ";
905     printBlockLabel(SS, E->elseBlock(), E->elseIndex());
906   }
907
908   void printIdentifier(Identifier *E, StreamType &SS) {
909     SS << E->name();
910   }
911
912   void printIfThenElse(IfThenElse *E, StreamType &SS) {
913     SS << "if (";
914     printSExpr(E->condition(), SS, Prec_MAX);
915     SS << ") then ";
916     printSExpr(E->thenExpr(), SS, Prec_Other);
917     SS << " else ";
918     printSExpr(E->elseExpr(), SS, Prec_Other);
919   }
920
921   void printLet(Let *E, StreamType &SS) {
922     SS << "let ";
923     printVariable(E->variableDecl(), SS, true);
924     SS << " = ";
925     printSExpr(E->variableDecl()->definition(), SS, Prec_Decl-1);
926     SS << "; ";
927     printSExpr(E->body(), SS, Prec_Decl-1);
928   }
929 };
930
931
932 } // end namespace til
933 } // end namespace threadSafety
934 } // end namespace clang
935
936 #endif  // LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H