Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:24

0001 //===- ThreadSafetyTIL.h ----------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file defines a simple Typed Intermediate Language, or TIL, that is used
0010 // by the thread safety analysis (See ThreadSafety.cpp).  The TIL is intended
0011 // to be largely independent of clang, in the hope that the analysis can be
0012 // reused for other non-C++ languages.  All dependencies on clang/llvm should
0013 // go in ThreadSafetyUtil.h.
0014 //
0015 // Thread safety analysis works by comparing mutex expressions, e.g.
0016 //
0017 // class A { Mutex mu; int dat GUARDED_BY(this->mu); }
0018 // class B { A a; }
0019 //
0020 // void foo(B* b) {
0021 //   (*b).a.mu.lock();     // locks (*b).a.mu
0022 //   b->a.dat = 0;         // substitute &b->a for 'this';
0023 //                         // requires lock on (&b->a)->mu
0024 //   (b->a.mu).unlock();   // unlocks (b->a.mu)
0025 // }
0026 //
0027 // As illustrated by the above example, clang Exprs are not well-suited to
0028 // represent mutex expressions directly, since there is no easy way to compare
0029 // Exprs for equivalence.  The thread safety analysis thus lowers clang Exprs
0030 // into a simple intermediate language (IL).  The IL supports:
0031 //
0032 // (1) comparisons for semantic equality of expressions
0033 // (2) SSA renaming of variables
0034 // (3) wildcards and pattern matching over expressions
0035 // (4) hash-based expression lookup
0036 //
0037 // The TIL is currently very experimental, is intended only for use within
0038 // the thread safety analysis, and is subject to change without notice.
0039 // After the API stabilizes and matures, it may be appropriate to make this
0040 // more generally available to other analyses.
0041 //
0042 // UNDER CONSTRUCTION.  USE AT YOUR OWN RISK.
0043 //
0044 //===----------------------------------------------------------------------===//
0045 
0046 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H
0047 #define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H
0048 
0049 #include "clang/AST/Decl.h"
0050 #include "clang/Analysis/Analyses/ThreadSafetyUtil.h"
0051 #include "clang/Basic/LLVM.h"
0052 #include "llvm/ADT/ArrayRef.h"
0053 #include "llvm/ADT/StringRef.h"
0054 #include "llvm/Support/Casting.h"
0055 #include "llvm/Support/raw_ostream.h"
0056 #include <algorithm>
0057 #include <cassert>
0058 #include <cstddef>
0059 #include <cstdint>
0060 #include <iterator>
0061 #include <optional>
0062 #include <string>
0063 #include <utility>
0064 
0065 namespace clang {
0066 
0067 class CallExpr;
0068 class Expr;
0069 class Stmt;
0070 
0071 namespace threadSafety {
0072 namespace til {
0073 
0074 class BasicBlock;
0075 
0076 /// Enum for the different distinct classes of SExpr
0077 enum TIL_Opcode : unsigned char {
0078 #define TIL_OPCODE_DEF(X) COP_##X,
0079 #include "ThreadSafetyOps.def"
0080 #undef TIL_OPCODE_DEF
0081 };
0082 
0083 /// Opcode for unary arithmetic operations.
0084 enum TIL_UnaryOpcode : unsigned char {
0085   UOP_Minus,        //  -
0086   UOP_BitNot,       //  ~
0087   UOP_LogicNot      //  !
0088 };
0089 
0090 /// Opcode for binary arithmetic operations.
0091 enum TIL_BinaryOpcode : unsigned char {
0092   BOP_Add,          //  +
0093   BOP_Sub,          //  -
0094   BOP_Mul,          //  *
0095   BOP_Div,          //  /
0096   BOP_Rem,          //  %
0097   BOP_Shl,          //  <<
0098   BOP_Shr,          //  >>
0099   BOP_BitAnd,       //  &
0100   BOP_BitXor,       //  ^
0101   BOP_BitOr,        //  |
0102   BOP_Eq,           //  ==
0103   BOP_Neq,          //  !=
0104   BOP_Lt,           //  <
0105   BOP_Leq,          //  <=
0106   BOP_Cmp,          //  <=>
0107   BOP_LogicAnd,     //  &&  (no short-circuit)
0108   BOP_LogicOr       //  ||  (no short-circuit)
0109 };
0110 
0111 /// Opcode for cast operations.
0112 enum TIL_CastOpcode : unsigned char {
0113   CAST_none = 0,
0114 
0115   // Extend precision of numeric type
0116   CAST_extendNum,
0117 
0118   // Truncate precision of numeric type
0119   CAST_truncNum,
0120 
0121   // Convert to floating point type
0122   CAST_toFloat,
0123 
0124   // Convert to integer type
0125   CAST_toInt,
0126 
0127   // Convert smart pointer to pointer (C++ only)
0128   CAST_objToPtr
0129 };
0130 
0131 const TIL_Opcode       COP_Min  = COP_Future;
0132 const TIL_Opcode       COP_Max  = COP_Branch;
0133 const TIL_UnaryOpcode  UOP_Min  = UOP_Minus;
0134 const TIL_UnaryOpcode  UOP_Max  = UOP_LogicNot;
0135 const TIL_BinaryOpcode BOP_Min  = BOP_Add;
0136 const TIL_BinaryOpcode BOP_Max  = BOP_LogicOr;
0137 const TIL_CastOpcode   CAST_Min = CAST_none;
0138 const TIL_CastOpcode   CAST_Max = CAST_toInt;
0139 
0140 /// Return the name of a unary opcode.
0141 StringRef getUnaryOpcodeString(TIL_UnaryOpcode Op);
0142 
0143 /// Return the name of a binary opcode.
0144 StringRef getBinaryOpcodeString(TIL_BinaryOpcode Op);
0145 
0146 /// ValueTypes are data types that can actually be held in registers.
0147 /// All variables and expressions must have a value type.
0148 /// Pointer types are further subdivided into the various heap-allocated
0149 /// types, such as functions, records, etc.
0150 /// Structured types that are passed by value (e.g. complex numbers)
0151 /// require special handling; they use BT_ValueRef, and size ST_0.
0152 struct ValueType {
0153   enum BaseType : unsigned char {
0154     BT_Void = 0,
0155     BT_Bool,
0156     BT_Int,
0157     BT_Float,
0158     BT_String,    // String literals
0159     BT_Pointer,
0160     BT_ValueRef
0161   };
0162 
0163   enum SizeType : unsigned char {
0164     ST_0 = 0,
0165     ST_1,
0166     ST_8,
0167     ST_16,
0168     ST_32,
0169     ST_64,
0170     ST_128
0171   };
0172 
0173   ValueType(BaseType B, SizeType Sz, bool S, unsigned char VS)
0174       : Base(B), Size(Sz), Signed(S), VectSize(VS) {}
0175 
0176   inline static SizeType getSizeType(unsigned nbytes);
0177 
0178   template <class T>
0179   inline static ValueType getValueType();
0180 
0181   BaseType Base;
0182   SizeType Size;
0183   bool Signed;
0184 
0185   // 0 for scalar, otherwise num elements in vector
0186   unsigned char VectSize;
0187 };
0188 
0189 inline ValueType::SizeType ValueType::getSizeType(unsigned nbytes) {
0190   switch (nbytes) {
0191     case 1: return ST_8;
0192     case 2: return ST_16;
0193     case 4: return ST_32;
0194     case 8: return ST_64;
0195     case 16: return ST_128;
0196     default: return ST_0;
0197   }
0198 }
0199 
0200 template<>
0201 inline ValueType ValueType::getValueType<void>() {
0202   return ValueType(BT_Void, ST_0, false, 0);
0203 }
0204 
0205 template<>
0206 inline ValueType ValueType::getValueType<bool>() {
0207   return ValueType(BT_Bool, ST_1, false, 0);
0208 }
0209 
0210 template<>
0211 inline ValueType ValueType::getValueType<int8_t>() {
0212   return ValueType(BT_Int, ST_8, true, 0);
0213 }
0214 
0215 template<>
0216 inline ValueType ValueType::getValueType<uint8_t>() {
0217   return ValueType(BT_Int, ST_8, false, 0);
0218 }
0219 
0220 template<>
0221 inline ValueType ValueType::getValueType<int16_t>() {
0222   return ValueType(BT_Int, ST_16, true, 0);
0223 }
0224 
0225 template<>
0226 inline ValueType ValueType::getValueType<uint16_t>() {
0227   return ValueType(BT_Int, ST_16, false, 0);
0228 }
0229 
0230 template<>
0231 inline ValueType ValueType::getValueType<int32_t>() {
0232   return ValueType(BT_Int, ST_32, true, 0);
0233 }
0234 
0235 template<>
0236 inline ValueType ValueType::getValueType<uint32_t>() {
0237   return ValueType(BT_Int, ST_32, false, 0);
0238 }
0239 
0240 template<>
0241 inline ValueType ValueType::getValueType<int64_t>() {
0242   return ValueType(BT_Int, ST_64, true, 0);
0243 }
0244 
0245 template<>
0246 inline ValueType ValueType::getValueType<uint64_t>() {
0247   return ValueType(BT_Int, ST_64, false, 0);
0248 }
0249 
0250 template<>
0251 inline ValueType ValueType::getValueType<float>() {
0252   return ValueType(BT_Float, ST_32, true, 0);
0253 }
0254 
0255 template<>
0256 inline ValueType ValueType::getValueType<double>() {
0257   return ValueType(BT_Float, ST_64, true, 0);
0258 }
0259 
0260 template<>
0261 inline ValueType ValueType::getValueType<long double>() {
0262   return ValueType(BT_Float, ST_128, true, 0);
0263 }
0264 
0265 template<>
0266 inline ValueType ValueType::getValueType<StringRef>() {
0267   return ValueType(BT_String, getSizeType(sizeof(StringRef)), false, 0);
0268 }
0269 
0270 template<>
0271 inline ValueType ValueType::getValueType<void*>() {
0272   return ValueType(BT_Pointer, getSizeType(sizeof(void*)), false, 0);
0273 }
0274 
0275 /// Base class for AST nodes in the typed intermediate language.
0276 class SExpr {
0277 public:
0278   SExpr() = delete;
0279 
0280   TIL_Opcode opcode() const { return Opcode; }
0281 
0282   // Subclasses of SExpr must define the following:
0283   //
0284   // This(const This& E, ...) {
0285   //   copy constructor: construct copy of E, with some additional arguments.
0286   // }
0287   //
0288   // template <class V>
0289   // typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
0290   //   traverse all subexpressions, following the traversal/rewriter interface.
0291   // }
0292   //
0293   // template <class C> typename C::CType compare(CType* E, C& Cmp) {
0294   //   compare all subexpressions, following the comparator interface
0295   // }
0296   void *operator new(size_t S, MemRegionRef &R) {
0297     return ::operator new(S, R);
0298   }
0299 
0300   /// SExpr objects must be created in an arena.
0301   void *operator new(size_t) = delete;
0302 
0303   /// SExpr objects cannot be deleted.
0304   // This declaration is public to workaround a gcc bug that breaks building
0305   // with REQUIRES_EH=1.
0306   void operator delete(void *) = delete;
0307 
0308   /// Returns the instruction ID for this expression.
0309   /// All basic block instructions have a unique ID (i.e. virtual register).
0310   unsigned id() const { return SExprID; }
0311 
0312   /// Returns the block, if this is an instruction in a basic block,
0313   /// otherwise returns null.
0314   BasicBlock *block() const { return Block; }
0315 
0316   /// Set the basic block and instruction ID for this expression.
0317   void setID(BasicBlock *B, unsigned id) { Block = B; SExprID = id; }
0318 
0319 protected:
0320   SExpr(TIL_Opcode Op) : Opcode(Op) {}
0321   SExpr(const SExpr &E) : Opcode(E.Opcode), Flags(E.Flags) {}
0322   SExpr &operator=(const SExpr &) = delete;
0323 
0324   const TIL_Opcode Opcode;
0325   unsigned char Reserved = 0;
0326   unsigned short Flags = 0;
0327   unsigned SExprID = 0;
0328   BasicBlock *Block = nullptr;
0329 };
0330 
0331 // Contains various helper functions for SExprs.
0332 namespace ThreadSafetyTIL {
0333 
0334 inline bool isTrivial(const SExpr *E) {
0335   TIL_Opcode Op = E->opcode();
0336   return Op == COP_Variable || Op == COP_Literal || Op == COP_LiteralPtr;
0337 }
0338 
0339 } // namespace ThreadSafetyTIL
0340 
0341 // Nodes which declare variables
0342 
0343 /// A named variable, e.g. "x".
0344 ///
0345 /// There are two distinct places in which a Variable can appear in the AST.
0346 /// A variable declaration introduces a new variable, and can occur in 3 places:
0347 ///   Let-expressions:           (Let (x = t) u)
0348 ///   Functions:                 (Function (x : t) u)
0349 ///   Self-applicable functions  (SFunction (x) t)
0350 ///
0351 /// If a variable occurs in any other location, it is a reference to an existing
0352 /// variable declaration -- e.g. 'x' in (x * y + z). To save space, we don't
0353 /// allocate a separate AST node for variable references; a reference is just a
0354 /// pointer to the original declaration.
0355 class Variable : public SExpr {
0356 public:
0357   enum VariableKind {
0358     /// Let-variable
0359     VK_Let,
0360 
0361     /// Function parameter
0362     VK_Fun,
0363 
0364     /// SFunction (self) parameter
0365     VK_SFun
0366   };
0367 
0368   Variable(StringRef s, SExpr *D = nullptr)
0369       : SExpr(COP_Variable), Name(s), Definition(D) {
0370     Flags = VK_Let;
0371   }
0372 
0373   Variable(SExpr *D, const ValueDecl *Cvd = nullptr)
0374       : SExpr(COP_Variable), Name(Cvd ? Cvd->getName() : "_x"),
0375         Definition(D), Cvdecl(Cvd) {
0376     Flags = VK_Let;
0377   }
0378 
0379   Variable(const Variable &Vd, SExpr *D)  // rewrite constructor
0380       : SExpr(Vd), Name(Vd.Name), Definition(D), Cvdecl(Vd.Cvdecl) {
0381     Flags = Vd.kind();
0382   }
0383 
0384   static bool classof(const SExpr *E) { return E->opcode() == COP_Variable; }
0385 
0386   /// Return the kind of variable (let, function param, or self)
0387   VariableKind kind() const { return static_cast<VariableKind>(Flags); }
0388 
0389   /// Return the name of the variable, if any.
0390   StringRef name() const { return Name; }
0391 
0392   /// Return the clang declaration for this variable, if any.
0393   const ValueDecl *clangDecl() const { return Cvdecl; }
0394 
0395   /// Return the definition of the variable.
0396   /// For let-vars, this is the setting expression.
0397   /// For function and self parameters, it is the type of the variable.
0398   SExpr *definition() { return Definition; }
0399   const SExpr *definition() const { return Definition; }
0400 
0401   void setName(StringRef S)    { Name = S;  }
0402   void setKind(VariableKind K) { Flags = K; }
0403   void setDefinition(SExpr *E) { Definition = E; }
0404   void setClangDecl(const ValueDecl *VD) { Cvdecl = VD; }
0405 
0406   template <class V>
0407   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
0408     // This routine is only called for variable references.
0409     return Vs.reduceVariableRef(this);
0410   }
0411 
0412   template <class C>
0413   typename C::CType compare(const Variable* E, C& Cmp) const {
0414     return Cmp.compareVariableRefs(this, E);
0415   }
0416 
0417 private:
0418   friend class BasicBlock;
0419   friend class Function;
0420   friend class Let;
0421   friend class SFunction;
0422 
0423   // The name of the variable.
0424   StringRef Name;
0425 
0426   // The TIL type or definition.
0427   SExpr *Definition;
0428 
0429   // The clang declaration for this variable.
0430   const ValueDecl *Cvdecl = nullptr;
0431 };
0432 
0433 /// Placeholder for an expression that has not yet been created.
0434 /// Used to implement lazy copy and rewriting strategies.
0435 class Future : public SExpr {
0436 public:
0437   enum FutureStatus {
0438     FS_pending,
0439     FS_evaluating,
0440     FS_done
0441   };
0442 
0443   Future() : SExpr(COP_Future) {}
0444   virtual ~Future() = delete;
0445 
0446   static bool classof(const SExpr *E) { return E->opcode() == COP_Future; }
0447 
0448   // A lazy rewriting strategy should subclass Future and override this method.
0449   virtual SExpr *compute() { return nullptr; }
0450 
0451   // Return the result of this future if it exists, otherwise return null.
0452   SExpr *maybeGetResult() const { return Result; }
0453 
0454   // Return the result of this future; forcing it if necessary.
0455   SExpr *result() {
0456     switch (Status) {
0457     case FS_pending:
0458       return force();
0459     case FS_evaluating:
0460       return nullptr; // infinite loop; illegal recursion.
0461     case FS_done:
0462       return Result;
0463     }
0464   }
0465 
0466   template <class V>
0467   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
0468     assert(Result && "Cannot traverse Future that has not been forced.");
0469     return Vs.traverse(Result, Ctx);
0470   }
0471 
0472   template <class C>
0473   typename C::CType compare(const Future* E, C& Cmp) const {
0474     if (!Result || !E->Result)
0475       return Cmp.comparePointers(this, E);
0476     return Cmp.compare(Result, E->Result);
0477   }
0478 
0479 private:
0480   SExpr* force();
0481 
0482   FutureStatus Status = FS_pending;
0483   SExpr *Result = nullptr;
0484 };
0485 
0486 /// Placeholder for expressions that cannot be represented in the TIL.
0487 class Undefined : public SExpr {
0488 public:
0489   Undefined(const Stmt *S = nullptr) : SExpr(COP_Undefined), Cstmt(S) {}
0490   Undefined(const Undefined &U) : SExpr(U), Cstmt(U.Cstmt) {}
0491 
0492   // The copy assignment operator is defined as deleted pending further
0493   // motivation.
0494   Undefined &operator=(const Undefined &) = delete;
0495 
0496   static bool classof(const SExpr *E) { return E->opcode() == COP_Undefined; }
0497 
0498   template <class V>
0499   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
0500     return Vs.reduceUndefined(*this);
0501   }
0502 
0503   template <class C>
0504   typename C::CType compare(const Undefined* E, C& Cmp) const {
0505     return Cmp.trueResult();
0506   }
0507 
0508 private:
0509   const Stmt *Cstmt;
0510 };
0511 
0512 /// Placeholder for a wildcard that matches any other expression.
0513 class Wildcard : public SExpr {
0514 public:
0515   Wildcard() : SExpr(COP_Wildcard) {}
0516   Wildcard(const Wildcard &) = default;
0517 
0518   static bool classof(const SExpr *E) { return E->opcode() == COP_Wildcard; }
0519 
0520   template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
0521     return Vs.reduceWildcard(*this);
0522   }
0523 
0524   template <class C>
0525   typename C::CType compare(const Wildcard* E, C& Cmp) const {
0526     return Cmp.trueResult();
0527   }
0528 };
0529 
0530 template <class T> class LiteralT;
0531 
0532 // Base class for literal values.
0533 class Literal : public SExpr {
0534 public:
0535   Literal(const Expr *C)
0536      : SExpr(COP_Literal), ValType(ValueType::getValueType<void>()), Cexpr(C) {}
0537   Literal(ValueType VT) : SExpr(COP_Literal), ValType(VT) {}
0538   Literal(const Literal &) = default;
0539 
0540   static bool classof(const SExpr *E) { return E->opcode() == COP_Literal; }
0541 
0542   // The clang expression for this literal.
0543   const Expr *clangExpr() const { return Cexpr; }
0544 
0545   ValueType valueType() const { return ValType; }
0546 
0547   template<class T> const LiteralT<T>& as() const {
0548     return *static_cast<const LiteralT<T>*>(this);
0549   }
0550   template<class T> LiteralT<T>& as() {
0551     return *static_cast<LiteralT<T>*>(this);
0552   }
0553 
0554   template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx);
0555 
0556   template <class C>
0557   typename C::CType compare(const Literal* E, C& Cmp) const {
0558     // TODO: defer actual comparison to LiteralT
0559     return Cmp.trueResult();
0560   }
0561 
0562 private:
0563   const ValueType ValType;
0564   const Expr *Cexpr = nullptr;
0565 };
0566 
0567 // Derived class for literal values, which stores the actual value.
0568 template<class T>
0569 class LiteralT : public Literal {
0570 public:
0571   LiteralT(T Dat) : Literal(ValueType::getValueType<T>()), Val(Dat) {}
0572   LiteralT(const LiteralT<T> &L) : Literal(L), Val(L.Val) {}
0573 
0574   // The copy assignment operator is defined as deleted pending further
0575   // motivation.
0576   LiteralT &operator=(const LiteralT<T> &) = delete;
0577 
0578   T value() const { return Val;}
0579   T& value() { return Val; }
0580 
0581 private:
0582   T Val;
0583 };
0584 
0585 template <class V>
0586 typename V::R_SExpr Literal::traverse(V &Vs, typename V::R_Ctx Ctx) {
0587   if (Cexpr)
0588     return Vs.reduceLiteral(*this);
0589 
0590   switch (ValType.Base) {
0591   case ValueType::BT_Void:
0592     break;
0593   case ValueType::BT_Bool:
0594     return Vs.reduceLiteralT(as<bool>());
0595   case ValueType::BT_Int: {
0596     switch (ValType.Size) {
0597     case ValueType::ST_8:
0598       if (ValType.Signed)
0599         return Vs.reduceLiteralT(as<int8_t>());
0600       else
0601         return Vs.reduceLiteralT(as<uint8_t>());
0602     case ValueType::ST_16:
0603       if (ValType.Signed)
0604         return Vs.reduceLiteralT(as<int16_t>());
0605       else
0606         return Vs.reduceLiteralT(as<uint16_t>());
0607     case ValueType::ST_32:
0608       if (ValType.Signed)
0609         return Vs.reduceLiteralT(as<int32_t>());
0610       else
0611         return Vs.reduceLiteralT(as<uint32_t>());
0612     case ValueType::ST_64:
0613       if (ValType.Signed)
0614         return Vs.reduceLiteralT(as<int64_t>());
0615       else
0616         return Vs.reduceLiteralT(as<uint64_t>());
0617     default:
0618       break;
0619     }
0620   }
0621   case ValueType::BT_Float: {
0622     switch (ValType.Size) {
0623     case ValueType::ST_32:
0624       return Vs.reduceLiteralT(as<float>());
0625     case ValueType::ST_64:
0626       return Vs.reduceLiteralT(as<double>());
0627     default:
0628       break;
0629     }
0630   }
0631   case ValueType::BT_String:
0632     return Vs.reduceLiteralT(as<StringRef>());
0633   case ValueType::BT_Pointer:
0634     return Vs.reduceLiteralT(as<void*>());
0635   case ValueType::BT_ValueRef:
0636     break;
0637   }
0638   return Vs.reduceLiteral(*this);
0639 }
0640 
0641 /// A Literal pointer to an object allocated in memory.
0642 /// At compile time, pointer literals are represented by symbolic names.
0643 class LiteralPtr : public SExpr {
0644 public:
0645   LiteralPtr(const ValueDecl *D) : SExpr(COP_LiteralPtr), Cvdecl(D) {}
0646   LiteralPtr(const LiteralPtr &) = default;
0647 
0648   static bool classof(const SExpr *E) { return E->opcode() == COP_LiteralPtr; }
0649 
0650   // The clang declaration for the value that this pointer points to.
0651   const ValueDecl *clangDecl() const { return Cvdecl; }
0652   void setClangDecl(const ValueDecl *VD) { Cvdecl = VD; }
0653 
0654   template <class V>
0655   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
0656     return Vs.reduceLiteralPtr(*this);
0657   }
0658 
0659   template <class C>
0660   typename C::CType compare(const LiteralPtr* E, C& Cmp) const {
0661     if (!Cvdecl || !E->Cvdecl)
0662       return Cmp.comparePointers(this, E);
0663     return Cmp.comparePointers(Cvdecl, E->Cvdecl);
0664   }
0665 
0666 private:
0667   const ValueDecl *Cvdecl;
0668 };
0669 
0670 /// A function -- a.k.a. lambda abstraction.
0671 /// Functions with multiple arguments are created by currying,
0672 /// e.g. (Function (x: Int) (Function (y: Int) (Code { return x + y })))
0673 class Function : public SExpr {
0674 public:
0675   Function(Variable *Vd, SExpr *Bd)
0676       : SExpr(COP_Function), VarDecl(Vd), Body(Bd) {
0677     Vd->setKind(Variable::VK_Fun);
0678   }
0679 
0680   Function(const Function &F, Variable *Vd, SExpr *Bd) // rewrite constructor
0681       : SExpr(F), VarDecl(Vd), Body(Bd) {
0682     Vd->setKind(Variable::VK_Fun);
0683   }
0684 
0685   static bool classof(const SExpr *E) { return E->opcode() == COP_Function; }
0686 
0687   Variable *variableDecl()  { return VarDecl; }
0688   const Variable *variableDecl() const { return VarDecl; }
0689 
0690   SExpr *body() { return Body; }
0691   const SExpr *body() const { return Body; }
0692 
0693   template <class V>
0694   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
0695     // This is a variable declaration, so traverse the definition.
0696     auto E0 = Vs.traverse(VarDecl->Definition, Vs.typeCtx(Ctx));
0697     // Tell the rewriter to enter the scope of the function.
0698     Variable *Nvd = Vs.enterScope(*VarDecl, E0);
0699     auto E1 = Vs.traverse(Body, Vs.declCtx(Ctx));
0700     Vs.exitScope(*VarDecl);
0701     return Vs.reduceFunction(*this, Nvd, E1);
0702   }
0703 
0704   template <class C>
0705   typename C::CType compare(const Function* E, C& Cmp) const {
0706     typename C::CType Ct =
0707       Cmp.compare(VarDecl->definition(), E->VarDecl->definition());
0708     if (Cmp.notTrue(Ct))
0709       return Ct;
0710     Cmp.enterScope(variableDecl(), E->variableDecl());
0711     Ct = Cmp.compare(body(), E->body());
0712     Cmp.leaveScope();
0713     return Ct;
0714   }
0715 
0716 private:
0717   Variable *VarDecl;
0718   SExpr* Body;
0719 };
0720 
0721 /// A self-applicable function.
0722 /// A self-applicable function can be applied to itself.  It's useful for
0723 /// implementing objects and late binding.
0724 class SFunction : public SExpr {
0725 public:
0726   SFunction(Variable *Vd, SExpr *B)
0727       : SExpr(COP_SFunction), VarDecl(Vd), Body(B) {
0728     assert(Vd->Definition == nullptr);
0729     Vd->setKind(Variable::VK_SFun);
0730     Vd->Definition = this;
0731   }
0732 
0733   SFunction(const SFunction &F, Variable *Vd, SExpr *B) // rewrite constructor
0734       : SExpr(F), VarDecl(Vd), Body(B) {
0735     assert(Vd->Definition == nullptr);
0736     Vd->setKind(Variable::VK_SFun);
0737     Vd->Definition = this;
0738   }
0739 
0740   static bool classof(const SExpr *E) { return E->opcode() == COP_SFunction; }
0741 
0742   Variable *variableDecl() { return VarDecl; }
0743   const Variable *variableDecl() const { return VarDecl; }
0744 
0745   SExpr *body() { return Body; }
0746   const SExpr *body() const { return Body; }
0747 
0748   template <class V>
0749   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
0750     // A self-variable points to the SFunction itself.
0751     // A rewrite must introduce the variable with a null definition, and update
0752     // it after 'this' has been rewritten.
0753     Variable *Nvd = Vs.enterScope(*VarDecl, nullptr);
0754     auto E1 = Vs.traverse(Body, Vs.declCtx(Ctx));
0755     Vs.exitScope(*VarDecl);
0756     // A rewrite operation will call SFun constructor to set Vvd->Definition.
0757     return Vs.reduceSFunction(*this, Nvd, E1);
0758   }
0759 
0760   template <class C>
0761   typename C::CType compare(const SFunction* E, C& Cmp) const {
0762     Cmp.enterScope(variableDecl(), E->variableDecl());
0763     typename C::CType Ct = Cmp.compare(body(), E->body());
0764     Cmp.leaveScope();
0765     return Ct;
0766   }
0767 
0768 private:
0769   Variable *VarDecl;
0770   SExpr* Body;
0771 };
0772 
0773 /// A block of code -- e.g. the body of a function.
0774 class Code : public SExpr {
0775 public:
0776   Code(SExpr *T, SExpr *B) : SExpr(COP_Code), ReturnType(T), Body(B) {}
0777   Code(const Code &C, SExpr *T, SExpr *B) // rewrite constructor
0778       : SExpr(C), ReturnType(T), Body(B) {}
0779 
0780   static bool classof(const SExpr *E) { return E->opcode() == COP_Code; }
0781 
0782   SExpr *returnType() { return ReturnType; }
0783   const SExpr *returnType() const { return ReturnType; }
0784 
0785   SExpr *body() { return Body; }
0786   const SExpr *body() const { return Body; }
0787 
0788   template <class V>
0789   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
0790     auto Nt = Vs.traverse(ReturnType, Vs.typeCtx(Ctx));
0791     auto Nb = Vs.traverse(Body,       Vs.lazyCtx(Ctx));
0792     return Vs.reduceCode(*this, Nt, Nb);
0793   }
0794 
0795   template <class C>
0796   typename C::CType compare(const Code* E, C& Cmp) const {
0797     typename C::CType Ct = Cmp.compare(returnType(), E->returnType());
0798     if (Cmp.notTrue(Ct))
0799       return Ct;
0800     return Cmp.compare(body(), E->body());
0801   }
0802 
0803 private:
0804   SExpr* ReturnType;
0805   SExpr* Body;
0806 };
0807 
0808 /// A typed, writable location in memory
0809 class Field : public SExpr {
0810 public:
0811   Field(SExpr *R, SExpr *B) : SExpr(COP_Field), Range(R), Body(B) {}
0812   Field(const Field &C, SExpr *R, SExpr *B) // rewrite constructor
0813       : SExpr(C), Range(R), Body(B) {}
0814 
0815   static bool classof(const SExpr *E) { return E->opcode() == COP_Field; }
0816 
0817   SExpr *range() { return Range; }
0818   const SExpr *range() const { return Range; }
0819 
0820   SExpr *body() { return Body; }
0821   const SExpr *body() const { return Body; }
0822 
0823   template <class V>
0824   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
0825     auto Nr = Vs.traverse(Range, Vs.typeCtx(Ctx));
0826     auto Nb = Vs.traverse(Body,  Vs.lazyCtx(Ctx));
0827     return Vs.reduceField(*this, Nr, Nb);
0828   }
0829 
0830   template <class C>
0831   typename C::CType compare(const Field* E, C& Cmp) const {
0832     typename C::CType Ct = Cmp.compare(range(), E->range());
0833     if (Cmp.notTrue(Ct))
0834       return Ct;
0835     return Cmp.compare(body(), E->body());
0836   }
0837 
0838 private:
0839   SExpr* Range;
0840   SExpr* Body;
0841 };
0842 
0843 /// Apply an argument to a function.
0844 /// Note that this does not actually call the function.  Functions are curried,
0845 /// so this returns a closure in which the first parameter has been applied.
0846 /// Once all parameters have been applied, Call can be used to invoke the
0847 /// function.
0848 class Apply : public SExpr {
0849 public:
0850   Apply(SExpr *F, SExpr *A) : SExpr(COP_Apply), Fun(F), Arg(A) {}
0851   Apply(const Apply &A, SExpr *F, SExpr *Ar)  // rewrite constructor
0852       : SExpr(A), Fun(F), Arg(Ar) {}
0853 
0854   static bool classof(const SExpr *E) { return E->opcode() == COP_Apply; }
0855 
0856   SExpr *fun() { return Fun; }
0857   const SExpr *fun() const { return Fun; }
0858 
0859   SExpr *arg() { return Arg; }
0860   const SExpr *arg() const { return Arg; }
0861 
0862   template <class V>
0863   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
0864     auto Nf = Vs.traverse(Fun, Vs.subExprCtx(Ctx));
0865     auto Na = Vs.traverse(Arg, Vs.subExprCtx(Ctx));
0866     return Vs.reduceApply(*this, Nf, Na);
0867   }
0868 
0869   template <class C>
0870   typename C::CType compare(const Apply* E, C& Cmp) const {
0871     typename C::CType Ct = Cmp.compare(fun(), E->fun());
0872     if (Cmp.notTrue(Ct))
0873       return Ct;
0874     return Cmp.compare(arg(), E->arg());
0875   }
0876 
0877 private:
0878   SExpr* Fun;
0879   SExpr* Arg;
0880 };
0881 
0882 /// Apply a self-argument to a self-applicable function.
0883 class SApply : public SExpr {
0884 public:
0885   SApply(SExpr *Sf, SExpr *A = nullptr) : SExpr(COP_SApply), Sfun(Sf), Arg(A) {}
0886   SApply(SApply &A, SExpr *Sf, SExpr *Ar = nullptr) // rewrite constructor
0887       : SExpr(A), Sfun(Sf), Arg(Ar) {}
0888 
0889   static bool classof(const SExpr *E) { return E->opcode() == COP_SApply; }
0890 
0891   SExpr *sfun() { return Sfun; }
0892   const SExpr *sfun() const { return Sfun; }
0893 
0894   SExpr *arg() { return Arg ? Arg : Sfun; }
0895   const SExpr *arg() const { return Arg ? Arg : Sfun; }
0896 
0897   bool isDelegation() const { return Arg != nullptr; }
0898 
0899   template <class V>
0900   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
0901     auto Nf = Vs.traverse(Sfun, Vs.subExprCtx(Ctx));
0902     typename V::R_SExpr Na = Arg ? Vs.traverse(Arg, Vs.subExprCtx(Ctx))
0903                                        : nullptr;
0904     return Vs.reduceSApply(*this, Nf, Na);
0905   }
0906 
0907   template <class C>
0908   typename C::CType compare(const SApply* E, C& Cmp) const {
0909     typename C::CType Ct = Cmp.compare(sfun(), E->sfun());
0910     if (Cmp.notTrue(Ct) || (!arg() && !E->arg()))
0911       return Ct;
0912     return Cmp.compare(arg(), E->arg());
0913   }
0914 
0915 private:
0916   SExpr* Sfun;
0917   SExpr* Arg;
0918 };
0919 
0920 /// Project a named slot from a C++ struct or class.
0921 class Project : public SExpr {
0922 public:
0923   Project(SExpr *R, const ValueDecl *Cvd)
0924       : SExpr(COP_Project), Rec(R), Cvdecl(Cvd) {
0925     assert(Cvd && "ValueDecl must not be null");
0926   }
0927 
0928   static bool classof(const SExpr *E) { return E->opcode() == COP_Project; }
0929 
0930   SExpr *record() { return Rec; }
0931   const SExpr *record() const { return Rec; }
0932 
0933   const ValueDecl *clangDecl() const { return Cvdecl; }
0934 
0935   bool isArrow() const { return (Flags & 0x01) != 0; }
0936 
0937   void setArrow(bool b) {
0938     if (b) Flags |= 0x01;
0939     else Flags &= 0xFFFE;
0940   }
0941 
0942   StringRef slotName() const {
0943     if (Cvdecl->getDeclName().isIdentifier())
0944       return Cvdecl->getName();
0945     if (!SlotName) {
0946       SlotName = "";
0947       llvm::raw_string_ostream OS(*SlotName);
0948       Cvdecl->printName(OS);
0949     }
0950     return *SlotName;
0951   }
0952 
0953   template <class V>
0954   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
0955     auto Nr = Vs.traverse(Rec, Vs.subExprCtx(Ctx));
0956     return Vs.reduceProject(*this, Nr);
0957   }
0958 
0959   template <class C>
0960   typename C::CType compare(const Project* E, C& Cmp) const {
0961     typename C::CType Ct = Cmp.compare(record(), E->record());
0962     if (Cmp.notTrue(Ct))
0963       return Ct;
0964     return Cmp.comparePointers(Cvdecl, E->Cvdecl);
0965   }
0966 
0967 private:
0968   SExpr* Rec;
0969   mutable std::optional<std::string> SlotName;
0970   const ValueDecl *Cvdecl;
0971 };
0972 
0973 /// Call a function (after all arguments have been applied).
0974 class Call : public SExpr {
0975 public:
0976   Call(SExpr *T, const CallExpr *Ce = nullptr)
0977       : SExpr(COP_Call), Target(T), Cexpr(Ce) {}
0978   Call(const Call &C, SExpr *T) : SExpr(C), Target(T), Cexpr(C.Cexpr) {}
0979 
0980   static bool classof(const SExpr *E) { return E->opcode() == COP_Call; }
0981 
0982   SExpr *target() { return Target; }
0983   const SExpr *target() const { return Target; }
0984 
0985   const CallExpr *clangCallExpr() const { return Cexpr; }
0986 
0987   template <class V>
0988   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
0989     auto Nt = Vs.traverse(Target, Vs.subExprCtx(Ctx));
0990     return Vs.reduceCall(*this, Nt);
0991   }
0992 
0993   template <class C>
0994   typename C::CType compare(const Call* E, C& Cmp) const {
0995     return Cmp.compare(target(), E->target());
0996   }
0997 
0998 private:
0999   SExpr* Target;
1000   const CallExpr *Cexpr;
1001 };
1002 
1003 /// Allocate memory for a new value on the heap or stack.
1004 class Alloc : public SExpr {
1005 public:
1006   enum AllocKind {
1007     AK_Stack,
1008     AK_Heap
1009   };
1010 
1011   Alloc(SExpr *D, AllocKind K) : SExpr(COP_Alloc), Dtype(D) { Flags = K; }
1012   Alloc(const Alloc &A, SExpr *Dt) : SExpr(A), Dtype(Dt) { Flags = A.kind(); }
1013 
1014   static bool classof(const SExpr *E) { return E->opcode() == COP_Call; }
1015 
1016   AllocKind kind() const { return static_cast<AllocKind>(Flags); }
1017 
1018   SExpr *dataType() { return Dtype; }
1019   const SExpr *dataType() const { return Dtype; }
1020 
1021   template <class V>
1022   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1023     auto Nd = Vs.traverse(Dtype, Vs.declCtx(Ctx));
1024     return Vs.reduceAlloc(*this, Nd);
1025   }
1026 
1027   template <class C>
1028   typename C::CType compare(const Alloc* E, C& Cmp) const {
1029     typename C::CType Ct = Cmp.compareIntegers(kind(), E->kind());
1030     if (Cmp.notTrue(Ct))
1031       return Ct;
1032     return Cmp.compare(dataType(), E->dataType());
1033   }
1034 
1035 private:
1036   SExpr* Dtype;
1037 };
1038 
1039 /// Load a value from memory.
1040 class Load : public SExpr {
1041 public:
1042   Load(SExpr *P) : SExpr(COP_Load), Ptr(P) {}
1043   Load(const Load &L, SExpr *P) : SExpr(L), Ptr(P) {}
1044 
1045   static bool classof(const SExpr *E) { return E->opcode() == COP_Load; }
1046 
1047   SExpr *pointer() { return Ptr; }
1048   const SExpr *pointer() const { return Ptr; }
1049 
1050   template <class V>
1051   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1052     auto Np = Vs.traverse(Ptr, Vs.subExprCtx(Ctx));
1053     return Vs.reduceLoad(*this, Np);
1054   }
1055 
1056   template <class C>
1057   typename C::CType compare(const Load* E, C& Cmp) const {
1058     return Cmp.compare(pointer(), E->pointer());
1059   }
1060 
1061 private:
1062   SExpr* Ptr;
1063 };
1064 
1065 /// Store a value to memory.
1066 /// The destination is a pointer to a field, the source is the value to store.
1067 class Store : public SExpr {
1068 public:
1069   Store(SExpr *P, SExpr *V) : SExpr(COP_Store), Dest(P), Source(V) {}
1070   Store(const Store &S, SExpr *P, SExpr *V) : SExpr(S), Dest(P), Source(V) {}
1071 
1072   static bool classof(const SExpr *E) { return E->opcode() == COP_Store; }
1073 
1074   SExpr *destination() { return Dest; }  // Address to store to
1075   const SExpr *destination() const { return Dest; }
1076 
1077   SExpr *source() { return Source; }     // Value to store
1078   const SExpr *source() const { return Source; }
1079 
1080   template <class V>
1081   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1082     auto Np = Vs.traverse(Dest,   Vs.subExprCtx(Ctx));
1083     auto Nv = Vs.traverse(Source, Vs.subExprCtx(Ctx));
1084     return Vs.reduceStore(*this, Np, Nv);
1085   }
1086 
1087   template <class C>
1088   typename C::CType compare(const Store* E, C& Cmp) const {
1089     typename C::CType Ct = Cmp.compare(destination(), E->destination());
1090     if (Cmp.notTrue(Ct))
1091       return Ct;
1092     return Cmp.compare(source(), E->source());
1093   }
1094 
1095 private:
1096   SExpr* Dest;
1097   SExpr* Source;
1098 };
1099 
1100 /// If p is a reference to an array, then p[i] is a reference to the i'th
1101 /// element of the array.
1102 class ArrayIndex : public SExpr {
1103 public:
1104   ArrayIndex(SExpr *A, SExpr *N) : SExpr(COP_ArrayIndex), Array(A), Index(N) {}
1105   ArrayIndex(const ArrayIndex &E, SExpr *A, SExpr *N)
1106       : SExpr(E), Array(A), Index(N) {}
1107 
1108   static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayIndex; }
1109 
1110   SExpr *array() { return Array; }
1111   const SExpr *array() const { return Array; }
1112 
1113   SExpr *index() { return Index; }
1114   const SExpr *index() const { return Index; }
1115 
1116   template <class V>
1117   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1118     auto Na = Vs.traverse(Array, Vs.subExprCtx(Ctx));
1119     auto Ni = Vs.traverse(Index, Vs.subExprCtx(Ctx));
1120     return Vs.reduceArrayIndex(*this, Na, Ni);
1121   }
1122 
1123   template <class C>
1124   typename C::CType compare(const ArrayIndex* E, C& Cmp) const {
1125     typename C::CType Ct = Cmp.compare(array(), E->array());
1126     if (Cmp.notTrue(Ct))
1127       return Ct;
1128     return Cmp.compare(index(), E->index());
1129   }
1130 
1131 private:
1132   SExpr* Array;
1133   SExpr* Index;
1134 };
1135 
1136 /// Pointer arithmetic, restricted to arrays only.
1137 /// If p is a reference to an array, then p + n, where n is an integer, is
1138 /// a reference to a subarray.
1139 class ArrayAdd : public SExpr {
1140 public:
1141   ArrayAdd(SExpr *A, SExpr *N) : SExpr(COP_ArrayAdd), Array(A), Index(N) {}
1142   ArrayAdd(const ArrayAdd &E, SExpr *A, SExpr *N)
1143       : SExpr(E), Array(A), Index(N) {}
1144 
1145   static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayAdd; }
1146 
1147   SExpr *array() { return Array; }
1148   const SExpr *array() const { return Array; }
1149 
1150   SExpr *index() { return Index; }
1151   const SExpr *index() const { return Index; }
1152 
1153   template <class V>
1154   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1155     auto Na = Vs.traverse(Array, Vs.subExprCtx(Ctx));
1156     auto Ni = Vs.traverse(Index, Vs.subExprCtx(Ctx));
1157     return Vs.reduceArrayAdd(*this, Na, Ni);
1158   }
1159 
1160   template <class C>
1161   typename C::CType compare(const ArrayAdd* E, C& Cmp) const {
1162     typename C::CType Ct = Cmp.compare(array(), E->array());
1163     if (Cmp.notTrue(Ct))
1164       return Ct;
1165     return Cmp.compare(index(), E->index());
1166   }
1167 
1168 private:
1169   SExpr* Array;
1170   SExpr* Index;
1171 };
1172 
1173 /// Simple arithmetic unary operations, e.g. negate and not.
1174 /// These operations have no side-effects.
1175 class UnaryOp : public SExpr {
1176 public:
1177   UnaryOp(TIL_UnaryOpcode Op, SExpr *E) : SExpr(COP_UnaryOp), Expr0(E) {
1178     Flags = Op;
1179   }
1180 
1181   UnaryOp(const UnaryOp &U, SExpr *E) : SExpr(U), Expr0(E) { Flags = U.Flags; }
1182 
1183   static bool classof(const SExpr *E) { return E->opcode() == COP_UnaryOp; }
1184 
1185   TIL_UnaryOpcode unaryOpcode() const {
1186     return static_cast<TIL_UnaryOpcode>(Flags);
1187   }
1188 
1189   SExpr *expr() { return Expr0; }
1190   const SExpr *expr() const { return Expr0; }
1191 
1192   template <class V>
1193   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1194     auto Ne = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
1195     return Vs.reduceUnaryOp(*this, Ne);
1196   }
1197 
1198   template <class C>
1199   typename C::CType compare(const UnaryOp* E, C& Cmp) const {
1200     typename C::CType Ct =
1201       Cmp.compareIntegers(unaryOpcode(), E->unaryOpcode());
1202     if (Cmp.notTrue(Ct))
1203       return Ct;
1204     return Cmp.compare(expr(), E->expr());
1205   }
1206 
1207 private:
1208   SExpr* Expr0;
1209 };
1210 
1211 /// Simple arithmetic binary operations, e.g. +, -, etc.
1212 /// These operations have no side effects.
1213 class BinaryOp : public SExpr {
1214 public:
1215   BinaryOp(TIL_BinaryOpcode Op, SExpr *E0, SExpr *E1)
1216       : SExpr(COP_BinaryOp), Expr0(E0), Expr1(E1) {
1217     Flags = Op;
1218   }
1219 
1220   BinaryOp(const BinaryOp &B, SExpr *E0, SExpr *E1)
1221       : SExpr(B), Expr0(E0), Expr1(E1) {
1222     Flags = B.Flags;
1223   }
1224 
1225   static bool classof(const SExpr *E) { return E->opcode() == COP_BinaryOp; }
1226 
1227   TIL_BinaryOpcode binaryOpcode() const {
1228     return static_cast<TIL_BinaryOpcode>(Flags);
1229   }
1230 
1231   SExpr *expr0() { return Expr0; }
1232   const SExpr *expr0() const { return Expr0; }
1233 
1234   SExpr *expr1() { return Expr1; }
1235   const SExpr *expr1() const { return Expr1; }
1236 
1237   template <class V>
1238   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1239     auto Ne0 = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
1240     auto Ne1 = Vs.traverse(Expr1, Vs.subExprCtx(Ctx));
1241     return Vs.reduceBinaryOp(*this, Ne0, Ne1);
1242   }
1243 
1244   template <class C>
1245   typename C::CType compare(const BinaryOp* E, C& Cmp) const {
1246     typename C::CType Ct =
1247       Cmp.compareIntegers(binaryOpcode(), E->binaryOpcode());
1248     if (Cmp.notTrue(Ct))
1249       return Ct;
1250     Ct = Cmp.compare(expr0(), E->expr0());
1251     if (Cmp.notTrue(Ct))
1252       return Ct;
1253     return Cmp.compare(expr1(), E->expr1());
1254   }
1255 
1256 private:
1257   SExpr* Expr0;
1258   SExpr* Expr1;
1259 };
1260 
1261 /// Cast expressions.
1262 /// Cast expressions are essentially unary operations, but we treat them
1263 /// as a distinct AST node because they only change the type of the result.
1264 class Cast : public SExpr {
1265 public:
1266   Cast(TIL_CastOpcode Op, SExpr *E) : SExpr(COP_Cast), Expr0(E) { Flags = Op; }
1267   Cast(const Cast &C, SExpr *E) : SExpr(C), Expr0(E) { Flags = C.Flags; }
1268 
1269   static bool classof(const SExpr *E) { return E->opcode() == COP_Cast; }
1270 
1271   TIL_CastOpcode castOpcode() const {
1272     return static_cast<TIL_CastOpcode>(Flags);
1273   }
1274 
1275   SExpr *expr() { return Expr0; }
1276   const SExpr *expr() const { return Expr0; }
1277 
1278   template <class V>
1279   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1280     auto Ne = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
1281     return Vs.reduceCast(*this, Ne);
1282   }
1283 
1284   template <class C>
1285   typename C::CType compare(const Cast* E, C& Cmp) const {
1286     typename C::CType Ct =
1287       Cmp.compareIntegers(castOpcode(), E->castOpcode());
1288     if (Cmp.notTrue(Ct))
1289       return Ct;
1290     return Cmp.compare(expr(), E->expr());
1291   }
1292 
1293 private:
1294   SExpr* Expr0;
1295 };
1296 
1297 class SCFG;
1298 
1299 /// Phi Node, for code in SSA form.
1300 /// Each Phi node has an array of possible values that it can take,
1301 /// depending on where control flow comes from.
1302 class Phi : public SExpr {
1303 public:
1304   using ValArray = SimpleArray<SExpr *>;
1305 
1306   // In minimal SSA form, all Phi nodes are MultiVal.
1307   // During conversion to SSA, incomplete Phi nodes may be introduced, which
1308   // are later determined to be SingleVal, and are thus redundant.
1309   enum Status {
1310     PH_MultiVal = 0, // Phi node has multiple distinct values.  (Normal)
1311     PH_SingleVal,    // Phi node has one distinct value, and can be eliminated
1312     PH_Incomplete    // Phi node is incomplete
1313   };
1314 
1315   Phi() : SExpr(COP_Phi) {}
1316   Phi(MemRegionRef A, unsigned Nvals) : SExpr(COP_Phi), Values(A, Nvals)  {}
1317   Phi(const Phi &P, ValArray &&Vs) : SExpr(P), Values(std::move(Vs)) {}
1318 
1319   static bool classof(const SExpr *E) { return E->opcode() == COP_Phi; }
1320 
1321   const ValArray &values() const { return Values; }
1322   ValArray &values() { return Values; }
1323 
1324   Status status() const { return static_cast<Status>(Flags); }
1325   void setStatus(Status s) { Flags = s; }
1326 
1327   /// Return the clang declaration of the variable for this Phi node, if any.
1328   const ValueDecl *clangDecl() const { return Cvdecl; }
1329 
1330   /// Set the clang variable associated with this Phi node.
1331   void setClangDecl(const ValueDecl *Cvd) { Cvdecl = Cvd; }
1332 
1333   template <class V>
1334   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1335     typename V::template Container<typename V::R_SExpr>
1336       Nvs(Vs, Values.size());
1337 
1338     for (const auto *Val : Values)
1339       Nvs.push_back( Vs.traverse(Val, Vs.subExprCtx(Ctx)) );
1340     return Vs.reducePhi(*this, Nvs);
1341   }
1342 
1343   template <class C>
1344   typename C::CType compare(const Phi *E, C &Cmp) const {
1345     // TODO: implement CFG comparisons
1346     return Cmp.comparePointers(this, E);
1347   }
1348 
1349 private:
1350   ValArray Values;
1351   const ValueDecl* Cvdecl = nullptr;
1352 };
1353 
1354 /// Base class for basic block terminators:  Branch, Goto, and Return.
1355 class Terminator : public SExpr {
1356 protected:
1357   Terminator(TIL_Opcode Op) : SExpr(Op) {}
1358   Terminator(const SExpr &E) : SExpr(E) {}
1359 
1360 public:
1361   static bool classof(const SExpr *E) {
1362     return E->opcode() >= COP_Goto && E->opcode() <= COP_Return;
1363   }
1364 
1365   /// Return the list of basic blocks that this terminator can branch to.
1366   ArrayRef<BasicBlock *> successors() const;
1367 };
1368 
1369 /// Jump to another basic block.
1370 /// A goto instruction is essentially a tail-recursive call into another
1371 /// block.  In addition to the block pointer, it specifies an index into the
1372 /// phi nodes of that block.  The index can be used to retrieve the "arguments"
1373 /// of the call.
1374 class Goto : public Terminator {
1375 public:
1376   Goto(BasicBlock *B, unsigned I)
1377       : Terminator(COP_Goto), TargetBlock(B), Index(I) {}
1378   Goto(const Goto &G, BasicBlock *B, unsigned I)
1379       : Terminator(COP_Goto), TargetBlock(B), Index(I) {}
1380 
1381   static bool classof(const SExpr *E) { return E->opcode() == COP_Goto; }
1382 
1383   const BasicBlock *targetBlock() const { return TargetBlock; }
1384   BasicBlock *targetBlock() { return TargetBlock; }
1385 
1386   /// Returns the index into the
1387   unsigned index() const { return Index; }
1388 
1389   /// Return the list of basic blocks that this terminator can branch to.
1390   ArrayRef<BasicBlock *> successors() const { return TargetBlock; }
1391 
1392   template <class V>
1393   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1394     BasicBlock *Ntb = Vs.reduceBasicBlockRef(TargetBlock);
1395     return Vs.reduceGoto(*this, Ntb);
1396   }
1397 
1398   template <class C>
1399   typename C::CType compare(const Goto *E, C &Cmp) const {
1400     // TODO: implement CFG comparisons
1401     return Cmp.comparePointers(this, E);
1402   }
1403 
1404 private:
1405   BasicBlock *TargetBlock;
1406   unsigned Index;
1407 };
1408 
1409 /// A conditional branch to two other blocks.
1410 /// Note that unlike Goto, Branch does not have an index.  The target blocks
1411 /// must be child-blocks, and cannot have Phi nodes.
1412 class Branch : public Terminator {
1413 public:
1414   Branch(SExpr *C, BasicBlock *T, BasicBlock *E)
1415       : Terminator(COP_Branch), Condition(C) {
1416     Branches[0] = T;
1417     Branches[1] = E;
1418   }
1419 
1420   Branch(const Branch &Br, SExpr *C, BasicBlock *T, BasicBlock *E)
1421       : Terminator(Br), Condition(C) {
1422     Branches[0] = T;
1423     Branches[1] = E;
1424   }
1425 
1426   static bool classof(const SExpr *E) { return E->opcode() == COP_Branch; }
1427 
1428   const SExpr *condition() const { return Condition; }
1429   SExpr *condition() { return Condition; }
1430 
1431   const BasicBlock *thenBlock() const { return Branches[0]; }
1432   BasicBlock *thenBlock() { return Branches[0]; }
1433 
1434   const BasicBlock *elseBlock() const { return Branches[1]; }
1435   BasicBlock *elseBlock() { return Branches[1]; }
1436 
1437   /// Return the list of basic blocks that this terminator can branch to.
1438   ArrayRef<BasicBlock *> successors() const { return llvm::ArrayRef(Branches); }
1439 
1440   template <class V>
1441   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1442     auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx));
1443     BasicBlock *Ntb = Vs.reduceBasicBlockRef(Branches[0]);
1444     BasicBlock *Nte = Vs.reduceBasicBlockRef(Branches[1]);
1445     return Vs.reduceBranch(*this, Nc, Ntb, Nte);
1446   }
1447 
1448   template <class C>
1449   typename C::CType compare(const Branch *E, C &Cmp) const {
1450     // TODO: implement CFG comparisons
1451     return Cmp.comparePointers(this, E);
1452   }
1453 
1454 private:
1455   SExpr *Condition;
1456   BasicBlock *Branches[2];
1457 };
1458 
1459 /// Return from the enclosing function, passing the return value to the caller.
1460 /// Only the exit block should end with a return statement.
1461 class Return : public Terminator {
1462 public:
1463   Return(SExpr* Rval) : Terminator(COP_Return), Retval(Rval) {}
1464   Return(const Return &R, SExpr* Rval) : Terminator(R), Retval(Rval) {}
1465 
1466   static bool classof(const SExpr *E) { return E->opcode() == COP_Return; }
1467 
1468   /// Return an empty list.
1469   ArrayRef<BasicBlock *> successors() const { return {}; }
1470 
1471   SExpr *returnValue() { return Retval; }
1472   const SExpr *returnValue() const { return Retval; }
1473 
1474   template <class V>
1475   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1476     auto Ne = Vs.traverse(Retval, Vs.subExprCtx(Ctx));
1477     return Vs.reduceReturn(*this, Ne);
1478   }
1479 
1480   template <class C>
1481   typename C::CType compare(const Return *E, C &Cmp) const {
1482     return Cmp.compare(Retval, E->Retval);
1483   }
1484 
1485 private:
1486   SExpr* Retval;
1487 };
1488 
1489 inline ArrayRef<BasicBlock *> Terminator::successors() const {
1490   switch (opcode()) {
1491     case COP_Goto:   return cast<Goto>(this)->successors();
1492     case COP_Branch: return cast<Branch>(this)->successors();
1493     case COP_Return: return cast<Return>(this)->successors();
1494     default:
1495       return {};
1496   }
1497 }
1498 
1499 /// A basic block is part of an SCFG.  It can be treated as a function in
1500 /// continuation passing style.  A block consists of a sequence of phi nodes,
1501 /// which are "arguments" to the function, followed by a sequence of
1502 /// instructions.  It ends with a Terminator, which is a Branch or Goto to
1503 /// another basic block in the same SCFG.
1504 class BasicBlock : public SExpr {
1505 public:
1506   using InstrArray = SimpleArray<SExpr *>;
1507   using BlockArray = SimpleArray<BasicBlock *>;
1508 
1509   // TopologyNodes are used to overlay tree structures on top of the CFG,
1510   // such as dominator and postdominator trees.  Each block is assigned an
1511   // ID in the tree according to a depth-first search.  Tree traversals are
1512   // always up, towards the parents.
1513   struct TopologyNode {
1514     int NodeID = 0;
1515 
1516     // Includes this node, so must be > 1.
1517     int SizeOfSubTree = 0;
1518 
1519     // Pointer to parent.
1520     BasicBlock *Parent = nullptr;
1521 
1522     TopologyNode() = default;
1523 
1524     bool isParentOf(const TopologyNode& OtherNode) {
1525       return OtherNode.NodeID > NodeID &&
1526              OtherNode.NodeID < NodeID + SizeOfSubTree;
1527     }
1528 
1529     bool isParentOfOrEqual(const TopologyNode& OtherNode) {
1530       return OtherNode.NodeID >= NodeID &&
1531              OtherNode.NodeID < NodeID + SizeOfSubTree;
1532     }
1533   };
1534 
1535   explicit BasicBlock(MemRegionRef A)
1536       : SExpr(COP_BasicBlock), Arena(A), BlockID(0), Visited(false) {}
1537   BasicBlock(BasicBlock &B, MemRegionRef A, InstrArray &&As, InstrArray &&Is,
1538              Terminator *T)
1539       : SExpr(COP_BasicBlock), Arena(A), BlockID(0), Visited(false),
1540         Args(std::move(As)), Instrs(std::move(Is)), TermInstr(T) {}
1541 
1542   static bool classof(const SExpr *E) { return E->opcode() == COP_BasicBlock; }
1543 
1544   /// Returns the block ID.  Every block has a unique ID in the CFG.
1545   int blockID() const { return BlockID; }
1546 
1547   /// Returns the number of predecessors.
1548   size_t numPredecessors() const { return Predecessors.size(); }
1549   size_t numSuccessors() const { return successors().size(); }
1550 
1551   const SCFG* cfg() const { return CFGPtr; }
1552   SCFG* cfg() { return CFGPtr; }
1553 
1554   const BasicBlock *parent() const { return DominatorNode.Parent; }
1555   BasicBlock *parent() { return DominatorNode.Parent; }
1556 
1557   const InstrArray &arguments() const { return Args; }
1558   InstrArray &arguments() { return Args; }
1559 
1560   InstrArray &instructions() { return Instrs; }
1561   const InstrArray &instructions() const { return Instrs; }
1562 
1563   /// Returns a list of predecessors.
1564   /// The order of predecessors in the list is important; each phi node has
1565   /// exactly one argument for each precessor, in the same order.
1566   BlockArray &predecessors() { return Predecessors; }
1567   const BlockArray &predecessors() const { return Predecessors; }
1568 
1569   ArrayRef<BasicBlock*> successors() { return TermInstr->successors(); }
1570   ArrayRef<BasicBlock*> successors() const { return TermInstr->successors(); }
1571 
1572   const Terminator *terminator() const { return TermInstr; }
1573   Terminator *terminator() { return TermInstr; }
1574 
1575   void setTerminator(Terminator *E) { TermInstr = E; }
1576 
1577   bool Dominates(const BasicBlock &Other) {
1578     return DominatorNode.isParentOfOrEqual(Other.DominatorNode);
1579   }
1580 
1581   bool PostDominates(const BasicBlock &Other) {
1582     return PostDominatorNode.isParentOfOrEqual(Other.PostDominatorNode);
1583   }
1584 
1585   /// Add a new argument.
1586   void addArgument(Phi *V) {
1587     Args.reserveCheck(1, Arena);
1588     Args.push_back(V);
1589   }
1590 
1591   /// Add a new instruction.
1592   void addInstruction(SExpr *V) {
1593     Instrs.reserveCheck(1, Arena);
1594     Instrs.push_back(V);
1595   }
1596 
1597   // Add a new predecessor, and return the phi-node index for it.
1598   // Will add an argument to all phi-nodes, initialized to nullptr.
1599   unsigned addPredecessor(BasicBlock *Pred);
1600 
1601   // Reserve space for Nargs arguments.
1602   void reserveArguments(unsigned Nargs)   { Args.reserve(Nargs, Arena); }
1603 
1604   // Reserve space for Nins instructions.
1605   void reserveInstructions(unsigned Nins) { Instrs.reserve(Nins, Arena); }
1606 
1607   // Reserve space for NumPreds predecessors, including space in phi nodes.
1608   void reservePredecessors(unsigned NumPreds);
1609 
1610   /// Return the index of BB, or Predecessors.size if BB is not a predecessor.
1611   unsigned findPredecessorIndex(const BasicBlock *BB) const {
1612     auto I = llvm::find(Predecessors, BB);
1613     return std::distance(Predecessors.cbegin(), I);
1614   }
1615 
1616   template <class V>
1617   typename V::R_BasicBlock traverse(V &Vs, typename V::R_Ctx Ctx) {
1618     typename V::template Container<SExpr*> Nas(Vs, Args.size());
1619     typename V::template Container<SExpr*> Nis(Vs, Instrs.size());
1620 
1621     // Entering the basic block should do any scope initialization.
1622     Vs.enterBasicBlock(*this);
1623 
1624     for (const auto *E : Args) {
1625       auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
1626       Nas.push_back(Ne);
1627     }
1628     for (const auto *E : Instrs) {
1629       auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
1630       Nis.push_back(Ne);
1631     }
1632     auto Nt = Vs.traverse(TermInstr, Ctx);
1633 
1634     // Exiting the basic block should handle any scope cleanup.
1635     Vs.exitBasicBlock(*this);
1636 
1637     return Vs.reduceBasicBlock(*this, Nas, Nis, Nt);
1638   }
1639 
1640   template <class C>
1641   typename C::CType compare(const BasicBlock *E, C &Cmp) const {
1642     // TODO: implement CFG comparisons
1643     return Cmp.comparePointers(this, E);
1644   }
1645 
1646 private:
1647   friend class SCFG;
1648 
1649   // assign unique ids to all instructions
1650   unsigned renumberInstrs(unsigned id);
1651 
1652   unsigned topologicalSort(SimpleArray<BasicBlock *> &Blocks, unsigned ID);
1653   unsigned topologicalFinalSort(SimpleArray<BasicBlock *> &Blocks, unsigned ID);
1654   void computeDominator();
1655   void computePostDominator();
1656 
1657   // The arena used to allocate this block.
1658   MemRegionRef Arena;
1659 
1660   // The CFG that contains this block.
1661   SCFG *CFGPtr = nullptr;
1662 
1663   // Unique ID for this BB in the containing CFG. IDs are in topological order.
1664   unsigned BlockID : 31;
1665 
1666   // Bit to determine if a block has been visited during a traversal.
1667   bool Visited : 1;
1668 
1669   // Predecessor blocks in the CFG.
1670   BlockArray Predecessors;
1671 
1672   // Phi nodes. One argument per predecessor.
1673   InstrArray Args;
1674 
1675   // Instructions.
1676   InstrArray Instrs;
1677 
1678   // Terminating instruction.
1679   Terminator *TermInstr = nullptr;
1680 
1681   // The dominator tree.
1682   TopologyNode DominatorNode;
1683 
1684   // The post-dominator tree.
1685   TopologyNode PostDominatorNode;
1686 };
1687 
1688 /// An SCFG is a control-flow graph.  It consists of a set of basic blocks,
1689 /// each of which terminates in a branch to another basic block.  There is one
1690 /// entry point, and one exit point.
1691 class SCFG : public SExpr {
1692 public:
1693   using BlockArray = SimpleArray<BasicBlock *>;
1694   using iterator = BlockArray::iterator;
1695   using const_iterator = BlockArray::const_iterator;
1696 
1697   SCFG(MemRegionRef A, unsigned Nblocks)
1698       : SExpr(COP_SCFG), Arena(A), Blocks(A, Nblocks) {
1699     Entry = new (A) BasicBlock(A);
1700     Exit  = new (A) BasicBlock(A);
1701     auto *V = new (A) Phi();
1702     Exit->addArgument(V);
1703     Exit->setTerminator(new (A) Return(V));
1704     add(Entry);
1705     add(Exit);
1706   }
1707 
1708   SCFG(const SCFG &Cfg, BlockArray &&Ba) // steals memory from Ba
1709       : SExpr(COP_SCFG), Arena(Cfg.Arena), Blocks(std::move(Ba)) {
1710     // TODO: set entry and exit!
1711   }
1712 
1713   static bool classof(const SExpr *E) { return E->opcode() == COP_SCFG; }
1714 
1715   /// Return true if this CFG is valid.
1716   bool valid() const { return Entry && Exit && Blocks.size() > 0; }
1717 
1718   /// Return true if this CFG has been normalized.
1719   /// After normalization, blocks are in topological order, and block and
1720   /// instruction IDs have been assigned.
1721   bool normal() const { return Normal; }
1722 
1723   iterator begin() { return Blocks.begin(); }
1724   iterator end() { return Blocks.end(); }
1725 
1726   const_iterator begin() const { return cbegin(); }
1727   const_iterator end() const { return cend(); }
1728 
1729   const_iterator cbegin() const { return Blocks.cbegin(); }
1730   const_iterator cend() const { return Blocks.cend(); }
1731 
1732   const BasicBlock *entry() const { return Entry; }
1733   BasicBlock *entry() { return Entry; }
1734   const BasicBlock *exit() const { return Exit; }
1735   BasicBlock *exit() { return Exit; }
1736 
1737   /// Return the number of blocks in the CFG.
1738   /// Block::blockID() will return a number less than numBlocks();
1739   size_t numBlocks() const { return Blocks.size(); }
1740 
1741   /// Return the total number of instructions in the CFG.
1742   /// This is useful for building instruction side-tables;
1743   /// A call to SExpr::id() will return a number less than numInstructions().
1744   unsigned numInstructions() { return NumInstructions; }
1745 
1746   inline void add(BasicBlock *BB) {
1747     assert(BB->CFGPtr == nullptr);
1748     BB->CFGPtr = this;
1749     Blocks.reserveCheck(1, Arena);
1750     Blocks.push_back(BB);
1751   }
1752 
1753   void setEntry(BasicBlock *BB) { Entry = BB; }
1754   void setExit(BasicBlock *BB)  { Exit = BB;  }
1755 
1756   void computeNormalForm();
1757 
1758   template <class V>
1759   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1760     Vs.enterCFG(*this);
1761     typename V::template Container<BasicBlock *> Bbs(Vs, Blocks.size());
1762 
1763     for (const auto *B : Blocks) {
1764       Bbs.push_back( B->traverse(Vs, Vs.subExprCtx(Ctx)) );
1765     }
1766     Vs.exitCFG(*this);
1767     return Vs.reduceSCFG(*this, Bbs);
1768   }
1769 
1770   template <class C>
1771   typename C::CType compare(const SCFG *E, C &Cmp) const {
1772     // TODO: implement CFG comparisons
1773     return Cmp.comparePointers(this, E);
1774   }
1775 
1776 private:
1777   // assign unique ids to all instructions
1778   void renumberInstrs();
1779 
1780   MemRegionRef Arena;
1781   BlockArray Blocks;
1782   BasicBlock *Entry = nullptr;
1783   BasicBlock *Exit = nullptr;
1784   unsigned NumInstructions = 0;
1785   bool Normal = false;
1786 };
1787 
1788 /// An identifier, e.g. 'foo' or 'x'.
1789 /// This is a pseduo-term; it will be lowered to a variable or projection.
1790 class Identifier : public SExpr {
1791 public:
1792   Identifier(StringRef Id): SExpr(COP_Identifier), Name(Id) {}
1793   Identifier(const Identifier &) = default;
1794 
1795   static bool classof(const SExpr *E) { return E->opcode() == COP_Identifier; }
1796 
1797   StringRef name() const { return Name; }
1798 
1799   template <class V>
1800   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1801     return Vs.reduceIdentifier(*this);
1802   }
1803 
1804   template <class C>
1805   typename C::CType compare(const Identifier* E, C& Cmp) const {
1806     return Cmp.compareStrings(name(), E->name());
1807   }
1808 
1809 private:
1810   StringRef Name;
1811 };
1812 
1813 /// An if-then-else expression.
1814 /// This is a pseduo-term; it will be lowered to a branch in a CFG.
1815 class IfThenElse : public SExpr {
1816 public:
1817   IfThenElse(SExpr *C, SExpr *T, SExpr *E)
1818       : SExpr(COP_IfThenElse), Condition(C), ThenExpr(T), ElseExpr(E) {}
1819   IfThenElse(const IfThenElse &I, SExpr *C, SExpr *T, SExpr *E)
1820       : SExpr(I), Condition(C), ThenExpr(T), ElseExpr(E) {}
1821 
1822   static bool classof(const SExpr *E) { return E->opcode() == COP_IfThenElse; }
1823 
1824   SExpr *condition() { return Condition; }   // Address to store to
1825   const SExpr *condition() const { return Condition; }
1826 
1827   SExpr *thenExpr() { return ThenExpr; }     // Value to store
1828   const SExpr *thenExpr() const { return ThenExpr; }
1829 
1830   SExpr *elseExpr() { return ElseExpr; }     // Value to store
1831   const SExpr *elseExpr() const { return ElseExpr; }
1832 
1833   template <class V>
1834   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1835     auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx));
1836     auto Nt = Vs.traverse(ThenExpr,  Vs.subExprCtx(Ctx));
1837     auto Ne = Vs.traverse(ElseExpr,  Vs.subExprCtx(Ctx));
1838     return Vs.reduceIfThenElse(*this, Nc, Nt, Ne);
1839   }
1840 
1841   template <class C>
1842   typename C::CType compare(const IfThenElse* E, C& Cmp) const {
1843     typename C::CType Ct = Cmp.compare(condition(), E->condition());
1844     if (Cmp.notTrue(Ct))
1845       return Ct;
1846     Ct = Cmp.compare(thenExpr(), E->thenExpr());
1847     if (Cmp.notTrue(Ct))
1848       return Ct;
1849     return Cmp.compare(elseExpr(), E->elseExpr());
1850   }
1851 
1852 private:
1853   SExpr* Condition;
1854   SExpr* ThenExpr;
1855   SExpr* ElseExpr;
1856 };
1857 
1858 /// A let-expression,  e.g.  let x=t; u.
1859 /// This is a pseduo-term; it will be lowered to instructions in a CFG.
1860 class Let : public SExpr {
1861 public:
1862   Let(Variable *Vd, SExpr *Bd) : SExpr(COP_Let), VarDecl(Vd), Body(Bd) {
1863     Vd->setKind(Variable::VK_Let);
1864   }
1865 
1866   Let(const Let &L, Variable *Vd, SExpr *Bd) : SExpr(L), VarDecl(Vd), Body(Bd) {
1867     Vd->setKind(Variable::VK_Let);
1868   }
1869 
1870   static bool classof(const SExpr *E) { return E->opcode() == COP_Let; }
1871 
1872   Variable *variableDecl()  { return VarDecl; }
1873   const Variable *variableDecl() const { return VarDecl; }
1874 
1875   SExpr *body() { return Body; }
1876   const SExpr *body() const { return Body; }
1877 
1878   template <class V>
1879   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1880     // This is a variable declaration, so traverse the definition.
1881     auto E0 = Vs.traverse(VarDecl->Definition, Vs.subExprCtx(Ctx));
1882     // Tell the rewriter to enter the scope of the let variable.
1883     Variable *Nvd = Vs.enterScope(*VarDecl, E0);
1884     auto E1 = Vs.traverse(Body, Ctx);
1885     Vs.exitScope(*VarDecl);
1886     return Vs.reduceLet(*this, Nvd, E1);
1887   }
1888 
1889   template <class C>
1890   typename C::CType compare(const Let* E, C& Cmp) const {
1891     typename C::CType Ct =
1892       Cmp.compare(VarDecl->definition(), E->VarDecl->definition());
1893     if (Cmp.notTrue(Ct))
1894       return Ct;
1895     Cmp.enterScope(variableDecl(), E->variableDecl());
1896     Ct = Cmp.compare(body(), E->body());
1897     Cmp.leaveScope();
1898     return Ct;
1899   }
1900 
1901 private:
1902   Variable *VarDecl;
1903   SExpr* Body;
1904 };
1905 
1906 const SExpr *getCanonicalVal(const SExpr *E);
1907 SExpr* simplifyToCanonicalVal(SExpr *E);
1908 void simplifyIncompleteArg(til::Phi *Ph);
1909 
1910 } // namespace til
1911 } // namespace threadSafety
1912 
1913 } // namespace clang
1914 
1915 #endif // LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H