clang API Documentation

ThreadSafetyTraverse.h
Go to the documentation of this file.
00001 //===- ThreadSafetyTraverse.h ----------------------------------*- C++ --*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file defines a framework for doing generic traversals and rewriting
00011 // operations over the Thread Safety TIL.
00012 //
00013 // UNDER CONSTRUCTION.  USE AT YOUR OWN RISK.
00014 //
00015 //===----------------------------------------------------------------------===//
00016 
00017 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H
00018 #define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H
00019 
00020 #include "ThreadSafetyTIL.h"
00021 
00022 #include <ostream>
00023 
00024 namespace clang {
00025 namespace threadSafety {
00026 namespace til {
00027 
00028 // Defines an interface used to traverse SExprs.  Traversals have been made as
00029 // generic as possible, and are intended to handle any kind of pass over the
00030 // AST, e.g. visiters, copying, non-destructive rewriting, destructive
00031 // (in-place) rewriting, hashing, typing, etc.
00032 //
00033 // Traversals implement the functional notion of a "fold" operation on SExprs.
00034 // Each SExpr class provides a traverse method, which does the following:
00035 //   * e->traverse(v):
00036 //       // compute a result r_i for each subexpression e_i
00037 //       for (i = 1..n)  r_i = v.traverse(e_i);
00038 //       // combine results into a result for e,  where X is the class of e
00039 //       return v.reduceX(*e, r_1, .. r_n).
00040 //
00041 // A visitor can control the traversal by overriding the following methods:
00042 //   * v.traverse(e):
00043 //       return v.traverseByCase(e), which returns v.traverseX(e)
00044 //   * v.traverseX(e):   (X is the class of e)
00045 //       return e->traverse(v).
00046 //   * v.reduceX(*e, r_1, .. r_n):
00047 //       compute a result for a node of type X
00048 //
00049 // The reduceX methods control the kind of traversal (visitor, copy, etc.).
00050 // They are defined in derived classes.
00051 //
00052 // Class R defines the basic interface types (R_SExpr).
00053 template <class Self, class R>
00054 class Traversal {
00055 public:
00056   Self *self() { return static_cast<Self *>(this); }
00057 
00058   // Traverse an expression -- returning a result of type R_SExpr.
00059   // Override this method to do something for every expression, regardless
00060   // of which kind it is.
00061   // E is a reference, so this can be use for in-place updates.
00062   // The type T must be a subclass of SExpr.
00063   template <class T>
00064   typename R::R_SExpr traverse(T* &E, typename R::R_Ctx Ctx) {
00065     return traverseSExpr(E, Ctx);
00066   }
00067 
00068   // Override this method to do something for every expression.
00069   // Does not allow in-place updates.
00070   typename R::R_SExpr traverseSExpr(SExpr *E, typename R::R_Ctx Ctx) {
00071     return traverseByCase(E, Ctx);
00072   }
00073 
00074   // Helper method to call traverseX(e) on the appropriate type.
00075   typename R::R_SExpr traverseByCase(SExpr *E, typename R::R_Ctx Ctx) {
00076     switch (E->opcode()) {
00077 #define TIL_OPCODE_DEF(X)                                                   \
00078     case COP_##X:                                                           \
00079       return self()->traverse##X(cast<X>(E), Ctx);
00080 #include "ThreadSafetyOps.def"
00081 #undef TIL_OPCODE_DEF
00082     }
00083     return self()->reduceNull();
00084   }
00085 
00086 // Traverse e, by static dispatch on the type "X" of e.
00087 // Override these methods to do something for a particular kind of term.
00088 #define TIL_OPCODE_DEF(X)                                                   \
00089   typename R::R_SExpr traverse##X(X *e, typename R::R_Ctx Ctx) {            \
00090     return e->traverse(*self(), Ctx);                                       \
00091   }
00092 #include "ThreadSafetyOps.def"
00093 #undef TIL_OPCODE_DEF
00094 };
00095 
00096 
00097 // Base class for simple reducers that don't much care about the context.
00098 class SimpleReducerBase {
00099 public:
00100   enum TraversalKind {
00101     TRV_Normal,   // ordinary subexpressions
00102     TRV_Decl,     // declarations (e.g. function bodies)
00103     TRV_Lazy,     // expressions that require lazy evaluation
00104     TRV_Type      // type expressions
00105   };
00106 
00107   // R_Ctx defines a "context" for the traversal, which encodes information
00108   // about where a term appears.  This can be used to encoding the
00109   // "current continuation" for CPS transforms, or other information.
00110   typedef TraversalKind R_Ctx;
00111 
00112   // Create context for an ordinary subexpression.
00113   R_Ctx subExprCtx(R_Ctx Ctx) { return TRV_Normal; }
00114 
00115   // Create context for a subexpression that occurs in a declaration position
00116   // (e.g. function body).
00117   R_Ctx declCtx(R_Ctx Ctx) { return TRV_Decl; }
00118 
00119   // Create context for a subexpression that occurs in a position that
00120   // should be reduced lazily.  (e.g. code body).
00121   R_Ctx lazyCtx(R_Ctx Ctx) { return TRV_Lazy; }
00122 
00123   // Create context for a subexpression that occurs in a type position.
00124   R_Ctx typeCtx(R_Ctx Ctx) { return TRV_Type; }
00125 };
00126 
00127 
00128 // Base class for traversals that rewrite an SExpr to another SExpr.
00129 class CopyReducerBase : public SimpleReducerBase {
00130 public:
00131   // R_SExpr is the result type for a traversal.
00132   // A copy or non-destructive rewrite returns a newly allocated term.
00133   typedef SExpr *R_SExpr;
00134   typedef BasicBlock *R_BasicBlock;
00135 
00136   // Container is a minimal interface used to store results when traversing
00137   // SExprs of variable arity, such as Phi, Goto, and SCFG.
00138   template <class T> class Container {
00139   public:
00140     // Allocate a new container with a capacity for n elements.
00141     Container(CopyReducerBase &S, unsigned N) : Elems(S.Arena, N) {}
00142 
00143     // Push a new element onto the container.
00144     void push_back(T E) { Elems.push_back(E); }
00145 
00146     SimpleArray<T> Elems;
00147   };
00148 
00149   CopyReducerBase(MemRegionRef A) : Arena(A) {}
00150 
00151 protected:
00152   MemRegionRef Arena;
00153 };
00154 
00155 
00156 // Base class for visit traversals.
00157 class VisitReducerBase : public SimpleReducerBase {
00158 public:
00159   // A visitor returns a bool, representing success or failure.
00160   typedef bool R_SExpr;
00161   typedef bool R_BasicBlock;
00162 
00163   // A visitor "container" is a single bool, which accumulates success.
00164   template <class T> class Container {
00165   public:
00166     Container(VisitReducerBase &S, unsigned N) : Success(true) {}
00167     void push_back(bool E) { Success = Success && E; }
00168 
00169     bool Success;
00170   };
00171 };
00172 
00173 
00174 // Implements a traversal that visits each subexpression, and returns either
00175 // true or false.
00176 template <class Self>
00177 class VisitReducer : public Traversal<Self, VisitReducerBase>,
00178                      public VisitReducerBase {
00179 public:
00180   VisitReducer() {}
00181 
00182 public:
00183   R_SExpr reduceNull() { return true; }
00184   R_SExpr reduceUndefined(Undefined &Orig) { return true; }
00185   R_SExpr reduceWildcard(Wildcard &Orig) { return true; }
00186 
00187   R_SExpr reduceLiteral(Literal &Orig) { return true; }
00188   template<class T>
00189   R_SExpr reduceLiteralT(LiteralT<T> &Orig) { return true; }
00190   R_SExpr reduceLiteralPtr(Literal &Orig) { return true; }
00191 
00192   R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) {
00193     return Nvd && E0;
00194   }
00195   R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) {
00196     return Nvd && E0;
00197   }
00198   R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) {
00199     return E0 && E1;
00200   }
00201   R_SExpr reduceField(Field &Orig, R_SExpr E0, R_SExpr E1) {
00202     return E0 && E1;
00203   }
00204   R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) {
00205     return E0 && E1;
00206   }
00207   R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) {
00208     return E0 && E1;
00209   }
00210   R_SExpr reduceProject(Project &Orig, R_SExpr E0) { return E0; }
00211   R_SExpr reduceCall(Call &Orig, R_SExpr E0) { return E0; }
00212   R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) { return E0; }
00213   R_SExpr reduceLoad(Load &Orig, R_SExpr E0) { return E0; }
00214   R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) { return E0 && E1; }
00215   R_SExpr reduceArrayIndex(Store &Orig, R_SExpr E0, R_SExpr E1) {
00216     return E0 && E1;
00217   }
00218   R_SExpr reduceArrayAdd(Store &Orig, R_SExpr E0, R_SExpr E1) {
00219     return E0 && E1;
00220   }
00221   R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) { return E0; }
00222   R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) {
00223     return E0 && E1;
00224   }
00225   R_SExpr reduceCast(Cast &Orig, R_SExpr E0) { return E0; }
00226 
00227   R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> Bbs) {
00228     return Bbs.Success;
00229   }
00230   R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container<R_SExpr> &As,
00231                                 Container<R_SExpr> &Is, R_SExpr T) {
00232     return (As.Success && Is.Success && T);
00233   }
00234   R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) {
00235     return As.Success;
00236   }
00237   R_SExpr reduceGoto(Goto &Orig, BasicBlock *B) {
00238     return true;
00239   }
00240   R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) {
00241     return C;
00242   }
00243   R_SExpr reduceReturn(Return &O, R_SExpr E) {
00244     return E;
00245   }
00246 
00247   R_SExpr reduceIdentifier(Identifier &Orig) {
00248     return true;
00249   }
00250   R_SExpr reduceIfThenElse(IfThenElse &Orig, R_SExpr C, R_SExpr T, R_SExpr E) {
00251     return C && T && E;
00252   }
00253   R_SExpr reduceLet(Let &Orig, Variable *Nvd, R_SExpr B) {
00254     return Nvd && B;
00255   }
00256 
00257   Variable *enterScope(Variable &Orig, R_SExpr E0) { return &Orig; }
00258   void exitScope(const Variable &Orig) {}
00259   void enterCFG(SCFG &Cfg) {}
00260   void exitCFG(SCFG &Cfg) {}
00261   void enterBasicBlock(BasicBlock &BB) {}
00262   void exitBasicBlock(BasicBlock &BB) {}
00263 
00264   Variable   *reduceVariableRef  (Variable *Ovd)   { return Ovd; }
00265   BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; }
00266 
00267 public:
00268   bool traverse(SExpr *E, TraversalKind K = TRV_Normal) {
00269     Success = Success && this->traverseByCase(E);
00270     return Success;
00271   }
00272 
00273   static bool visit(SExpr *E) {
00274     Self Visitor;
00275     return Visitor.traverse(E, TRV_Normal);
00276   }
00277 
00278 private:
00279   bool Success;
00280 };
00281 
00282 
00283 // Basic class for comparison operations over expressions.
00284 template <typename Self>
00285 class Comparator {
00286 protected:
00287   Self *self() { return reinterpret_cast<Self *>(this); }
00288 
00289 public:
00290   bool compareByCase(const SExpr *E1, const SExpr* E2) {
00291     switch (E1->opcode()) {
00292 #define TIL_OPCODE_DEF(X)                                                     \
00293     case COP_##X:                                                             \
00294       return cast<X>(E1)->compare(cast<X>(E2), *self());
00295 #include "ThreadSafetyOps.def"
00296 #undef TIL_OPCODE_DEF
00297     }
00298     return false;
00299   }
00300 };
00301 
00302 
00303 class EqualsComparator : public Comparator<EqualsComparator> {
00304 public:
00305   // Result type for the comparison, e.g. bool for simple equality,
00306   // or int for lexigraphic comparison (-1, 0, 1).  Must have one value which
00307   // denotes "true".
00308   typedef bool CType;
00309 
00310   CType trueResult() { return true; }
00311   bool notTrue(CType ct) { return !ct; }
00312 
00313   bool compareIntegers(unsigned i, unsigned j)       { return i == j; }
00314   bool compareStrings (StringRef s, StringRef r)     { return s == r; }
00315   bool comparePointers(const void* P, const void* Q) { return P == Q; }
00316 
00317   bool compare(const SExpr *E1, const SExpr* E2) {
00318     if (E1->opcode() != E2->opcode())
00319       return false;
00320     return compareByCase(E1, E2);
00321   }
00322 
00323   // TODO -- handle alpha-renaming of variables
00324   void enterScope(const Variable* V1, const Variable* V2) { }
00325   void leaveScope() { }
00326 
00327   bool compareVariableRefs(const Variable* V1, const Variable* V2) {
00328     return V1 == V2;
00329   }
00330 
00331   static bool compareExprs(const SExpr *E1, const SExpr* E2) {
00332     EqualsComparator Eq;
00333     return Eq.compare(E1, E2);
00334   }
00335 };
00336 
00337 
00338 
00339 class MatchComparator : public Comparator<MatchComparator> {
00340 public:
00341   // Result type for the comparison, e.g. bool for simple equality,
00342   // or int for lexigraphic comparison (-1, 0, 1).  Must have one value which
00343   // denotes "true".
00344   typedef bool CType;
00345 
00346   CType trueResult() { return true; }
00347   bool notTrue(CType ct) { return !ct; }
00348 
00349   bool compareIntegers(unsigned i, unsigned j)       { return i == j; }
00350   bool compareStrings (StringRef s, StringRef r)     { return s == r; }
00351   bool comparePointers(const void* P, const void* Q) { return P == Q; }
00352 
00353   bool compare(const SExpr *E1, const SExpr* E2) {
00354     // Wildcards match anything.
00355     if (E1->opcode() == COP_Wildcard || E2->opcode() == COP_Wildcard)
00356       return true;
00357     // otherwise normal equality.
00358     if (E1->opcode() != E2->opcode())
00359       return false;
00360     return compareByCase(E1, E2);
00361   }
00362 
00363   // TODO -- handle alpha-renaming of variables
00364   void enterScope(const Variable* V1, const Variable* V2) { }
00365   void leaveScope() { }
00366 
00367   bool compareVariableRefs(const Variable* V1, const Variable* V2) {
00368     return V1 == V2;
00369   }
00370 
00371   static bool compareExprs(const SExpr *E1, const SExpr* E2) {
00372     MatchComparator Matcher;
00373     return Matcher.compare(E1, E2);
00374   }
00375 };
00376 
00377 
00378 
00379 // inline std::ostream& operator<<(std::ostream& SS, StringRef R) {
00380 //   return SS.write(R.data(), R.size());
00381 // }
00382 
00383 // Pretty printer for TIL expressions
00384 template <typename Self, typename StreamType>
00385 class PrettyPrinter {
00386 private:
00387   bool Verbose;  // Print out additional information
00388   bool Cleanup;  // Omit redundant decls.
00389   bool CStyle;   // Print exprs in C-like syntax.
00390 
00391 public:
00392   PrettyPrinter(bool V = false, bool C = true, bool CS = true)
00393      : Verbose(V), Cleanup(C), CStyle(CS)
00394   {}
00395 
00396   static void print(const SExpr *E, StreamType &SS) {
00397     Self printer;
00398     printer.printSExpr(E, SS, Prec_MAX);
00399   }
00400 
00401 protected:
00402   Self *self() { return reinterpret_cast<Self *>(this); }
00403 
00404   void newline(StreamType &SS) {
00405     SS << "\n";
00406   }
00407 
00408   // TODO: further distinguish between binary operations.
00409   static const unsigned Prec_Atom = 0;
00410   static const unsigned Prec_Postfix = 1;
00411   static const unsigned Prec_Unary = 2;
00412   static const unsigned Prec_Binary = 3;
00413   static const unsigned Prec_Other = 4;
00414   static const unsigned Prec_Decl = 5;
00415   static const unsigned Prec_MAX = 6;
00416 
00417   // Return the precedence of a given node, for use in pretty printing.
00418   unsigned precedence(const SExpr *E) {
00419     switch (E->opcode()) {
00420       case COP_Future:     return Prec_Atom;
00421       case COP_Undefined:  return Prec_Atom;
00422       case COP_Wildcard:   return Prec_Atom;
00423 
00424       case COP_Literal:    return Prec_Atom;
00425       case COP_LiteralPtr: return Prec_Atom;
00426       case COP_Variable:   return Prec_Atom;
00427       case COP_Function:   return Prec_Decl;
00428       case COP_SFunction:  return Prec_Decl;
00429       case COP_Code:       return Prec_Decl;
00430       case COP_Field:      return Prec_Decl;
00431 
00432       case COP_Apply:      return Prec_Postfix;
00433       case COP_SApply:     return Prec_Postfix;
00434       case COP_Project:    return Prec_Postfix;
00435 
00436       case COP_Call:       return Prec_Postfix;
00437       case COP_Alloc:      return Prec_Other;
00438       case COP_Load:       return Prec_Postfix;
00439       case COP_Store:      return Prec_Other;
00440       case COP_ArrayIndex: return Prec_Postfix;
00441       case COP_ArrayAdd:   return Prec_Postfix;
00442 
00443       case COP_UnaryOp:    return Prec_Unary;
00444       case COP_BinaryOp:   return Prec_Binary;
00445       case COP_Cast:       return Prec_Atom;
00446 
00447       case COP_SCFG:       return Prec_Decl;
00448       case COP_BasicBlock: return Prec_MAX;
00449       case COP_Phi:        return Prec_Atom;
00450       case COP_Goto:       return Prec_Atom;
00451       case COP_Branch:     return Prec_Atom;
00452       case COP_Return:     return Prec_Other;
00453 
00454       case COP_Identifier: return Prec_Atom;
00455       case COP_IfThenElse: return Prec_Other;
00456       case COP_Let:        return Prec_Decl;
00457     }
00458     return Prec_MAX;
00459   }
00460 
00461   void printBlockLabel(StreamType & SS, const BasicBlock *BB, int index) {
00462     if (!BB) {
00463       SS << "BB_null";
00464       return;
00465     }
00466     SS << "BB_";
00467     SS << BB->blockID();
00468     if (index >= 0) {
00469       SS << ":";
00470       SS << index;
00471     }
00472   }
00473 
00474 
00475   void printSExpr(const SExpr *E, StreamType &SS, unsigned P, bool Sub=true) {
00476     if (!E) {
00477       self()->printNull(SS);
00478       return;
00479     }
00480     if (Sub && E->block() && E->opcode() != COP_Variable) {
00481       SS << "_x" << E->id();
00482       return;
00483     }
00484     if (self()->precedence(E) > P) {
00485       // Wrap expr in () if necessary.
00486       SS << "(";
00487       self()->printSExpr(E, SS, Prec_MAX);
00488       SS << ")";
00489       return;
00490     }
00491 
00492     switch (E->opcode()) {
00493 #define TIL_OPCODE_DEF(X)                                                  \
00494     case COP_##X:                                                          \
00495       self()->print##X(cast<X>(E), SS);                                    \
00496       return;
00497 #include "ThreadSafetyOps.def"
00498 #undef TIL_OPCODE_DEF
00499     }
00500   }
00501 
00502   void printNull(StreamType &SS) {
00503     SS << "#null";
00504   }
00505 
00506   void printFuture(const Future *E, StreamType &SS) {
00507     self()->printSExpr(E->maybeGetResult(), SS, Prec_Atom);
00508   }
00509 
00510   void printUndefined(const Undefined *E, StreamType &SS) {
00511     SS << "#undefined";
00512   }
00513 
00514   void printWildcard(const Wildcard *E, StreamType &SS) {
00515     SS << "*";
00516   }
00517 
00518   template<class T>
00519   void printLiteralT(const LiteralT<T> *E, StreamType &SS) {
00520     SS << E->value();
00521   }
00522 
00523   void printLiteralT(const LiteralT<uint8_t> *E, StreamType &SS) {
00524     SS << "'" << E->value() << "'";
00525   }
00526 
00527   void printLiteral(const Literal *E, StreamType &SS) {
00528     if (E->clangExpr()) {
00529       SS << getSourceLiteralString(E->clangExpr());
00530       return;
00531     }
00532     else {
00533       ValueType VT = E->valueType();
00534       switch (VT.Base) {
00535       case ValueType::BT_Void: {
00536         SS << "void";
00537         return;
00538       }
00539       case ValueType::BT_Bool: {
00540         if (E->as<bool>().value())
00541           SS << "true";
00542         else
00543           SS << "false";
00544         return;
00545       }
00546       case ValueType::BT_Int: {
00547         switch (VT.Size) {
00548         case ValueType::ST_8:
00549           if (VT.Signed)
00550             printLiteralT(&E->as<int8_t>(), SS);
00551           else
00552             printLiteralT(&E->as<uint8_t>(), SS);
00553           return;
00554         case ValueType::ST_16:
00555           if (VT.Signed)
00556             printLiteralT(&E->as<int16_t>(), SS);
00557           else
00558             printLiteralT(&E->as<uint16_t>(), SS);
00559           return;
00560         case ValueType::ST_32:
00561           if (VT.Signed)
00562             printLiteralT(&E->as<int32_t>(), SS);
00563           else
00564             printLiteralT(&E->as<uint32_t>(), SS);
00565           return;
00566         case ValueType::ST_64:
00567           if (VT.Signed)
00568             printLiteralT(&E->as<int64_t>(), SS);
00569           else
00570             printLiteralT(&E->as<uint64_t>(), SS);
00571           return;
00572         default:
00573           break;
00574         }
00575         break;
00576       }
00577       case ValueType::BT_Float: {
00578         switch (VT.Size) {
00579         case ValueType::ST_32:
00580           printLiteralT(&E->as<float>(), SS);
00581           return;
00582         case ValueType::ST_64:
00583           printLiteralT(&E->as<double>(), SS);
00584           return;
00585         default:
00586           break;
00587         }
00588         break;
00589       }
00590       case ValueType::BT_String: {
00591         SS << "\"";
00592         printLiteralT(&E->as<StringRef>(), SS);
00593         SS << "\"";
00594         return;
00595       }
00596       case ValueType::BT_Pointer: {
00597         SS << "#ptr";
00598         return;
00599       }
00600       case ValueType::BT_ValueRef: {
00601         SS << "#vref";
00602         return;
00603       }
00604       }
00605     }
00606     SS << "#lit";
00607   }
00608 
00609   void printLiteralPtr(const LiteralPtr *E, StreamType &SS) {
00610     SS << E->clangDecl()->getNameAsString();
00611   }
00612 
00613   void printVariable(const Variable *V, StreamType &SS, bool IsVarDecl=false) {
00614     if (CStyle && V->kind() == Variable::VK_SFun)
00615       SS << "this";
00616     else
00617       SS << V->name() << V->id();
00618   }
00619 
00620   void printFunction(const Function *E, StreamType &SS, unsigned sugared = 0) {
00621     switch (sugared) {
00622       default:
00623         SS << "\\(";   // Lambda
00624         break;
00625       case 1:
00626         SS << "(";     // Slot declarations
00627         break;
00628       case 2:
00629         SS << ", ";    // Curried functions
00630         break;
00631     }
00632     self()->printVariable(E->variableDecl(), SS, true);
00633     SS << ": ";
00634     self()->printSExpr(E->variableDecl()->definition(), SS, Prec_MAX);
00635 
00636     const SExpr *B = E->body();
00637     if (B && B->opcode() == COP_Function)
00638       self()->printFunction(cast<Function>(B), SS, 2);
00639     else {
00640       SS << ")";
00641       self()->printSExpr(B, SS, Prec_Decl);
00642     }
00643   }
00644 
00645   void printSFunction(const SFunction *E, StreamType &SS) {
00646     SS << "@";
00647     self()->printVariable(E->variableDecl(), SS, true);
00648     SS << " ";
00649     self()->printSExpr(E->body(), SS, Prec_Decl);
00650   }
00651 
00652   void printCode(const Code *E, StreamType &SS) {
00653     SS << ": ";
00654     self()->printSExpr(E->returnType(), SS, Prec_Decl-1);
00655     SS << " -> ";
00656     self()->printSExpr(E->body(), SS, Prec_Decl);
00657   }
00658 
00659   void printField(const Field *E, StreamType &SS) {
00660     SS << ": ";
00661     self()->printSExpr(E->range(), SS, Prec_Decl-1);
00662     SS << " = ";
00663     self()->printSExpr(E->body(), SS, Prec_Decl);
00664   }
00665 
00666   void printApply(const Apply *E, StreamType &SS, bool sugared = false) {
00667     const SExpr *F = E->fun();
00668     if (F->opcode() == COP_Apply) {
00669       printApply(cast<Apply>(F), SS, true);
00670       SS << ", ";
00671     } else {
00672       self()->printSExpr(F, SS, Prec_Postfix);
00673       SS << "(";
00674     }
00675     self()->printSExpr(E->arg(), SS, Prec_MAX);
00676     if (!sugared)
00677       SS << ")$";
00678   }
00679 
00680   void printSApply(const SApply *E, StreamType &SS) {
00681     self()->printSExpr(E->sfun(), SS, Prec_Postfix);
00682     if (E->isDelegation()) {
00683       SS << "@(";
00684       self()->printSExpr(E->arg(), SS, Prec_MAX);
00685       SS << ")";
00686     }
00687   }
00688 
00689   void printProject(const Project *E, StreamType &SS) {
00690     if (CStyle) {
00691       // Omit the  this->
00692       if (const SApply *SAP = dyn_cast<SApply>(E->record())) {
00693         if (const Variable *V = dyn_cast<Variable>(SAP->sfun())) {
00694           if (!SAP->isDelegation() && V->kind() == Variable::VK_SFun) {
00695             SS << E->slotName();
00696             return;
00697           }
00698         }
00699       }
00700       if (isa<Wildcard>(E->record())) {
00701         // handle existentials
00702         SS << "&";
00703         SS << E->clangDecl()->getQualifiedNameAsString();
00704         return;
00705       }
00706     }
00707     self()->printSExpr(E->record(), SS, Prec_Postfix);
00708     if (CStyle && E->isArrow()) {
00709       SS << "->";
00710     }
00711     else {
00712       SS << ".";
00713     }
00714     SS << E->slotName();
00715   }
00716 
00717   void printCall(const Call *E, StreamType &SS) {
00718     const SExpr *T = E->target();
00719     if (T->opcode() == COP_Apply) {
00720       self()->printApply(cast<Apply>(T), SS, true);
00721       SS << ")";
00722     }
00723     else {
00724       self()->printSExpr(T, SS, Prec_Postfix);
00725       SS << "()";
00726     }
00727   }
00728 
00729   void printAlloc(const Alloc *E, StreamType &SS) {
00730     SS << "new ";
00731     self()->printSExpr(E->dataType(), SS, Prec_Other-1);
00732   }
00733 
00734   void printLoad(const Load *E, StreamType &SS) {
00735     self()->printSExpr(E->pointer(), SS, Prec_Postfix);
00736     if (!CStyle)
00737       SS << "^";
00738   }
00739 
00740   void printStore(const Store *E, StreamType &SS) {
00741     self()->printSExpr(E->destination(), SS, Prec_Other-1);
00742     SS << " := ";
00743     self()->printSExpr(E->source(), SS, Prec_Other-1);
00744   }
00745 
00746   void printArrayIndex(const ArrayIndex *E, StreamType &SS) {
00747     self()->printSExpr(E->array(), SS, Prec_Postfix);
00748     SS << "[";
00749     self()->printSExpr(E->index(), SS, Prec_MAX);
00750     SS << "]";
00751   }
00752 
00753   void printArrayAdd(const ArrayAdd *E, StreamType &SS) {
00754     self()->printSExpr(E->array(), SS, Prec_Postfix);
00755     SS << " + ";
00756     self()->printSExpr(E->index(), SS, Prec_Atom);
00757   }
00758 
00759   void printUnaryOp(const UnaryOp *E, StreamType &SS) {
00760     SS << getUnaryOpcodeString(E->unaryOpcode());
00761     self()->printSExpr(E->expr(), SS, Prec_Unary);
00762   }
00763 
00764   void printBinaryOp(const BinaryOp *E, StreamType &SS) {
00765     self()->printSExpr(E->expr0(), SS, Prec_Binary-1);
00766     SS << " " << getBinaryOpcodeString(E->binaryOpcode()) << " ";
00767     self()->printSExpr(E->expr1(), SS, Prec_Binary-1);
00768   }
00769 
00770   void printCast(const Cast *E, StreamType &SS) {
00771     if (!CStyle) {
00772       SS << "cast[";
00773       SS << E->castOpcode();
00774       SS << "](";
00775       self()->printSExpr(E->expr(), SS, Prec_Unary);
00776       SS << ")";
00777       return;
00778     }
00779     self()->printSExpr(E->expr(), SS, Prec_Unary);
00780   }
00781 
00782   void printSCFG(const SCFG *E, StreamType &SS) {
00783     SS << "CFG {\n";
00784     for (auto BBI : *E) {
00785       printBasicBlock(BBI, SS);
00786     }
00787     SS << "}";
00788     newline(SS);
00789   }
00790 
00791 
00792   void printBBInstr(const SExpr *E, StreamType &SS) {
00793     bool Sub = false;
00794     if (E->opcode() == COP_Variable) {
00795       auto *V = cast<Variable>(E);
00796       SS << "let " << V->name() << V->id() << " = ";
00797       E = V->definition();
00798       Sub = true;
00799     }
00800     else if (E->opcode() != COP_Store) {
00801       SS << "let _x" << E->id() << " = ";
00802     }
00803     self()->printSExpr(E, SS, Prec_MAX, Sub);
00804     SS << ";";
00805     newline(SS);
00806   }
00807 
00808   void printBasicBlock(const BasicBlock *E, StreamType &SS) {
00809     SS << "BB_" << E->blockID() << ":";
00810     if (E->parent())
00811       SS << " BB_" << E->parent()->blockID();
00812     newline(SS);
00813 
00814     for (auto *A : E->arguments())
00815       printBBInstr(A, SS);
00816 
00817     for (auto *I : E->instructions())
00818       printBBInstr(I, SS);
00819 
00820     const SExpr *T = E->terminator();
00821     if (T) {
00822       self()->printSExpr(T, SS, Prec_MAX, false);
00823       SS << ";";
00824       newline(SS);
00825     }
00826     newline(SS);
00827   }
00828 
00829   void printPhi(const Phi *E, StreamType &SS) {
00830     SS << "phi(";
00831     if (E->status() == Phi::PH_SingleVal)
00832       self()->printSExpr(E->values()[0], SS, Prec_MAX);
00833     else {
00834       unsigned i = 0;
00835       for (auto V : E->values()) {
00836         if (i++ > 0)
00837           SS << ", ";
00838         self()->printSExpr(V, SS, Prec_MAX);
00839       }
00840     }
00841     SS << ")";
00842   }
00843 
00844   void printGoto(const Goto *E, StreamType &SS) {
00845     SS << "goto ";
00846     printBlockLabel(SS, E->targetBlock(), E->index());
00847   }
00848 
00849   void printBranch(const Branch *E, StreamType &SS) {
00850     SS << "branch (";
00851     self()->printSExpr(E->condition(), SS, Prec_MAX);
00852     SS << ") ";
00853     printBlockLabel(SS, E->thenBlock(), -1);
00854     SS << " ";
00855     printBlockLabel(SS, E->elseBlock(), -1);
00856   }
00857 
00858   void printReturn(const Return *E, StreamType &SS) {
00859     SS << "return ";
00860     self()->printSExpr(E->returnValue(), SS, Prec_Other);
00861   }
00862 
00863   void printIdentifier(const Identifier *E, StreamType &SS) {
00864     SS << E->name();
00865   }
00866 
00867   void printIfThenElse(const IfThenElse *E, StreamType &SS) {
00868     if (CStyle) {
00869       printSExpr(E->condition(), SS, Prec_Unary);
00870       SS << " ? ";
00871       printSExpr(E->thenExpr(), SS, Prec_Unary);
00872       SS << " : ";
00873       printSExpr(E->elseExpr(), SS, Prec_Unary);
00874       return;
00875     }
00876     SS << "if (";
00877     printSExpr(E->condition(), SS, Prec_MAX);
00878     SS << ") then ";
00879     printSExpr(E->thenExpr(), SS, Prec_Other);
00880     SS << " else ";
00881     printSExpr(E->elseExpr(), SS, Prec_Other);
00882   }
00883 
00884   void printLet(const Let *E, StreamType &SS) {
00885     SS << "let ";
00886     printVariable(E->variableDecl(), SS, true);
00887     SS << " = ";
00888     printSExpr(E->variableDecl()->definition(), SS, Prec_Decl-1);
00889     SS << "; ";
00890     printSExpr(E->body(), SS, Prec_Decl-1);
00891   }
00892 };
00893 
00894 
00895 class StdPrinter : public PrettyPrinter<StdPrinter, std::ostream> { };
00896 
00897 
00898 
00899 } // end namespace til
00900 } // end namespace threadSafety
00901 } // end namespace clang
00902 
00903 #endif  // LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H