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