clang API Documentation

ThreadSafetyTIL.h
Go to the documentation of this file.
00001 //===- ThreadSafetyTIL.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 in the llvm repository for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file defines a simple Typed Intermediate Language, or TIL, that is used
00011 // by the thread safety analysis (See ThreadSafety.cpp).  The TIL is intended
00012 // to be largely independent of clang, in the hope that the analysis can be
00013 // reused for other non-C++ languages.  All dependencies on clang/llvm should
00014 // go in ThreadSafetyUtil.h.
00015 //
00016 // Thread safety analysis works by comparing mutex expressions, e.g.
00017 //
00018 // class A { Mutex mu; int dat GUARDED_BY(this->mu); }
00019 // class B { A a; }
00020 //
00021 // void foo(B* b) {
00022 //   (*b).a.mu.lock();     // locks (*b).a.mu
00023 //   b->a.dat = 0;         // substitute &b->a for 'this';
00024 //                         // requires lock on (&b->a)->mu
00025 //   (b->a.mu).unlock();   // unlocks (b->a.mu)
00026 // }
00027 //
00028 // As illustrated by the above example, clang Exprs are not well-suited to
00029 // represent mutex expressions directly, since there is no easy way to compare
00030 // Exprs for equivalence.  The thread safety analysis thus lowers clang Exprs
00031 // into a simple intermediate language (IL).  The IL supports:
00032 //
00033 // (1) comparisons for semantic equality of expressions
00034 // (2) SSA renaming of variables
00035 // (3) wildcards and pattern matching over expressions
00036 // (4) hash-based expression lookup
00037 //
00038 // The TIL is currently very experimental, is intended only for use within
00039 // the thread safety analysis, and is subject to change without notice.
00040 // After the API stabilizes and matures, it may be appropriate to make this
00041 // more generally available to other analyses.
00042 //
00043 // UNDER CONSTRUCTION.  USE AT YOUR OWN RISK.
00044 //
00045 //===----------------------------------------------------------------------===//
00046 
00047 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H
00048 #define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H
00049 
00050 // All clang include dependencies for this file must be put in
00051 // ThreadSafetyUtil.h.
00052 #include "ThreadSafetyUtil.h"
00053 
00054 #include <stdint.h>
00055 #include <algorithm>
00056 #include <cassert>
00057 #include <cstddef>
00058 #include <utility>
00059 
00060 
00061 namespace clang {
00062 namespace threadSafety {
00063 namespace til {
00064 
00065 
00066 /// Enum for the different distinct classes of SExpr
00067 enum TIL_Opcode {
00068 #define TIL_OPCODE_DEF(X) COP_##X,
00069 #include "ThreadSafetyOps.def"
00070 #undef TIL_OPCODE_DEF
00071 };
00072 
00073 /// Opcode for unary arithmetic operations.
00074 enum TIL_UnaryOpcode : unsigned char {
00075   UOP_Minus,        //  -
00076   UOP_BitNot,       //  ~
00077   UOP_LogicNot      //  !
00078 };
00079 
00080 /// Opcode for binary arithmetic operations.
00081 enum TIL_BinaryOpcode : unsigned char {
00082   BOP_Add,          //  +
00083   BOP_Sub,          //  -
00084   BOP_Mul,          //  *
00085   BOP_Div,          //  /
00086   BOP_Rem,          //  %
00087   BOP_Shl,          //  <<
00088   BOP_Shr,          //  >>
00089   BOP_BitAnd,       //  &
00090   BOP_BitXor,       //  ^
00091   BOP_BitOr,        //  |
00092   BOP_Eq,           //  ==
00093   BOP_Neq,          //  !=
00094   BOP_Lt,           //  <
00095   BOP_Leq,          //  <=
00096   BOP_LogicAnd,     //  &&  (no short-circuit)
00097   BOP_LogicOr       //  ||  (no short-circuit)
00098 };
00099 
00100 /// Opcode for cast operations.
00101 enum TIL_CastOpcode : unsigned char {
00102   CAST_none = 0,
00103   CAST_extendNum,   // extend precision of numeric type
00104   CAST_truncNum,    // truncate precision of numeric type
00105   CAST_toFloat,     // convert to floating point type
00106   CAST_toInt,       // convert to integer type
00107   CAST_objToPtr     // convert smart pointer to pointer  (C++ only)
00108 };
00109 
00110 const TIL_Opcode       COP_Min  = COP_Future;
00111 const TIL_Opcode       COP_Max  = COP_Branch;
00112 const TIL_UnaryOpcode  UOP_Min  = UOP_Minus;
00113 const TIL_UnaryOpcode  UOP_Max  = UOP_LogicNot;
00114 const TIL_BinaryOpcode BOP_Min  = BOP_Add;
00115 const TIL_BinaryOpcode BOP_Max  = BOP_LogicOr;
00116 const TIL_CastOpcode   CAST_Min = CAST_none;
00117 const TIL_CastOpcode   CAST_Max = CAST_toInt;
00118 
00119 /// Return the name of a unary opcode.
00120 StringRef getUnaryOpcodeString(TIL_UnaryOpcode Op);
00121 
00122 /// Return the name of a binary opcode.
00123 StringRef getBinaryOpcodeString(TIL_BinaryOpcode Op);
00124 
00125 
00126 /// ValueTypes are data types that can actually be held in registers.
00127 /// All variables and expressions must have a value type.
00128 /// Pointer types are further subdivided into the various heap-allocated
00129 /// types, such as functions, records, etc.
00130 /// Structured types that are passed by value (e.g. complex numbers)
00131 /// require special handling; they use BT_ValueRef, and size ST_0.
00132 struct ValueType {
00133   enum BaseType : unsigned char {
00134     BT_Void = 0,
00135     BT_Bool,
00136     BT_Int,
00137     BT_Float,
00138     BT_String,    // String literals
00139     BT_Pointer,
00140     BT_ValueRef
00141   };
00142 
00143   enum SizeType : unsigned char {
00144     ST_0 = 0,
00145     ST_1,
00146     ST_8,
00147     ST_16,
00148     ST_32,
00149     ST_64,
00150     ST_128
00151   };
00152 
00153   inline static SizeType getSizeType(unsigned nbytes);
00154 
00155   template <class T>
00156   inline static ValueType getValueType();
00157 
00158   ValueType(BaseType B, SizeType Sz, bool S, unsigned char VS)
00159       : Base(B), Size(Sz), Signed(S), VectSize(VS)
00160   { }
00161 
00162   BaseType      Base;
00163   SizeType      Size;
00164   bool          Signed;
00165   unsigned char VectSize;  // 0 for scalar, otherwise num elements in vector
00166 };
00167 
00168 
00169 inline ValueType::SizeType ValueType::getSizeType(unsigned nbytes) {
00170   switch (nbytes) {
00171     case 1: return ST_8;
00172     case 2: return ST_16;
00173     case 4: return ST_32;
00174     case 8: return ST_64;
00175     case 16: return ST_128;
00176     default: return ST_0;
00177   }
00178 }
00179 
00180 
00181 template<>
00182 inline ValueType ValueType::getValueType<void>() {
00183   return ValueType(BT_Void, ST_0, false, 0);
00184 }
00185 
00186 template<>
00187 inline ValueType ValueType::getValueType<bool>() {
00188   return ValueType(BT_Bool, ST_1, false, 0);
00189 }
00190 
00191 template<>
00192 inline ValueType ValueType::getValueType<int8_t>() {
00193   return ValueType(BT_Int, ST_8, true, 0);
00194 }
00195 
00196 template<>
00197 inline ValueType ValueType::getValueType<uint8_t>() {
00198   return ValueType(BT_Int, ST_8, false, 0);
00199 }
00200 
00201 template<>
00202 inline ValueType ValueType::getValueType<int16_t>() {
00203   return ValueType(BT_Int, ST_16, true, 0);
00204 }
00205 
00206 template<>
00207 inline ValueType ValueType::getValueType<uint16_t>() {
00208   return ValueType(BT_Int, ST_16, false, 0);
00209 }
00210 
00211 template<>
00212 inline ValueType ValueType::getValueType<int32_t>() {
00213   return ValueType(BT_Int, ST_32, true, 0);
00214 }
00215 
00216 template<>
00217 inline ValueType ValueType::getValueType<uint32_t>() {
00218   return ValueType(BT_Int, ST_32, false, 0);
00219 }
00220 
00221 template<>
00222 inline ValueType ValueType::getValueType<int64_t>() {
00223   return ValueType(BT_Int, ST_64, true, 0);
00224 }
00225 
00226 template<>
00227 inline ValueType ValueType::getValueType<uint64_t>() {
00228   return ValueType(BT_Int, ST_64, false, 0);
00229 }
00230 
00231 template<>
00232 inline ValueType ValueType::getValueType<float>() {
00233   return ValueType(BT_Float, ST_32, true, 0);
00234 }
00235 
00236 template<>
00237 inline ValueType ValueType::getValueType<double>() {
00238   return ValueType(BT_Float, ST_64, true, 0);
00239 }
00240 
00241 template<>
00242 inline ValueType ValueType::getValueType<long double>() {
00243   return ValueType(BT_Float, ST_128, true, 0);
00244 }
00245 
00246 template<>
00247 inline ValueType ValueType::getValueType<StringRef>() {
00248   return ValueType(BT_String, getSizeType(sizeof(StringRef)), false, 0);
00249 }
00250 
00251 template<>
00252 inline ValueType ValueType::getValueType<void*>() {
00253   return ValueType(BT_Pointer, getSizeType(sizeof(void*)), false, 0);
00254 }
00255 
00256 
00257 class BasicBlock;
00258 
00259 
00260 /// Base class for AST nodes in the typed intermediate language.
00261 class SExpr {
00262 public:
00263   TIL_Opcode opcode() const { return static_cast<TIL_Opcode>(Opcode); }
00264 
00265   // Subclasses of SExpr must define the following:
00266   //
00267   // This(const This& E, ...) {
00268   //   copy constructor: construct copy of E, with some additional arguments.
00269   // }
00270   //
00271   // template <class V>
00272   // typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
00273   //   traverse all subexpressions, following the traversal/rewriter interface.
00274   // }
00275   //
00276   // template <class C> typename C::CType compare(CType* E, C& Cmp) {
00277   //   compare all subexpressions, following the comparator interface
00278   // }
00279   void *operator new(size_t S, MemRegionRef &R) {
00280     return ::operator new(S, R);
00281   }
00282 
00283   /// SExpr objects cannot be deleted.
00284   // This declaration is public to workaround a gcc bug that breaks building
00285   // with REQUIRES_EH=1.
00286   void operator delete(void *) LLVM_DELETED_FUNCTION;
00287 
00288   /// Returns the instruction ID for this expression.
00289   /// All basic block instructions have a unique ID (i.e. virtual register).
00290   unsigned id() const { return SExprID; }
00291 
00292   /// Returns the block, if this is an instruction in a basic block,
00293   /// otherwise returns null.
00294   BasicBlock* block() const { return Block; }
00295 
00296   /// Set the basic block and instruction ID for this expression.
00297   void setID(BasicBlock *B, unsigned id) { Block = B; SExprID = id; }
00298 
00299 protected:
00300   SExpr(TIL_Opcode Op)
00301     : Opcode(Op), Reserved(0), Flags(0), SExprID(0), Block(nullptr) {}
00302   SExpr(const SExpr &E)
00303     : Opcode(E.Opcode), Reserved(0), Flags(E.Flags), SExprID(0),
00304       Block(nullptr) {}
00305 
00306   const unsigned char Opcode;
00307   unsigned char Reserved;
00308   unsigned short Flags;
00309   unsigned SExprID;
00310   BasicBlock* Block;
00311 
00312 private:
00313   SExpr() LLVM_DELETED_FUNCTION;
00314 
00315   /// SExpr objects must be created in an arena.
00316   void *operator new(size_t) LLVM_DELETED_FUNCTION;
00317 };
00318 
00319 
00320 // Contains various helper functions for SExprs.
00321 namespace ThreadSafetyTIL {
00322   inline bool isTrivial(const SExpr *E) {
00323     unsigned Op = E->opcode();
00324     return Op == COP_Variable || Op == COP_Literal || Op == COP_LiteralPtr;
00325   }
00326 }
00327 
00328 // Nodes which declare variables
00329 class Function;
00330 class SFunction;
00331 class Let;
00332 
00333 
00334 /// A named variable, e.g. "x".
00335 ///
00336 /// There are two distinct places in which a Variable can appear in the AST.
00337 /// A variable declaration introduces a new variable, and can occur in 3 places:
00338 ///   Let-expressions:           (Let (x = t) u)
00339 ///   Functions:                 (Function (x : t) u)
00340 ///   Self-applicable functions  (SFunction (x) t)
00341 ///
00342 /// If a variable occurs in any other location, it is a reference to an existing
00343 /// variable declaration -- e.g. 'x' in (x * y + z). To save space, we don't
00344 /// allocate a separate AST node for variable references; a reference is just a
00345 /// pointer to the original declaration.
00346 class Variable : public SExpr {
00347 public:
00348   static bool classof(const SExpr *E) { return E->opcode() == COP_Variable; }
00349 
00350   enum VariableKind {
00351     VK_Let,  ///< Let-variable
00352     VK_Fun,  ///< Function parameter
00353     VK_SFun  ///< SFunction (self) parameter
00354   };
00355 
00356   Variable(StringRef s, SExpr *D = nullptr)
00357       : SExpr(COP_Variable), Name(s), Definition(D), Cvdecl(nullptr) {
00358     Flags = VK_Let;
00359   }
00360   Variable(SExpr *D, const clang::ValueDecl *Cvd = nullptr)
00361       : SExpr(COP_Variable), Name(Cvd ? Cvd->getName() : "_x"),
00362         Definition(D), Cvdecl(Cvd) {
00363     Flags = VK_Let;
00364   }
00365   Variable(const Variable &Vd, SExpr *D)  // rewrite constructor
00366       : SExpr(Vd), Name(Vd.Name), Definition(D), Cvdecl(Vd.Cvdecl) {
00367     Flags = Vd.kind();
00368   }
00369 
00370   /// Return the kind of variable (let, function param, or self)
00371   VariableKind kind() const { return static_cast<VariableKind>(Flags); }
00372 
00373   /// Return the name of the variable, if any.
00374   StringRef name() const { return Name; }
00375 
00376   /// Return the clang declaration for this variable, if any.
00377   const clang::ValueDecl *clangDecl() const { return Cvdecl; }
00378 
00379   /// Return the definition of the variable.
00380   /// For let-vars, this is the setting expression.
00381   /// For function and self parameters, it is the type of the variable.
00382   SExpr *definition() { return Definition; }
00383   const SExpr *definition() const { return Definition; }
00384 
00385   void setName(StringRef S)    { Name = S;  }
00386   void setKind(VariableKind K) { Flags = K; }
00387   void setDefinition(SExpr *E) { Definition = E; }
00388   void setClangDecl(const clang::ValueDecl *VD) { Cvdecl = VD; }
00389 
00390   template <class V>
00391   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
00392     // This routine is only called for variable references.
00393     return Vs.reduceVariableRef(this);
00394   }
00395 
00396   template <class C>
00397   typename C::CType compare(const Variable* E, C& Cmp) const {
00398     return Cmp.compareVariableRefs(this, E);
00399   }
00400 
00401 private:
00402   friend class Function;
00403   friend class SFunction;
00404   friend class BasicBlock;
00405   friend class Let;
00406 
00407   StringRef Name;                  // The name of the variable.
00408   SExpr*    Definition;            // The TIL type or definition
00409   const clang::ValueDecl *Cvdecl;  // The clang declaration for this variable.
00410 };
00411 
00412 
00413 /// Placeholder for an expression that has not yet been created.
00414 /// Used to implement lazy copy and rewriting strategies.
00415 class Future : public SExpr {
00416 public:
00417   static bool classof(const SExpr *E) { return E->opcode() == COP_Future; }
00418 
00419   enum FutureStatus {
00420     FS_pending,
00421     FS_evaluating,
00422     FS_done
00423   };
00424 
00425   Future() : SExpr(COP_Future), Status(FS_pending), Result(nullptr) {}
00426 
00427 private:
00428   virtual ~Future() LLVM_DELETED_FUNCTION;
00429 
00430 public:
00431   // A lazy rewriting strategy should subclass Future and override this method.
00432   virtual SExpr *compute() { return nullptr; }
00433 
00434   // Return the result of this future if it exists, otherwise return null.
00435   SExpr *maybeGetResult() const {
00436     return Result;
00437   }
00438 
00439   // Return the result of this future; forcing it if necessary.
00440   SExpr *result() {
00441     switch (Status) {
00442     case FS_pending:
00443       return force();
00444     case FS_evaluating:
00445       return nullptr; // infinite loop; illegal recursion.
00446     case FS_done:
00447       return Result;
00448     }
00449   }
00450 
00451   template <class V>
00452   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
00453     assert(Result && "Cannot traverse Future that has not been forced.");
00454     return Vs.traverse(Result, Ctx);
00455   }
00456 
00457   template <class C>
00458   typename C::CType compare(const Future* E, C& Cmp) const {
00459     if (!Result || !E->Result)
00460       return Cmp.comparePointers(this, E);
00461     return Cmp.compare(Result, E->Result);
00462   }
00463 
00464 private:
00465   SExpr* force();
00466 
00467   FutureStatus Status;
00468   SExpr *Result;
00469 };
00470 
00471 
00472 /// Placeholder for expressions that cannot be represented in the TIL.
00473 class Undefined : public SExpr {
00474 public:
00475   static bool classof(const SExpr *E) { return E->opcode() == COP_Undefined; }
00476 
00477   Undefined(const clang::Stmt *S = nullptr) : SExpr(COP_Undefined), Cstmt(S) {}
00478   Undefined(const Undefined &U) : SExpr(U), Cstmt(U.Cstmt) {}
00479 
00480   template <class V>
00481   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
00482     return Vs.reduceUndefined(*this);
00483   }
00484 
00485   template <class C>
00486   typename C::CType compare(const Undefined* E, C& Cmp) const {
00487     return Cmp.trueResult();
00488   }
00489 
00490 private:
00491   const clang::Stmt *Cstmt;
00492 };
00493 
00494 
00495 /// Placeholder for a wildcard that matches any other expression.
00496 class Wildcard : public SExpr {
00497 public:
00498   static bool classof(const SExpr *E) { return E->opcode() == COP_Wildcard; }
00499 
00500   Wildcard() : SExpr(COP_Wildcard) {}
00501   Wildcard(const Wildcard &W) : SExpr(W) {}
00502 
00503   template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
00504     return Vs.reduceWildcard(*this);
00505   }
00506 
00507   template <class C>
00508   typename C::CType compare(const Wildcard* E, C& Cmp) const {
00509     return Cmp.trueResult();
00510   }
00511 };
00512 
00513 
00514 template <class T> class LiteralT;
00515 
00516 // Base class for literal values.
00517 class Literal : public SExpr {
00518 public:
00519   static bool classof(const SExpr *E) { return E->opcode() == COP_Literal; }
00520 
00521   Literal(const clang::Expr *C)
00522      : SExpr(COP_Literal), ValType(ValueType::getValueType<void>()), Cexpr(C)
00523   { }
00524   Literal(ValueType VT) : SExpr(COP_Literal), ValType(VT), Cexpr(nullptr) {}
00525   Literal(const Literal &L) : SExpr(L), ValType(L.ValType), Cexpr(L.Cexpr) {}
00526 
00527   // The clang expression for this literal.
00528   const clang::Expr *clangExpr() const { return Cexpr; }
00529 
00530   ValueType valueType() const { return ValType; }
00531 
00532   template<class T> const LiteralT<T>& as() const {
00533     return *static_cast<const LiteralT<T>*>(this);
00534   }
00535   template<class T> LiteralT<T>& as() {
00536     return *static_cast<LiteralT<T>*>(this);
00537   }
00538 
00539   template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx);
00540 
00541   template <class C>
00542   typename C::CType compare(const Literal* E, C& Cmp) const {
00543     // TODO: defer actual comparison to LiteralT
00544     return Cmp.trueResult();
00545   }
00546 
00547 private:
00548   const ValueType ValType;
00549   const clang::Expr *Cexpr;
00550 };
00551 
00552 
00553 // Derived class for literal values, which stores the actual value.
00554 template<class T>
00555 class LiteralT : public Literal {
00556 public:
00557   LiteralT(T Dat) : Literal(ValueType::getValueType<T>()), Val(Dat) { }
00558   LiteralT(const LiteralT<T> &L) : Literal(L), Val(L.Val) { }
00559 
00560   T  value() const { return Val;}
00561   T& value() { return Val; }
00562 
00563 private:
00564   T Val;
00565 };
00566 
00567 
00568 
00569 template <class V>
00570 typename V::R_SExpr Literal::traverse(V &Vs, typename V::R_Ctx Ctx) {
00571   if (Cexpr)
00572     return Vs.reduceLiteral(*this);
00573 
00574   switch (ValType.Base) {
00575   case ValueType::BT_Void:
00576     break;
00577   case ValueType::BT_Bool:
00578     return Vs.reduceLiteralT(as<bool>());
00579   case ValueType::BT_Int: {
00580     switch (ValType.Size) {
00581     case ValueType::ST_8:
00582       if (ValType.Signed)
00583         return Vs.reduceLiteralT(as<int8_t>());
00584       else
00585         return Vs.reduceLiteralT(as<uint8_t>());
00586     case ValueType::ST_16:
00587       if (ValType.Signed)
00588         return Vs.reduceLiteralT(as<int16_t>());
00589       else
00590         return Vs.reduceLiteralT(as<uint16_t>());
00591     case ValueType::ST_32:
00592       if (ValType.Signed)
00593         return Vs.reduceLiteralT(as<int32_t>());
00594       else
00595         return Vs.reduceLiteralT(as<uint32_t>());
00596     case ValueType::ST_64:
00597       if (ValType.Signed)
00598         return Vs.reduceLiteralT(as<int64_t>());
00599       else
00600         return Vs.reduceLiteralT(as<uint64_t>());
00601     default:
00602       break;
00603     }
00604   }
00605   case ValueType::BT_Float: {
00606     switch (ValType.Size) {
00607     case ValueType::ST_32:
00608       return Vs.reduceLiteralT(as<float>());
00609     case ValueType::ST_64:
00610       return Vs.reduceLiteralT(as<double>());
00611     default:
00612       break;
00613     }
00614   }
00615   case ValueType::BT_String:
00616     return Vs.reduceLiteralT(as<StringRef>());
00617   case ValueType::BT_Pointer:
00618     return Vs.reduceLiteralT(as<void*>());
00619   case ValueType::BT_ValueRef:
00620     break;
00621   }
00622   return Vs.reduceLiteral(*this);
00623 }
00624 
00625 
00626 /// A Literal pointer to an object allocated in memory.
00627 /// At compile time, pointer literals are represented by symbolic names.
00628 class LiteralPtr : public SExpr {
00629 public:
00630   static bool classof(const SExpr *E) { return E->opcode() == COP_LiteralPtr; }
00631 
00632   LiteralPtr(const clang::ValueDecl *D) : SExpr(COP_LiteralPtr), Cvdecl(D) {}
00633   LiteralPtr(const LiteralPtr &R) : SExpr(R), Cvdecl(R.Cvdecl) {}
00634 
00635   // The clang declaration for the value that this pointer points to.
00636   const clang::ValueDecl *clangDecl() const { return Cvdecl; }
00637 
00638   template <class V>
00639   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
00640     return Vs.reduceLiteralPtr(*this);
00641   }
00642 
00643   template <class C>
00644   typename C::CType compare(const LiteralPtr* E, C& Cmp) const {
00645     return Cmp.comparePointers(Cvdecl, E->Cvdecl);
00646   }
00647 
00648 private:
00649   const clang::ValueDecl *Cvdecl;
00650 };
00651 
00652 
00653 /// A function -- a.k.a. lambda abstraction.
00654 /// Functions with multiple arguments are created by currying,
00655 /// e.g. (Function (x: Int) (Function (y: Int) (Code { return x + y })))
00656 class Function : public SExpr {
00657 public:
00658   static bool classof(const SExpr *E) { return E->opcode() == COP_Function; }
00659 
00660   Function(Variable *Vd, SExpr *Bd)
00661       : SExpr(COP_Function), VarDecl(Vd), Body(Bd) {
00662     Vd->setKind(Variable::VK_Fun);
00663   }
00664   Function(const Function &F, Variable *Vd, SExpr *Bd) // rewrite constructor
00665       : SExpr(F), VarDecl(Vd), Body(Bd) {
00666     Vd->setKind(Variable::VK_Fun);
00667   }
00668 
00669   Variable *variableDecl()  { return VarDecl; }
00670   const Variable *variableDecl() const { return VarDecl; }
00671 
00672   SExpr *body() { return Body; }
00673   const SExpr *body() const { return Body; }
00674 
00675   template <class V>
00676   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
00677     // This is a variable declaration, so traverse the definition.
00678     auto E0 = Vs.traverse(VarDecl->Definition, Vs.typeCtx(Ctx));
00679     // Tell the rewriter to enter the scope of the function.
00680     Variable *Nvd = Vs.enterScope(*VarDecl, E0);
00681     auto E1 = Vs.traverse(Body, Vs.declCtx(Ctx));
00682     Vs.exitScope(*VarDecl);
00683     return Vs.reduceFunction(*this, Nvd, E1);
00684   }
00685 
00686   template <class C>
00687   typename C::CType compare(const Function* E, C& Cmp) const {
00688     typename C::CType Ct =
00689       Cmp.compare(VarDecl->definition(), E->VarDecl->definition());
00690     if (Cmp.notTrue(Ct))
00691       return Ct;
00692     Cmp.enterScope(variableDecl(), E->variableDecl());
00693     Ct = Cmp.compare(body(), E->body());
00694     Cmp.leaveScope();
00695     return Ct;
00696   }
00697 
00698 private:
00699   Variable *VarDecl;
00700   SExpr* Body;
00701 };
00702 
00703 
00704 /// A self-applicable function.
00705 /// A self-applicable function can be applied to itself.  It's useful for
00706 /// implementing objects and late binding.
00707 class SFunction : public SExpr {
00708 public:
00709   static bool classof(const SExpr *E) { return E->opcode() == COP_SFunction; }
00710 
00711   SFunction(Variable *Vd, SExpr *B)
00712       : SExpr(COP_SFunction), VarDecl(Vd), Body(B) {
00713     assert(Vd->Definition == nullptr);
00714     Vd->setKind(Variable::VK_SFun);
00715     Vd->Definition = this;
00716   }
00717   SFunction(const SFunction &F, Variable *Vd, SExpr *B) // rewrite constructor
00718       : SExpr(F), VarDecl(Vd), Body(B) {
00719     assert(Vd->Definition == nullptr);
00720     Vd->setKind(Variable::VK_SFun);
00721     Vd->Definition = this;
00722   }
00723 
00724   Variable *variableDecl() { return VarDecl; }
00725   const Variable *variableDecl() const { return VarDecl; }
00726 
00727   SExpr *body() { return Body; }
00728   const SExpr *body() const { return Body; }
00729 
00730   template <class V>
00731   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
00732     // A self-variable points to the SFunction itself.
00733     // A rewrite must introduce the variable with a null definition, and update
00734     // it after 'this' has been rewritten.
00735     Variable *Nvd = Vs.enterScope(*VarDecl, nullptr);
00736     auto E1 = Vs.traverse(Body, Vs.declCtx(Ctx));
00737     Vs.exitScope(*VarDecl);
00738     // A rewrite operation will call SFun constructor to set Vvd->Definition.
00739     return Vs.reduceSFunction(*this, Nvd, E1);
00740   }
00741 
00742   template <class C>
00743   typename C::CType compare(const SFunction* E, C& Cmp) const {
00744     Cmp.enterScope(variableDecl(), E->variableDecl());
00745     typename C::CType Ct = Cmp.compare(body(), E->body());
00746     Cmp.leaveScope();
00747     return Ct;
00748   }
00749 
00750 private:
00751   Variable *VarDecl;
00752   SExpr* Body;
00753 };
00754 
00755 
00756 /// A block of code -- e.g. the body of a function.
00757 class Code : public SExpr {
00758 public:
00759   static bool classof(const SExpr *E) { return E->opcode() == COP_Code; }
00760 
00761   Code(SExpr *T, SExpr *B) : SExpr(COP_Code), ReturnType(T), Body(B) {}
00762   Code(const Code &C, SExpr *T, SExpr *B) // rewrite constructor
00763       : SExpr(C), ReturnType(T), Body(B) {}
00764 
00765   SExpr *returnType() { return ReturnType; }
00766   const SExpr *returnType() const { return ReturnType; }
00767 
00768   SExpr *body() { return Body; }
00769   const SExpr *body() const { return Body; }
00770 
00771   template <class V>
00772   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
00773     auto Nt = Vs.traverse(ReturnType, Vs.typeCtx(Ctx));
00774     auto Nb = Vs.traverse(Body,       Vs.lazyCtx(Ctx));
00775     return Vs.reduceCode(*this, Nt, Nb);
00776   }
00777 
00778   template <class C>
00779   typename C::CType compare(const Code* E, C& Cmp) const {
00780     typename C::CType Ct = Cmp.compare(returnType(), E->returnType());
00781     if (Cmp.notTrue(Ct))
00782       return Ct;
00783     return Cmp.compare(body(), E->body());
00784   }
00785 
00786 private:
00787   SExpr* ReturnType;
00788   SExpr* Body;
00789 };
00790 
00791 
00792 /// A typed, writable location in memory
00793 class Field : public SExpr {
00794 public:
00795   static bool classof(const SExpr *E) { return E->opcode() == COP_Field; }
00796 
00797   Field(SExpr *R, SExpr *B) : SExpr(COP_Field), Range(R), Body(B) {}
00798   Field(const Field &C, SExpr *R, SExpr *B) // rewrite constructor
00799       : SExpr(C), Range(R), Body(B) {}
00800 
00801   SExpr *range() { return Range; }
00802   const SExpr *range() const { return Range; }
00803 
00804   SExpr *body() { return Body; }
00805   const SExpr *body() const { return Body; }
00806 
00807   template <class V>
00808   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
00809     auto Nr = Vs.traverse(Range, Vs.typeCtx(Ctx));
00810     auto Nb = Vs.traverse(Body,  Vs.lazyCtx(Ctx));
00811     return Vs.reduceField(*this, Nr, Nb);
00812   }
00813 
00814   template <class C>
00815   typename C::CType compare(const Field* E, C& Cmp) const {
00816     typename C::CType Ct = Cmp.compare(range(), E->range());
00817     if (Cmp.notTrue(Ct))
00818       return Ct;
00819     return Cmp.compare(body(), E->body());
00820   }
00821 
00822 private:
00823   SExpr* Range;
00824   SExpr* Body;
00825 };
00826 
00827 
00828 /// Apply an argument to a function.
00829 /// Note that this does not actually call the function.  Functions are curried,
00830 /// so this returns a closure in which the first parameter has been applied.
00831 /// Once all parameters have been applied, Call can be used to invoke the
00832 /// function.
00833 class Apply : public SExpr {
00834 public:
00835   static bool classof(const SExpr *E) { return E->opcode() == COP_Apply; }
00836 
00837   Apply(SExpr *F, SExpr *A) : SExpr(COP_Apply), Fun(F), Arg(A) {}
00838   Apply(const Apply &A, SExpr *F, SExpr *Ar)  // rewrite constructor
00839       : SExpr(A), Fun(F), Arg(Ar)
00840   {}
00841 
00842   SExpr *fun() { return Fun; }
00843   const SExpr *fun() const { return Fun; }
00844 
00845   SExpr *arg() { return Arg; }
00846   const SExpr *arg() const { return Arg; }
00847 
00848   template <class V>
00849   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
00850     auto Nf = Vs.traverse(Fun, Vs.subExprCtx(Ctx));
00851     auto Na = Vs.traverse(Arg, Vs.subExprCtx(Ctx));
00852     return Vs.reduceApply(*this, Nf, Na);
00853   }
00854 
00855   template <class C>
00856   typename C::CType compare(const Apply* E, C& Cmp) const {
00857     typename C::CType Ct = Cmp.compare(fun(), E->fun());
00858     if (Cmp.notTrue(Ct))
00859       return Ct;
00860     return Cmp.compare(arg(), E->arg());
00861   }
00862 
00863 private:
00864   SExpr* Fun;
00865   SExpr* Arg;
00866 };
00867 
00868 
00869 /// Apply a self-argument to a self-applicable function.
00870 class SApply : public SExpr {
00871 public:
00872   static bool classof(const SExpr *E) { return E->opcode() == COP_SApply; }
00873 
00874   SApply(SExpr *Sf, SExpr *A = nullptr) : SExpr(COP_SApply), Sfun(Sf), Arg(A) {}
00875   SApply(SApply &A, SExpr *Sf, SExpr *Ar = nullptr) // rewrite constructor
00876       : SExpr(A), Sfun(Sf), Arg(Ar) {}
00877 
00878   SExpr *sfun() { return Sfun; }
00879   const SExpr *sfun() const { return Sfun; }
00880 
00881   SExpr *arg() { return Arg ? Arg : Sfun; }
00882   const SExpr *arg() const { return Arg ? Arg : Sfun; }
00883 
00884   bool isDelegation() const { return Arg != nullptr; }
00885 
00886   template <class V>
00887   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
00888     auto Nf = Vs.traverse(Sfun, Vs.subExprCtx(Ctx));
00889     typename V::R_SExpr Na = Arg ? Vs.traverse(Arg, Vs.subExprCtx(Ctx))
00890                                        : nullptr;
00891     return Vs.reduceSApply(*this, Nf, Na);
00892   }
00893 
00894   template <class C>
00895   typename C::CType compare(const SApply* E, C& Cmp) const {
00896     typename C::CType Ct = Cmp.compare(sfun(), E->sfun());
00897     if (Cmp.notTrue(Ct) || (!arg() && !E->arg()))
00898       return Ct;
00899     return Cmp.compare(arg(), E->arg());
00900   }
00901 
00902 private:
00903   SExpr* Sfun;
00904   SExpr* Arg;
00905 };
00906 
00907 
00908 /// Project a named slot from a C++ struct or class.
00909 class Project : public SExpr {
00910 public:
00911   static bool classof(const SExpr *E) { return E->opcode() == COP_Project; }
00912 
00913   Project(SExpr *R, StringRef SName)
00914       : SExpr(COP_Project), Rec(R), SlotName(SName), Cvdecl(nullptr)
00915   { }
00916   Project(SExpr *R, const clang::ValueDecl *Cvd)
00917       : SExpr(COP_Project), Rec(R), SlotName(Cvd->getName()), Cvdecl(Cvd)
00918   { }
00919   Project(const Project &P, SExpr *R)
00920       : SExpr(P), Rec(R), SlotName(P.SlotName), Cvdecl(P.Cvdecl)
00921   { }
00922 
00923   SExpr *record() { return Rec; }
00924   const SExpr *record() const { return Rec; }
00925 
00926   const clang::ValueDecl *clangDecl() const { return Cvdecl; }
00927 
00928   bool isArrow() const { return (Flags & 0x01) != 0; }
00929   void setArrow(bool b) {
00930     if (b) Flags |= 0x01;
00931     else Flags &= 0xFFFE;
00932   }
00933 
00934   StringRef slotName() const {
00935     if (Cvdecl)
00936       return Cvdecl->getName();
00937     else
00938       return SlotName;
00939   }
00940 
00941   template <class V>
00942   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
00943     auto Nr = Vs.traverse(Rec, Vs.subExprCtx(Ctx));
00944     return Vs.reduceProject(*this, Nr);
00945   }
00946 
00947   template <class C>
00948   typename C::CType compare(const Project* E, C& Cmp) const {
00949     typename C::CType Ct = Cmp.compare(record(), E->record());
00950     if (Cmp.notTrue(Ct))
00951       return Ct;
00952     return Cmp.comparePointers(Cvdecl, E->Cvdecl);
00953   }
00954 
00955 private:
00956   SExpr* Rec;
00957   StringRef SlotName;
00958   const clang::ValueDecl *Cvdecl;
00959 };
00960 
00961 
00962 /// Call a function (after all arguments have been applied).
00963 class Call : public SExpr {
00964 public:
00965   static bool classof(const SExpr *E) { return E->opcode() == COP_Call; }
00966 
00967   Call(SExpr *T, const clang::CallExpr *Ce = nullptr)
00968       : SExpr(COP_Call), Target(T), Cexpr(Ce) {}
00969   Call(const Call &C, SExpr *T) : SExpr(C), Target(T), Cexpr(C.Cexpr) {}
00970 
00971   SExpr *target() { return Target; }
00972   const SExpr *target() const { return Target; }
00973 
00974   const clang::CallExpr *clangCallExpr() const { return Cexpr; }
00975 
00976   template <class V>
00977   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
00978     auto Nt = Vs.traverse(Target, Vs.subExprCtx(Ctx));
00979     return Vs.reduceCall(*this, Nt);
00980   }
00981 
00982   template <class C>
00983   typename C::CType compare(const Call* E, C& Cmp) const {
00984     return Cmp.compare(target(), E->target());
00985   }
00986 
00987 private:
00988   SExpr* Target;
00989   const clang::CallExpr *Cexpr;
00990 };
00991 
00992 
00993 /// Allocate memory for a new value on the heap or stack.
00994 class Alloc : public SExpr {
00995 public:
00996   static bool classof(const SExpr *E) { return E->opcode() == COP_Call; }
00997 
00998   enum AllocKind {
00999     AK_Stack,
01000     AK_Heap
01001   };
01002 
01003   Alloc(SExpr *D, AllocKind K) : SExpr(COP_Alloc), Dtype(D) { Flags = K; }
01004   Alloc(const Alloc &A, SExpr *Dt) : SExpr(A), Dtype(Dt) { Flags = A.kind(); }
01005 
01006   AllocKind kind() const { return static_cast<AllocKind>(Flags); }
01007 
01008   SExpr *dataType() { return Dtype; }
01009   const SExpr *dataType() const { return Dtype; }
01010 
01011   template <class V>
01012   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
01013     auto Nd = Vs.traverse(Dtype, Vs.declCtx(Ctx));
01014     return Vs.reduceAlloc(*this, Nd);
01015   }
01016 
01017   template <class C>
01018   typename C::CType compare(const Alloc* E, C& Cmp) const {
01019     typename C::CType Ct = Cmp.compareIntegers(kind(), E->kind());
01020     if (Cmp.notTrue(Ct))
01021       return Ct;
01022     return Cmp.compare(dataType(), E->dataType());
01023   }
01024 
01025 private:
01026   SExpr* Dtype;
01027 };
01028 
01029 
01030 /// Load a value from memory.
01031 class Load : public SExpr {
01032 public:
01033   static bool classof(const SExpr *E) { return E->opcode() == COP_Load; }
01034 
01035   Load(SExpr *P) : SExpr(COP_Load), Ptr(P) {}
01036   Load(const Load &L, SExpr *P) : SExpr(L), Ptr(P) {}
01037 
01038   SExpr *pointer() { return Ptr; }
01039   const SExpr *pointer() const { return Ptr; }
01040 
01041   template <class V>
01042   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
01043     auto Np = Vs.traverse(Ptr, Vs.subExprCtx(Ctx));
01044     return Vs.reduceLoad(*this, Np);
01045   }
01046 
01047   template <class C>
01048   typename C::CType compare(const Load* E, C& Cmp) const {
01049     return Cmp.compare(pointer(), E->pointer());
01050   }
01051 
01052 private:
01053   SExpr* Ptr;
01054 };
01055 
01056 
01057 /// Store a value to memory.
01058 /// The destination is a pointer to a field, the source is the value to store.
01059 class Store : public SExpr {
01060 public:
01061   static bool classof(const SExpr *E) { return E->opcode() == COP_Store; }
01062 
01063   Store(SExpr *P, SExpr *V) : SExpr(COP_Store), Dest(P), Source(V) {}
01064   Store(const Store &S, SExpr *P, SExpr *V) : SExpr(S), Dest(P), Source(V) {}
01065 
01066   SExpr *destination() { return Dest; }  // Address to store to
01067   const SExpr *destination() const { return Dest; }
01068 
01069   SExpr *source() { return Source; }     // Value to store
01070   const SExpr *source() const { return Source; }
01071 
01072   template <class V>
01073   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
01074     auto Np = Vs.traverse(Dest,   Vs.subExprCtx(Ctx));
01075     auto Nv = Vs.traverse(Source, Vs.subExprCtx(Ctx));
01076     return Vs.reduceStore(*this, Np, Nv);
01077   }
01078 
01079   template <class C>
01080   typename C::CType compare(const Store* E, C& Cmp) const {
01081     typename C::CType Ct = Cmp.compare(destination(), E->destination());
01082     if (Cmp.notTrue(Ct))
01083       return Ct;
01084     return Cmp.compare(source(), E->source());
01085   }
01086 
01087 private:
01088   SExpr* Dest;
01089   SExpr* Source;
01090 };
01091 
01092 
01093 /// If p is a reference to an array, then p[i] is a reference to the i'th
01094 /// element of the array.
01095 class ArrayIndex : public SExpr {
01096 public:
01097   static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayIndex; }
01098 
01099   ArrayIndex(SExpr *A, SExpr *N) : SExpr(COP_ArrayIndex), Array(A), Index(N) {}
01100   ArrayIndex(const ArrayIndex &E, SExpr *A, SExpr *N)
01101     : SExpr(E), Array(A), Index(N) {}
01102 
01103   SExpr *array() { return Array; }
01104   const SExpr *array() const { return Array; }
01105 
01106   SExpr *index() { return Index; }
01107   const SExpr *index() const { return Index; }
01108 
01109   template <class V>
01110   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
01111     auto Na = Vs.traverse(Array, Vs.subExprCtx(Ctx));
01112     auto Ni = Vs.traverse(Index, Vs.subExprCtx(Ctx));
01113     return Vs.reduceArrayIndex(*this, Na, Ni);
01114   }
01115 
01116   template <class C>
01117   typename C::CType compare(const ArrayIndex* E, C& Cmp) const {
01118     typename C::CType Ct = Cmp.compare(array(), E->array());
01119     if (Cmp.notTrue(Ct))
01120       return Ct;
01121     return Cmp.compare(index(), E->index());
01122   }
01123 
01124 private:
01125   SExpr* Array;
01126   SExpr* Index;
01127 };
01128 
01129 
01130 /// Pointer arithmetic, restricted to arrays only.
01131 /// If p is a reference to an array, then p + n, where n is an integer, is
01132 /// a reference to a subarray.
01133 class ArrayAdd : public SExpr {
01134 public:
01135   static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayAdd; }
01136 
01137   ArrayAdd(SExpr *A, SExpr *N) : SExpr(COP_ArrayAdd), Array(A), Index(N) {}
01138   ArrayAdd(const ArrayAdd &E, SExpr *A, SExpr *N)
01139     : SExpr(E), Array(A), Index(N) {}
01140 
01141   SExpr *array() { return Array; }
01142   const SExpr *array() const { return Array; }
01143 
01144   SExpr *index() { return Index; }
01145   const SExpr *index() const { return Index; }
01146 
01147   template <class V>
01148   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
01149     auto Na = Vs.traverse(Array, Vs.subExprCtx(Ctx));
01150     auto Ni = Vs.traverse(Index, Vs.subExprCtx(Ctx));
01151     return Vs.reduceArrayAdd(*this, Na, Ni);
01152   }
01153 
01154   template <class C>
01155   typename C::CType compare(const ArrayAdd* E, C& Cmp) const {
01156     typename C::CType Ct = Cmp.compare(array(), E->array());
01157     if (Cmp.notTrue(Ct))
01158       return Ct;
01159     return Cmp.compare(index(), E->index());
01160   }
01161 
01162 private:
01163   SExpr* Array;
01164   SExpr* Index;
01165 };
01166 
01167 
01168 /// Simple arithmetic unary operations, e.g. negate and not.
01169 /// These operations have no side-effects.
01170 class UnaryOp : public SExpr {
01171 public:
01172   static bool classof(const SExpr *E) { return E->opcode() == COP_UnaryOp; }
01173 
01174   UnaryOp(TIL_UnaryOpcode Op, SExpr *E) : SExpr(COP_UnaryOp), Expr0(E) {
01175     Flags = Op;
01176   }
01177   UnaryOp(const UnaryOp &U, SExpr *E) : SExpr(U), Expr0(E) { Flags = U.Flags; }
01178 
01179   TIL_UnaryOpcode unaryOpcode() const {
01180     return static_cast<TIL_UnaryOpcode>(Flags);
01181   }
01182 
01183   SExpr *expr() { return Expr0; }
01184   const SExpr *expr() const { return Expr0; }
01185 
01186   template <class V>
01187   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
01188     auto Ne = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
01189     return Vs.reduceUnaryOp(*this, Ne);
01190   }
01191 
01192   template <class C>
01193   typename C::CType compare(const UnaryOp* E, C& Cmp) const {
01194     typename C::CType Ct =
01195       Cmp.compareIntegers(unaryOpcode(), E->unaryOpcode());
01196     if (Cmp.notTrue(Ct))
01197       return Ct;
01198     return Cmp.compare(expr(), E->expr());
01199   }
01200 
01201 private:
01202   SExpr* Expr0;
01203 };
01204 
01205 
01206 /// Simple arithmetic binary operations, e.g. +, -, etc.
01207 /// These operations have no side effects.
01208 class BinaryOp : public SExpr {
01209 public:
01210   static bool classof(const SExpr *E) { return E->opcode() == COP_BinaryOp; }
01211 
01212   BinaryOp(TIL_BinaryOpcode Op, SExpr *E0, SExpr *E1)
01213       : SExpr(COP_BinaryOp), Expr0(E0), Expr1(E1) {
01214     Flags = Op;
01215   }
01216   BinaryOp(const BinaryOp &B, SExpr *E0, SExpr *E1)
01217       : SExpr(B), Expr0(E0), Expr1(E1) {
01218     Flags = B.Flags;
01219   }
01220 
01221   TIL_BinaryOpcode binaryOpcode() const {
01222     return static_cast<TIL_BinaryOpcode>(Flags);
01223   }
01224 
01225   SExpr *expr0() { return Expr0; }
01226   const SExpr *expr0() const { return Expr0; }
01227 
01228   SExpr *expr1() { return Expr1; }
01229   const SExpr *expr1() const { return Expr1; }
01230 
01231   template <class V>
01232   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
01233     auto Ne0 = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
01234     auto Ne1 = Vs.traverse(Expr1, Vs.subExprCtx(Ctx));
01235     return Vs.reduceBinaryOp(*this, Ne0, Ne1);
01236   }
01237 
01238   template <class C>
01239   typename C::CType compare(const BinaryOp* E, C& Cmp) const {
01240     typename C::CType Ct =
01241       Cmp.compareIntegers(binaryOpcode(), E->binaryOpcode());
01242     if (Cmp.notTrue(Ct))
01243       return Ct;
01244     Ct = Cmp.compare(expr0(), E->expr0());
01245     if (Cmp.notTrue(Ct))
01246       return Ct;
01247     return Cmp.compare(expr1(), E->expr1());
01248   }
01249 
01250 private:
01251   SExpr* Expr0;
01252   SExpr* Expr1;
01253 };
01254 
01255 
01256 /// Cast expressions.
01257 /// Cast expressions are essentially unary operations, but we treat them
01258 /// as a distinct AST node because they only change the type of the result.
01259 class Cast : public SExpr {
01260 public:
01261   static bool classof(const SExpr *E) { return E->opcode() == COP_Cast; }
01262 
01263   Cast(TIL_CastOpcode Op, SExpr *E) : SExpr(COP_Cast), Expr0(E) { Flags = Op; }
01264   Cast(const Cast &C, SExpr *E) : SExpr(C), Expr0(E) { Flags = C.Flags; }
01265 
01266   TIL_CastOpcode castOpcode() const {
01267     return static_cast<TIL_CastOpcode>(Flags);
01268   }
01269 
01270   SExpr *expr() { return Expr0; }
01271   const SExpr *expr() const { return Expr0; }
01272 
01273   template <class V>
01274   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
01275     auto Ne = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
01276     return Vs.reduceCast(*this, Ne);
01277   }
01278 
01279   template <class C>
01280   typename C::CType compare(const Cast* E, C& Cmp) const {
01281     typename C::CType Ct =
01282       Cmp.compareIntegers(castOpcode(), E->castOpcode());
01283     if (Cmp.notTrue(Ct))
01284       return Ct;
01285     return Cmp.compare(expr(), E->expr());
01286   }
01287 
01288 private:
01289   SExpr* Expr0;
01290 };
01291 
01292 
01293 class SCFG;
01294 
01295 
01296 /// Phi Node, for code in SSA form.
01297 /// Each Phi node has an array of possible values that it can take,
01298 /// depending on where control flow comes from.
01299 class Phi : public SExpr {
01300 public:
01301   typedef SimpleArray<SExpr *> ValArray;
01302 
01303   // In minimal SSA form, all Phi nodes are MultiVal.
01304   // During conversion to SSA, incomplete Phi nodes may be introduced, which
01305   // are later determined to be SingleVal, and are thus redundant.
01306   enum Status {
01307     PH_MultiVal = 0, // Phi node has multiple distinct values.  (Normal)
01308     PH_SingleVal,    // Phi node has one distinct value, and can be eliminated
01309     PH_Incomplete    // Phi node is incomplete
01310   };
01311 
01312   static bool classof(const SExpr *E) { return E->opcode() == COP_Phi; }
01313 
01314   Phi()
01315     : SExpr(COP_Phi), Cvdecl(nullptr) {}
01316   Phi(MemRegionRef A, unsigned Nvals)
01317     : SExpr(COP_Phi), Values(A, Nvals), Cvdecl(nullptr)  {}
01318   Phi(const Phi &P, ValArray &&Vs)
01319     : SExpr(P), Values(std::move(Vs)), Cvdecl(nullptr) {}
01320 
01321   const ValArray &values() const { return Values; }
01322   ValArray &values() { return Values; }
01323 
01324   Status status() const { return static_cast<Status>(Flags); }
01325   void setStatus(Status s) { Flags = s; }
01326 
01327   /// Return the clang declaration of the variable for this Phi node, if any.
01328   const clang::ValueDecl *clangDecl() const { return Cvdecl; }
01329 
01330   /// Set the clang variable associated with this Phi node.
01331   void setClangDecl(const clang::ValueDecl *Cvd) { Cvdecl = Cvd; }
01332 
01333   template <class V>
01334   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
01335     typename V::template Container<typename V::R_SExpr>
01336       Nvs(Vs, Values.size());
01337 
01338     for (auto *Val : Values) {
01339       Nvs.push_back( Vs.traverse(Val, Vs.subExprCtx(Ctx)) );
01340     }
01341     return Vs.reducePhi(*this, Nvs);
01342   }
01343 
01344   template <class C>
01345   typename C::CType compare(const Phi *E, C &Cmp) const {
01346     // TODO: implement CFG comparisons
01347     return Cmp.comparePointers(this, E);
01348   }
01349 
01350 private:
01351   ValArray Values;
01352   const clang::ValueDecl* Cvdecl;
01353 };
01354 
01355 
01356 /// Base class for basic block terminators:  Branch, Goto, and Return.
01357 class Terminator : public SExpr {
01358 public:
01359   static bool classof(const SExpr *E) {
01360     return E->opcode() >= COP_Goto && E->opcode() <= COP_Return;
01361   }
01362 
01363 protected:
01364   Terminator(TIL_Opcode Op)  : SExpr(Op) {}
01365   Terminator(const SExpr &E) : SExpr(E)  {}
01366 
01367 public:
01368   /// Return the list of basic blocks that this terminator can branch to.
01369   ArrayRef<BasicBlock*> successors();
01370 
01371   ArrayRef<BasicBlock*> successors() const {
01372     return const_cast<const Terminator*>(this)->successors();
01373   }
01374 };
01375 
01376 
01377 /// Jump to another basic block.
01378 /// A goto instruction is essentially a tail-recursive call into another
01379 /// block.  In addition to the block pointer, it specifies an index into the
01380 /// phi nodes of that block.  The index can be used to retrieve the "arguments"
01381 /// of the call.
01382 class Goto : public Terminator {
01383 public:
01384   static bool classof(const SExpr *E) { return E->opcode() == COP_Goto; }
01385 
01386   Goto(BasicBlock *B, unsigned I)
01387       : Terminator(COP_Goto), TargetBlock(B), Index(I) {}
01388   Goto(const Goto &G, BasicBlock *B, unsigned I)
01389       : Terminator(COP_Goto), TargetBlock(B), Index(I) {}
01390 
01391   const BasicBlock *targetBlock() const { return TargetBlock; }
01392   BasicBlock *targetBlock() { return TargetBlock; }
01393 
01394   /// Returns the index into the
01395   unsigned index() const { return Index; }
01396 
01397   /// Return the list of basic blocks that this terminator can branch to.
01398   ArrayRef<BasicBlock*> successors() {
01399     return ArrayRef<BasicBlock*>(&TargetBlock, 1);
01400   }
01401 
01402   template <class V>
01403   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
01404     BasicBlock *Ntb = Vs.reduceBasicBlockRef(TargetBlock);
01405     return Vs.reduceGoto(*this, Ntb);
01406   }
01407 
01408   template <class C>
01409   typename C::CType compare(const Goto *E, C &Cmp) const {
01410     // TODO: implement CFG comparisons
01411     return Cmp.comparePointers(this, E);
01412   }
01413 
01414 private:
01415   BasicBlock *TargetBlock;
01416   unsigned Index;
01417 };
01418 
01419 
01420 /// A conditional branch to two other blocks.
01421 /// Note that unlike Goto, Branch does not have an index.  The target blocks
01422 /// must be child-blocks, and cannot have Phi nodes.
01423 class Branch : public Terminator {
01424 public:
01425   static bool classof(const SExpr *E) { return E->opcode() == COP_Branch; }
01426 
01427   Branch(SExpr *C, BasicBlock *T, BasicBlock *E)
01428       : Terminator(COP_Branch), Condition(C) {
01429     Branches[0] = T;
01430     Branches[1] = E;
01431   }
01432   Branch(const Branch &Br, SExpr *C, BasicBlock *T, BasicBlock *E)
01433       : Terminator(Br), Condition(C) {
01434     Branches[0] = T;
01435     Branches[1] = E;
01436   }
01437 
01438   const SExpr *condition() const { return Condition; }
01439   SExpr *condition() { return Condition; }
01440 
01441   const BasicBlock *thenBlock() const { return Branches[0]; }
01442   BasicBlock *thenBlock() { return Branches[0]; }
01443 
01444   const BasicBlock *elseBlock() const { return Branches[1]; }
01445   BasicBlock *elseBlock() { return Branches[1]; }
01446 
01447   /// Return the list of basic blocks that this terminator can branch to.
01448   ArrayRef<BasicBlock*> successors() {
01449     return ArrayRef<BasicBlock*>(Branches, 2);
01450   }
01451 
01452   template <class V>
01453   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
01454     auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx));
01455     BasicBlock *Ntb = Vs.reduceBasicBlockRef(Branches[0]);
01456     BasicBlock *Nte = Vs.reduceBasicBlockRef(Branches[1]);
01457     return Vs.reduceBranch(*this, Nc, Ntb, Nte);
01458   }
01459 
01460   template <class C>
01461   typename C::CType compare(const Branch *E, C &Cmp) const {
01462     // TODO: implement CFG comparisons
01463     return Cmp.comparePointers(this, E);
01464   }
01465 
01466 private:
01467   SExpr*     Condition;
01468   BasicBlock *Branches[2];
01469 };
01470 
01471 
01472 /// Return from the enclosing function, passing the return value to the caller.
01473 /// Only the exit block should end with a return statement.
01474 class Return : public Terminator {
01475 public:
01476   static bool classof(const SExpr *E) { return E->opcode() == COP_Return; }
01477 
01478   Return(SExpr* Rval) : Terminator(COP_Return), Retval(Rval) {}
01479   Return(const Return &R, SExpr* Rval) : Terminator(R), Retval(Rval) {}
01480 
01481   /// Return an empty list.
01482   ArrayRef<BasicBlock*> successors() {
01483     return ArrayRef<BasicBlock*>();
01484   }
01485 
01486   SExpr *returnValue() { return Retval; }
01487   const SExpr *returnValue() const { return Retval; }
01488 
01489   template <class V>
01490   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
01491     auto Ne = Vs.traverse(Retval, Vs.subExprCtx(Ctx));
01492     return Vs.reduceReturn(*this, Ne);
01493   }
01494 
01495   template <class C>
01496   typename C::CType compare(const Return *E, C &Cmp) const {
01497     return Cmp.compare(Retval, E->Retval);
01498   }
01499 
01500 private:
01501   SExpr* Retval;
01502 };
01503 
01504 
01505 inline ArrayRef<BasicBlock*> Terminator::successors() {
01506   switch (opcode()) {
01507     case COP_Goto:   return cast<Goto>(this)->successors();
01508     case COP_Branch: return cast<Branch>(this)->successors();
01509     case COP_Return: return cast<Return>(this)->successors();
01510     default:
01511       return ArrayRef<BasicBlock*>();
01512   }
01513 }
01514 
01515 
01516 /// A basic block is part of an SCFG.  It can be treated as a function in
01517 /// continuation passing style.  A block consists of a sequence of phi nodes,
01518 /// which are "arguments" to the function, followed by a sequence of
01519 /// instructions.  It ends with a Terminator, which is a Branch or Goto to
01520 /// another basic block in the same SCFG.
01521 class BasicBlock : public SExpr {
01522 public:
01523   typedef SimpleArray<SExpr*>      InstrArray;
01524   typedef SimpleArray<BasicBlock*> BlockArray;
01525 
01526   // TopologyNodes are used to overlay tree structures on top of the CFG,
01527   // such as dominator and postdominator trees.  Each block is assigned an
01528   // ID in the tree according to a depth-first search.  Tree traversals are
01529   // always up, towards the parents.
01530   struct TopologyNode {
01531     TopologyNode() : NodeID(0), SizeOfSubTree(0), Parent(nullptr) {}
01532 
01533     bool isParentOf(const TopologyNode& OtherNode) {
01534       return OtherNode.NodeID > NodeID &&
01535              OtherNode.NodeID < NodeID + SizeOfSubTree;
01536     }
01537 
01538     bool isParentOfOrEqual(const TopologyNode& OtherNode) {
01539       return OtherNode.NodeID >= NodeID &&
01540              OtherNode.NodeID < NodeID + SizeOfSubTree;
01541     }
01542 
01543     int NodeID;
01544     int SizeOfSubTree;    // Includes this node, so must be > 1.
01545     BasicBlock *Parent;   // Pointer to parent.
01546   };
01547 
01548   static bool classof(const SExpr *E) { return E->opcode() == COP_BasicBlock; }
01549 
01550   explicit BasicBlock(MemRegionRef A)
01551       : SExpr(COP_BasicBlock), Arena(A), CFGPtr(nullptr), BlockID(0),
01552         Visited(0), TermInstr(nullptr) {}
01553   BasicBlock(BasicBlock &B, MemRegionRef A, InstrArray &&As, InstrArray &&Is,
01554              Terminator *T)
01555       : SExpr(COP_BasicBlock), Arena(A), CFGPtr(nullptr), BlockID(0),Visited(0),
01556         Args(std::move(As)), Instrs(std::move(Is)), TermInstr(T) {}
01557 
01558   /// Returns the block ID.  Every block has a unique ID in the CFG.
01559   int blockID() const { return BlockID; }
01560 
01561   /// Returns the number of predecessors.
01562   size_t numPredecessors() const { return Predecessors.size(); }
01563   size_t numSuccessors() const { return successors().size(); }
01564 
01565   const SCFG* cfg() const { return CFGPtr; }
01566   SCFG* cfg() { return CFGPtr; }
01567 
01568   const BasicBlock *parent() const { return DominatorNode.Parent; }
01569   BasicBlock *parent() { return DominatorNode.Parent; }
01570 
01571   const InstrArray &arguments() const { return Args; }
01572   InstrArray &arguments() { return Args; }
01573 
01574   InstrArray &instructions() { return Instrs; }
01575   const InstrArray &instructions() const { return Instrs; }
01576 
01577   /// Returns a list of predecessors.
01578   /// The order of predecessors in the list is important; each phi node has
01579   /// exactly one argument for each precessor, in the same order.
01580   BlockArray &predecessors() { return Predecessors; }
01581   const BlockArray &predecessors() const { return Predecessors; }
01582 
01583   ArrayRef<BasicBlock*> successors() { return TermInstr->successors(); }
01584   ArrayRef<BasicBlock*> successors() const { return TermInstr->successors(); }
01585 
01586   const Terminator *terminator() const { return TermInstr; }
01587   Terminator *terminator() { return TermInstr; }
01588 
01589   void setTerminator(Terminator *E) { TermInstr = E; }
01590 
01591   bool Dominates(const BasicBlock &Other) {
01592     return DominatorNode.isParentOfOrEqual(Other.DominatorNode);
01593   }
01594 
01595   bool PostDominates(const BasicBlock &Other) {
01596     return PostDominatorNode.isParentOfOrEqual(Other.PostDominatorNode);
01597   }
01598 
01599   /// Add a new argument.
01600   void addArgument(Phi *V) {
01601     Args.reserveCheck(1, Arena);
01602     Args.push_back(V);
01603   }
01604   /// Add a new instruction.
01605   void addInstruction(SExpr *V) {
01606     Instrs.reserveCheck(1, Arena);
01607     Instrs.push_back(V);
01608   }
01609   // Add a new predecessor, and return the phi-node index for it.
01610   // Will add an argument to all phi-nodes, initialized to nullptr.
01611   unsigned addPredecessor(BasicBlock *Pred);
01612 
01613   // Reserve space for Nargs arguments.
01614   void reserveArguments(unsigned Nargs)   { Args.reserve(Nargs, Arena); }
01615 
01616   // Reserve space for Nins instructions.
01617   void reserveInstructions(unsigned Nins) { Instrs.reserve(Nins, Arena); }
01618 
01619   // Reserve space for NumPreds predecessors, including space in phi nodes.
01620   void reservePredecessors(unsigned NumPreds);
01621 
01622   /// Return the index of BB, or Predecessors.size if BB is not a predecessor.
01623   unsigned findPredecessorIndex(const BasicBlock *BB) const {
01624     auto I = std::find(Predecessors.cbegin(), Predecessors.cend(), BB);
01625     return std::distance(Predecessors.cbegin(), I);
01626   }
01627 
01628   template <class V>
01629   typename V::R_BasicBlock traverse(V &Vs, typename V::R_Ctx Ctx) {
01630     typename V::template Container<SExpr*> Nas(Vs, Args.size());
01631     typename V::template Container<SExpr*> Nis(Vs, Instrs.size());
01632 
01633     // Entering the basic block should do any scope initialization.
01634     Vs.enterBasicBlock(*this);
01635 
01636     for (auto *E : Args) {
01637       auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
01638       Nas.push_back(Ne);
01639     }
01640     for (auto *E : Instrs) {
01641       auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
01642       Nis.push_back(Ne);
01643     }
01644     auto Nt = Vs.traverse(TermInstr, Ctx);
01645 
01646     // Exiting the basic block should handle any scope cleanup.
01647     Vs.exitBasicBlock(*this);
01648 
01649     return Vs.reduceBasicBlock(*this, Nas, Nis, Nt);
01650   }
01651 
01652   template <class C>
01653   typename C::CType compare(const BasicBlock *E, C &Cmp) const {
01654     // TODO: implement CFG comparisons
01655     return Cmp.comparePointers(this, E);
01656   }
01657 
01658 private:
01659   friend class SCFG;
01660 
01661   int  renumberInstrs(int id);  // assign unique ids to all instructions
01662   int  topologicalSort(SimpleArray<BasicBlock*>& Blocks, int ID);
01663   int  topologicalFinalSort(SimpleArray<BasicBlock*>& Blocks, int ID);
01664   void computeDominator();
01665   void computePostDominator();
01666 
01667 private:
01668   MemRegionRef Arena;        // The arena used to allocate this block.
01669   SCFG         *CFGPtr;      // The CFG that contains this block.
01670   int          BlockID : 31; // unique id for this BB in the containing CFG.
01671                              // IDs are in topological order.
01672   bool         Visited : 1;  // Bit to determine if a block has been visited
01673                              // during a traversal.
01674   BlockArray  Predecessors;  // Predecessor blocks in the CFG.
01675   InstrArray  Args;          // Phi nodes.  One argument per predecessor.
01676   InstrArray  Instrs;        // Instructions.
01677   Terminator* TermInstr;     // Terminating instruction
01678 
01679   TopologyNode DominatorNode;       // The dominator tree
01680   TopologyNode PostDominatorNode;   // The post-dominator tree
01681 };
01682 
01683 
01684 /// An SCFG is a control-flow graph.  It consists of a set of basic blocks,
01685 /// each of which terminates in a branch to another basic block.  There is one
01686 /// entry point, and one exit point.
01687 class SCFG : public SExpr {
01688 public:
01689   typedef SimpleArray<BasicBlock *> BlockArray;
01690   typedef BlockArray::iterator iterator;
01691   typedef BlockArray::const_iterator const_iterator;
01692 
01693   static bool classof(const SExpr *E) { return E->opcode() == COP_SCFG; }
01694 
01695   SCFG(MemRegionRef A, unsigned Nblocks)
01696     : SExpr(COP_SCFG), Arena(A), Blocks(A, Nblocks),
01697       Entry(nullptr), Exit(nullptr), NumInstructions(0), Normal(false) {
01698     Entry = new (A) BasicBlock(A);
01699     Exit  = new (A) BasicBlock(A);
01700     auto *V = new (A) Phi();
01701     Exit->addArgument(V);
01702     Exit->setTerminator(new (A) Return(V));
01703     add(Entry);
01704     add(Exit);
01705   }
01706   SCFG(const SCFG &Cfg, BlockArray &&Ba) // steals memory from Ba
01707       : SExpr(COP_SCFG), Arena(Cfg.Arena), Blocks(std::move(Ba)),
01708         Entry(nullptr), Exit(nullptr), NumInstructions(0), Normal(false) {
01709     // TODO: set entry and exit!
01710   }
01711 
01712   /// Return true if this CFG is valid.
01713   bool valid() const { return Entry && Exit && Blocks.size() > 0; }
01714 
01715   /// Return true if this CFG has been normalized.
01716   /// After normalization, blocks are in topological order, and block and
01717   /// instruction IDs have been assigned.
01718   bool normal() const { return Normal; }
01719 
01720   iterator begin() { return Blocks.begin(); }
01721   iterator end() { return Blocks.end(); }
01722 
01723   const_iterator begin() const { return cbegin(); }
01724   const_iterator end() const { return cend(); }
01725 
01726   const_iterator cbegin() const { return Blocks.cbegin(); }
01727   const_iterator cend() const { return Blocks.cend(); }
01728 
01729   const BasicBlock *entry() const { return Entry; }
01730   BasicBlock *entry() { return Entry; }
01731   const BasicBlock *exit() const { return Exit; }
01732   BasicBlock *exit() { return Exit; }
01733 
01734   /// Return the number of blocks in the CFG.
01735   /// Block::blockID() will return a number less than numBlocks();
01736   size_t numBlocks() const { return Blocks.size(); }
01737 
01738   /// Return the total number of instructions in the CFG.
01739   /// This is useful for building instruction side-tables;
01740   /// A call to SExpr::id() will return a number less than numInstructions().
01741   unsigned numInstructions() { return NumInstructions; }
01742 
01743   inline void add(BasicBlock *BB) {
01744     assert(BB->CFGPtr == nullptr);
01745     BB->CFGPtr = this;
01746     Blocks.reserveCheck(1, Arena);
01747     Blocks.push_back(BB);
01748   }
01749 
01750   void setEntry(BasicBlock *BB) { Entry = BB; }
01751   void setExit(BasicBlock *BB)  { Exit = BB;  }
01752 
01753   void computeNormalForm();
01754 
01755   template <class V>
01756   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
01757     Vs.enterCFG(*this);
01758     typename V::template Container<BasicBlock *> Bbs(Vs, Blocks.size());
01759 
01760     for (auto *B : Blocks) {
01761       Bbs.push_back( B->traverse(Vs, Vs.subExprCtx(Ctx)) );
01762     }
01763     Vs.exitCFG(*this);
01764     return Vs.reduceSCFG(*this, Bbs);
01765   }
01766 
01767   template <class C>
01768   typename C::CType compare(const SCFG *E, C &Cmp) const {
01769     // TODO: implement CFG comparisons
01770     return Cmp.comparePointers(this, E);
01771   }
01772 
01773 private:
01774   void renumberInstrs();       // assign unique ids to all instructions
01775 
01776 private:
01777   MemRegionRef Arena;
01778   BlockArray   Blocks;
01779   BasicBlock   *Entry;
01780   BasicBlock   *Exit;
01781   unsigned     NumInstructions;
01782   bool         Normal;
01783 };
01784 
01785 
01786 
01787 /// An identifier, e.g. 'foo' or 'x'.
01788 /// This is a pseduo-term; it will be lowered to a variable or projection.
01789 class Identifier : public SExpr {
01790 public:
01791   static bool classof(const SExpr *E) { return E->opcode() == COP_Identifier; }
01792 
01793   Identifier(StringRef Id): SExpr(COP_Identifier), Name(Id) { }
01794   Identifier(const Identifier& I) : SExpr(I), Name(I.Name)  { }
01795 
01796   StringRef name() const { return Name; }
01797 
01798   template <class V>
01799   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
01800     return Vs.reduceIdentifier(*this);
01801   }
01802 
01803   template <class C>
01804   typename C::CType compare(const Identifier* E, C& Cmp) const {
01805     return Cmp.compareStrings(name(), E->name());
01806   }
01807 
01808 private:
01809   StringRef Name;
01810 };
01811 
01812 
01813 /// An if-then-else expression.
01814 /// This is a pseduo-term; it will be lowered to a branch in a CFG.
01815 class IfThenElse : public SExpr {
01816 public:
01817   static bool classof(const SExpr *E) { return E->opcode() == COP_IfThenElse; }
01818 
01819   IfThenElse(SExpr *C, SExpr *T, SExpr *E)
01820     : SExpr(COP_IfThenElse), Condition(C), ThenExpr(T), ElseExpr(E)
01821   { }
01822   IfThenElse(const IfThenElse &I, SExpr *C, SExpr *T, SExpr *E)
01823     : SExpr(I), Condition(C), ThenExpr(T), ElseExpr(E)
01824   { }
01825 
01826   SExpr *condition() { return Condition; }   // Address to store to
01827   const SExpr *condition() const { return Condition; }
01828 
01829   SExpr *thenExpr() { return ThenExpr; }     // Value to store
01830   const SExpr *thenExpr() const { return ThenExpr; }
01831 
01832   SExpr *elseExpr() { return ElseExpr; }     // Value to store
01833   const SExpr *elseExpr() const { return ElseExpr; }
01834 
01835   template <class V>
01836   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
01837     auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx));
01838     auto Nt = Vs.traverse(ThenExpr,  Vs.subExprCtx(Ctx));
01839     auto Ne = Vs.traverse(ElseExpr,  Vs.subExprCtx(Ctx));
01840     return Vs.reduceIfThenElse(*this, Nc, Nt, Ne);
01841   }
01842 
01843   template <class C>
01844   typename C::CType compare(const IfThenElse* E, C& Cmp) const {
01845     typename C::CType Ct = Cmp.compare(condition(), E->condition());
01846     if (Cmp.notTrue(Ct))
01847       return Ct;
01848     Ct = Cmp.compare(thenExpr(), E->thenExpr());
01849     if (Cmp.notTrue(Ct))
01850       return Ct;
01851     return Cmp.compare(elseExpr(), E->elseExpr());
01852   }
01853 
01854 private:
01855   SExpr* Condition;
01856   SExpr* ThenExpr;
01857   SExpr* ElseExpr;
01858 };
01859 
01860 
01861 /// A let-expression,  e.g.  let x=t; u.
01862 /// This is a pseduo-term; it will be lowered to instructions in a CFG.
01863 class Let : public SExpr {
01864 public:
01865   static bool classof(const SExpr *E) { return E->opcode() == COP_Let; }
01866 
01867   Let(Variable *Vd, SExpr *Bd) : SExpr(COP_Let), VarDecl(Vd), Body(Bd) {
01868     Vd->setKind(Variable::VK_Let);
01869   }
01870   Let(const Let &L, Variable *Vd, SExpr *Bd) : SExpr(L), VarDecl(Vd), Body(Bd) {
01871     Vd->setKind(Variable::VK_Let);
01872   }
01873 
01874   Variable *variableDecl()  { return VarDecl; }
01875   const Variable *variableDecl() const { return VarDecl; }
01876 
01877   SExpr *body() { return Body; }
01878   const SExpr *body() const { return Body; }
01879 
01880   template <class V>
01881   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
01882     // This is a variable declaration, so traverse the definition.
01883     auto E0 = Vs.traverse(VarDecl->Definition, Vs.subExprCtx(Ctx));
01884     // Tell the rewriter to enter the scope of the let variable.
01885     Variable *Nvd = Vs.enterScope(*VarDecl, E0);
01886     auto E1 = Vs.traverse(Body, Ctx);
01887     Vs.exitScope(*VarDecl);
01888     return Vs.reduceLet(*this, Nvd, E1);
01889   }
01890 
01891   template <class C>
01892   typename C::CType compare(const Let* E, C& Cmp) const {
01893     typename C::CType Ct =
01894       Cmp.compare(VarDecl->definition(), E->VarDecl->definition());
01895     if (Cmp.notTrue(Ct))
01896       return Ct;
01897     Cmp.enterScope(variableDecl(), E->variableDecl());
01898     Ct = Cmp.compare(body(), E->body());
01899     Cmp.leaveScope();
01900     return Ct;
01901   }
01902 
01903 private:
01904   Variable *VarDecl;
01905   SExpr* Body;
01906 };
01907 
01908 
01909 
01910 const SExpr *getCanonicalVal(const SExpr *E);
01911 SExpr* simplifyToCanonicalVal(SExpr *E);
01912 void simplifyIncompleteArg(til::Phi *Ph);
01913 
01914 
01915 } // end namespace til
01916 } // end namespace threadSafety
01917 } // end namespace clang
01918 
01919 #endif