xref: /aosp_15_r20/external/clang/include/clang/Analysis/Analyses/ThreadSafetyTIL.h (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li //===- ThreadSafetyTIL.h ---------------------------------------*- C++ --*-===//
2*67e74705SXin Li //
3*67e74705SXin Li //                     The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT in the llvm repository for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li // This file defines a simple Typed Intermediate Language, or TIL, that is used
11*67e74705SXin Li // by the thread safety analysis (See ThreadSafety.cpp).  The TIL is intended
12*67e74705SXin Li // to be largely independent of clang, in the hope that the analysis can be
13*67e74705SXin Li // reused for other non-C++ languages.  All dependencies on clang/llvm should
14*67e74705SXin Li // go in ThreadSafetyUtil.h.
15*67e74705SXin Li //
16*67e74705SXin Li // Thread safety analysis works by comparing mutex expressions, e.g.
17*67e74705SXin Li //
18*67e74705SXin Li // class A { Mutex mu; int dat GUARDED_BY(this->mu); }
19*67e74705SXin Li // class B { A a; }
20*67e74705SXin Li //
21*67e74705SXin Li // void foo(B* b) {
22*67e74705SXin Li //   (*b).a.mu.lock();     // locks (*b).a.mu
23*67e74705SXin Li //   b->a.dat = 0;         // substitute &b->a for 'this';
24*67e74705SXin Li //                         // requires lock on (&b->a)->mu
25*67e74705SXin Li //   (b->a.mu).unlock();   // unlocks (b->a.mu)
26*67e74705SXin Li // }
27*67e74705SXin Li //
28*67e74705SXin Li // As illustrated by the above example, clang Exprs are not well-suited to
29*67e74705SXin Li // represent mutex expressions directly, since there is no easy way to compare
30*67e74705SXin Li // Exprs for equivalence.  The thread safety analysis thus lowers clang Exprs
31*67e74705SXin Li // into a simple intermediate language (IL).  The IL supports:
32*67e74705SXin Li //
33*67e74705SXin Li // (1) comparisons for semantic equality of expressions
34*67e74705SXin Li // (2) SSA renaming of variables
35*67e74705SXin Li // (3) wildcards and pattern matching over expressions
36*67e74705SXin Li // (4) hash-based expression lookup
37*67e74705SXin Li //
38*67e74705SXin Li // The TIL is currently very experimental, is intended only for use within
39*67e74705SXin Li // the thread safety analysis, and is subject to change without notice.
40*67e74705SXin Li // After the API stabilizes and matures, it may be appropriate to make this
41*67e74705SXin Li // more generally available to other analyses.
42*67e74705SXin Li //
43*67e74705SXin Li // UNDER CONSTRUCTION.  USE AT YOUR OWN RISK.
44*67e74705SXin Li //
45*67e74705SXin Li //===----------------------------------------------------------------------===//
46*67e74705SXin Li 
47*67e74705SXin Li #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H
48*67e74705SXin Li #define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H
49*67e74705SXin Li 
50*67e74705SXin Li // All clang include dependencies for this file must be put in
51*67e74705SXin Li // ThreadSafetyUtil.h.
52*67e74705SXin Li #include "ThreadSafetyUtil.h"
53*67e74705SXin Li #include <algorithm>
54*67e74705SXin Li #include <cassert>
55*67e74705SXin Li #include <cstddef>
56*67e74705SXin Li #include <stdint.h>
57*67e74705SXin Li #include <utility>
58*67e74705SXin Li 
59*67e74705SXin Li 
60*67e74705SXin Li namespace clang {
61*67e74705SXin Li namespace threadSafety {
62*67e74705SXin Li namespace til {
63*67e74705SXin Li 
64*67e74705SXin Li 
65*67e74705SXin Li /// Enum for the different distinct classes of SExpr
66*67e74705SXin Li enum TIL_Opcode {
67*67e74705SXin Li #define TIL_OPCODE_DEF(X) COP_##X,
68*67e74705SXin Li #include "ThreadSafetyOps.def"
69*67e74705SXin Li #undef TIL_OPCODE_DEF
70*67e74705SXin Li };
71*67e74705SXin Li 
72*67e74705SXin Li /// Opcode for unary arithmetic operations.
73*67e74705SXin Li enum TIL_UnaryOpcode : unsigned char {
74*67e74705SXin Li   UOP_Minus,        //  -
75*67e74705SXin Li   UOP_BitNot,       //  ~
76*67e74705SXin Li   UOP_LogicNot      //  !
77*67e74705SXin Li };
78*67e74705SXin Li 
79*67e74705SXin Li /// Opcode for binary arithmetic operations.
80*67e74705SXin Li enum TIL_BinaryOpcode : unsigned char {
81*67e74705SXin Li   BOP_Add,          //  +
82*67e74705SXin Li   BOP_Sub,          //  -
83*67e74705SXin Li   BOP_Mul,          //  *
84*67e74705SXin Li   BOP_Div,          //  /
85*67e74705SXin Li   BOP_Rem,          //  %
86*67e74705SXin Li   BOP_Shl,          //  <<
87*67e74705SXin Li   BOP_Shr,          //  >>
88*67e74705SXin Li   BOP_BitAnd,       //  &
89*67e74705SXin Li   BOP_BitXor,       //  ^
90*67e74705SXin Li   BOP_BitOr,        //  |
91*67e74705SXin Li   BOP_Eq,           //  ==
92*67e74705SXin Li   BOP_Neq,          //  !=
93*67e74705SXin Li   BOP_Lt,           //  <
94*67e74705SXin Li   BOP_Leq,          //  <=
95*67e74705SXin Li   BOP_LogicAnd,     //  &&  (no short-circuit)
96*67e74705SXin Li   BOP_LogicOr       //  ||  (no short-circuit)
97*67e74705SXin Li };
98*67e74705SXin Li 
99*67e74705SXin Li /// Opcode for cast operations.
100*67e74705SXin Li enum TIL_CastOpcode : unsigned char {
101*67e74705SXin Li   CAST_none = 0,
102*67e74705SXin Li   CAST_extendNum,   // extend precision of numeric type
103*67e74705SXin Li   CAST_truncNum,    // truncate precision of numeric type
104*67e74705SXin Li   CAST_toFloat,     // convert to floating point type
105*67e74705SXin Li   CAST_toInt,       // convert to integer type
106*67e74705SXin Li   CAST_objToPtr     // convert smart pointer to pointer  (C++ only)
107*67e74705SXin Li };
108*67e74705SXin Li 
109*67e74705SXin Li const TIL_Opcode       COP_Min  = COP_Future;
110*67e74705SXin Li const TIL_Opcode       COP_Max  = COP_Branch;
111*67e74705SXin Li const TIL_UnaryOpcode  UOP_Min  = UOP_Minus;
112*67e74705SXin Li const TIL_UnaryOpcode  UOP_Max  = UOP_LogicNot;
113*67e74705SXin Li const TIL_BinaryOpcode BOP_Min  = BOP_Add;
114*67e74705SXin Li const TIL_BinaryOpcode BOP_Max  = BOP_LogicOr;
115*67e74705SXin Li const TIL_CastOpcode   CAST_Min = CAST_none;
116*67e74705SXin Li const TIL_CastOpcode   CAST_Max = CAST_toInt;
117*67e74705SXin Li 
118*67e74705SXin Li /// Return the name of a unary opcode.
119*67e74705SXin Li StringRef getUnaryOpcodeString(TIL_UnaryOpcode Op);
120*67e74705SXin Li 
121*67e74705SXin Li /// Return the name of a binary opcode.
122*67e74705SXin Li StringRef getBinaryOpcodeString(TIL_BinaryOpcode Op);
123*67e74705SXin Li 
124*67e74705SXin Li 
125*67e74705SXin Li /// ValueTypes are data types that can actually be held in registers.
126*67e74705SXin Li /// All variables and expressions must have a value type.
127*67e74705SXin Li /// Pointer types are further subdivided into the various heap-allocated
128*67e74705SXin Li /// types, such as functions, records, etc.
129*67e74705SXin Li /// Structured types that are passed by value (e.g. complex numbers)
130*67e74705SXin Li /// require special handling; they use BT_ValueRef, and size ST_0.
131*67e74705SXin Li struct ValueType {
132*67e74705SXin Li   enum BaseType : unsigned char {
133*67e74705SXin Li     BT_Void = 0,
134*67e74705SXin Li     BT_Bool,
135*67e74705SXin Li     BT_Int,
136*67e74705SXin Li     BT_Float,
137*67e74705SXin Li     BT_String,    // String literals
138*67e74705SXin Li     BT_Pointer,
139*67e74705SXin Li     BT_ValueRef
140*67e74705SXin Li   };
141*67e74705SXin Li 
142*67e74705SXin Li   enum SizeType : unsigned char {
143*67e74705SXin Li     ST_0 = 0,
144*67e74705SXin Li     ST_1,
145*67e74705SXin Li     ST_8,
146*67e74705SXin Li     ST_16,
147*67e74705SXin Li     ST_32,
148*67e74705SXin Li     ST_64,
149*67e74705SXin Li     ST_128
150*67e74705SXin Li   };
151*67e74705SXin Li 
152*67e74705SXin Li   inline static SizeType getSizeType(unsigned nbytes);
153*67e74705SXin Li 
154*67e74705SXin Li   template <class T>
155*67e74705SXin Li   inline static ValueType getValueType();
156*67e74705SXin Li 
ValueTypeValueType157*67e74705SXin Li   ValueType(BaseType B, SizeType Sz, bool S, unsigned char VS)
158*67e74705SXin Li       : Base(B), Size(Sz), Signed(S), VectSize(VS)
159*67e74705SXin Li   { }
160*67e74705SXin Li 
161*67e74705SXin Li   BaseType      Base;
162*67e74705SXin Li   SizeType      Size;
163*67e74705SXin Li   bool          Signed;
164*67e74705SXin Li   unsigned char VectSize;  // 0 for scalar, otherwise num elements in vector
165*67e74705SXin Li };
166*67e74705SXin Li 
167*67e74705SXin Li 
getSizeType(unsigned nbytes)168*67e74705SXin Li inline ValueType::SizeType ValueType::getSizeType(unsigned nbytes) {
169*67e74705SXin Li   switch (nbytes) {
170*67e74705SXin Li     case 1: return ST_8;
171*67e74705SXin Li     case 2: return ST_16;
172*67e74705SXin Li     case 4: return ST_32;
173*67e74705SXin Li     case 8: return ST_64;
174*67e74705SXin Li     case 16: return ST_128;
175*67e74705SXin Li     default: return ST_0;
176*67e74705SXin Li   }
177*67e74705SXin Li }
178*67e74705SXin Li 
179*67e74705SXin Li 
180*67e74705SXin Li template<>
181*67e74705SXin Li inline ValueType ValueType::getValueType<void>() {
182*67e74705SXin Li   return ValueType(BT_Void, ST_0, false, 0);
183*67e74705SXin Li }
184*67e74705SXin Li 
185*67e74705SXin Li template<>
186*67e74705SXin Li inline ValueType ValueType::getValueType<bool>() {
187*67e74705SXin Li   return ValueType(BT_Bool, ST_1, false, 0);
188*67e74705SXin Li }
189*67e74705SXin Li 
190*67e74705SXin Li template<>
191*67e74705SXin Li inline ValueType ValueType::getValueType<int8_t>() {
192*67e74705SXin Li   return ValueType(BT_Int, ST_8, true, 0);
193*67e74705SXin Li }
194*67e74705SXin Li 
195*67e74705SXin Li template<>
196*67e74705SXin Li inline ValueType ValueType::getValueType<uint8_t>() {
197*67e74705SXin Li   return ValueType(BT_Int, ST_8, false, 0);
198*67e74705SXin Li }
199*67e74705SXin Li 
200*67e74705SXin Li template<>
201*67e74705SXin Li inline ValueType ValueType::getValueType<int16_t>() {
202*67e74705SXin Li   return ValueType(BT_Int, ST_16, true, 0);
203*67e74705SXin Li }
204*67e74705SXin Li 
205*67e74705SXin Li template<>
206*67e74705SXin Li inline ValueType ValueType::getValueType<uint16_t>() {
207*67e74705SXin Li   return ValueType(BT_Int, ST_16, false, 0);
208*67e74705SXin Li }
209*67e74705SXin Li 
210*67e74705SXin Li template<>
211*67e74705SXin Li inline ValueType ValueType::getValueType<int32_t>() {
212*67e74705SXin Li   return ValueType(BT_Int, ST_32, true, 0);
213*67e74705SXin Li }
214*67e74705SXin Li 
215*67e74705SXin Li template<>
216*67e74705SXin Li inline ValueType ValueType::getValueType<uint32_t>() {
217*67e74705SXin Li   return ValueType(BT_Int, ST_32, false, 0);
218*67e74705SXin Li }
219*67e74705SXin Li 
220*67e74705SXin Li template<>
221*67e74705SXin Li inline ValueType ValueType::getValueType<int64_t>() {
222*67e74705SXin Li   return ValueType(BT_Int, ST_64, true, 0);
223*67e74705SXin Li }
224*67e74705SXin Li 
225*67e74705SXin Li template<>
226*67e74705SXin Li inline ValueType ValueType::getValueType<uint64_t>() {
227*67e74705SXin Li   return ValueType(BT_Int, ST_64, false, 0);
228*67e74705SXin Li }
229*67e74705SXin Li 
230*67e74705SXin Li template<>
231*67e74705SXin Li inline ValueType ValueType::getValueType<float>() {
232*67e74705SXin Li   return ValueType(BT_Float, ST_32, true, 0);
233*67e74705SXin Li }
234*67e74705SXin Li 
235*67e74705SXin Li template<>
236*67e74705SXin Li inline ValueType ValueType::getValueType<double>() {
237*67e74705SXin Li   return ValueType(BT_Float, ST_64, true, 0);
238*67e74705SXin Li }
239*67e74705SXin Li 
240*67e74705SXin Li template<>
241*67e74705SXin Li inline ValueType ValueType::getValueType<long double>() {
242*67e74705SXin Li   return ValueType(BT_Float, ST_128, true, 0);
243*67e74705SXin Li }
244*67e74705SXin Li 
245*67e74705SXin Li template<>
246*67e74705SXin Li inline ValueType ValueType::getValueType<StringRef>() {
247*67e74705SXin Li   return ValueType(BT_String, getSizeType(sizeof(StringRef)), false, 0);
248*67e74705SXin Li }
249*67e74705SXin Li 
250*67e74705SXin Li template<>
251*67e74705SXin Li inline ValueType ValueType::getValueType<void*>() {
252*67e74705SXin Li   return ValueType(BT_Pointer, getSizeType(sizeof(void*)), false, 0);
253*67e74705SXin Li }
254*67e74705SXin Li 
255*67e74705SXin Li 
256*67e74705SXin Li class BasicBlock;
257*67e74705SXin Li 
258*67e74705SXin Li 
259*67e74705SXin Li /// Base class for AST nodes in the typed intermediate language.
260*67e74705SXin Li class SExpr {
261*67e74705SXin Li public:
opcode()262*67e74705SXin Li   TIL_Opcode opcode() const { return static_cast<TIL_Opcode>(Opcode); }
263*67e74705SXin Li 
264*67e74705SXin Li   // Subclasses of SExpr must define the following:
265*67e74705SXin Li   //
266*67e74705SXin Li   // This(const This& E, ...) {
267*67e74705SXin Li   //   copy constructor: construct copy of E, with some additional arguments.
268*67e74705SXin Li   // }
269*67e74705SXin Li   //
270*67e74705SXin Li   // template <class V>
271*67e74705SXin Li   // typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
272*67e74705SXin Li   //   traverse all subexpressions, following the traversal/rewriter interface.
273*67e74705SXin Li   // }
274*67e74705SXin Li   //
275*67e74705SXin Li   // template <class C> typename C::CType compare(CType* E, C& Cmp) {
276*67e74705SXin Li   //   compare all subexpressions, following the comparator interface
277*67e74705SXin Li   // }
new(size_t S,MemRegionRef & R)278*67e74705SXin Li   void *operator new(size_t S, MemRegionRef &R) {
279*67e74705SXin Li     return ::operator new(S, R);
280*67e74705SXin Li   }
281*67e74705SXin Li 
282*67e74705SXin Li   /// SExpr objects cannot be deleted.
283*67e74705SXin Li   // This declaration is public to workaround a gcc bug that breaks building
284*67e74705SXin Li   // with REQUIRES_EH=1.
285*67e74705SXin Li   void operator delete(void *) = delete;
286*67e74705SXin Li 
287*67e74705SXin Li   /// Returns the instruction ID for this expression.
288*67e74705SXin Li   /// All basic block instructions have a unique ID (i.e. virtual register).
id()289*67e74705SXin Li   unsigned id() const { return SExprID; }
290*67e74705SXin Li 
291*67e74705SXin Li   /// Returns the block, if this is an instruction in a basic block,
292*67e74705SXin Li   /// otherwise returns null.
block()293*67e74705SXin Li   BasicBlock* block() const { return Block; }
294*67e74705SXin Li 
295*67e74705SXin Li   /// Set the basic block and instruction ID for this expression.
setID(BasicBlock * B,unsigned id)296*67e74705SXin Li   void setID(BasicBlock *B, unsigned id) { Block = B; SExprID = id; }
297*67e74705SXin Li 
298*67e74705SXin Li protected:
SExpr(TIL_Opcode Op)299*67e74705SXin Li   SExpr(TIL_Opcode Op)
300*67e74705SXin Li     : Opcode(Op), Reserved(0), Flags(0), SExprID(0), Block(nullptr) {}
SExpr(const SExpr & E)301*67e74705SXin Li   SExpr(const SExpr &E)
302*67e74705SXin Li     : Opcode(E.Opcode), Reserved(0), Flags(E.Flags), SExprID(0),
303*67e74705SXin Li       Block(nullptr) {}
304*67e74705SXin Li 
305*67e74705SXin Li   const unsigned char Opcode;
306*67e74705SXin Li   unsigned char Reserved;
307*67e74705SXin Li   unsigned short Flags;
308*67e74705SXin Li   unsigned SExprID;
309*67e74705SXin Li   BasicBlock* Block;
310*67e74705SXin Li 
311*67e74705SXin Li private:
312*67e74705SXin Li   SExpr() = delete;
313*67e74705SXin Li 
314*67e74705SXin Li   /// SExpr objects must be created in an arena.
315*67e74705SXin Li   void *operator new(size_t) = delete;
316*67e74705SXin Li };
317*67e74705SXin Li 
318*67e74705SXin Li 
319*67e74705SXin Li // Contains various helper functions for SExprs.
320*67e74705SXin Li namespace ThreadSafetyTIL {
isTrivial(const SExpr * E)321*67e74705SXin Li   inline bool isTrivial(const SExpr *E) {
322*67e74705SXin Li     unsigned Op = E->opcode();
323*67e74705SXin Li     return Op == COP_Variable || Op == COP_Literal || Op == COP_LiteralPtr;
324*67e74705SXin Li   }
325*67e74705SXin Li }
326*67e74705SXin Li 
327*67e74705SXin Li // Nodes which declare variables
328*67e74705SXin Li class Function;
329*67e74705SXin Li class SFunction;
330*67e74705SXin Li class Let;
331*67e74705SXin Li 
332*67e74705SXin Li 
333*67e74705SXin Li /// A named variable, e.g. "x".
334*67e74705SXin Li ///
335*67e74705SXin Li /// There are two distinct places in which a Variable can appear in the AST.
336*67e74705SXin Li /// A variable declaration introduces a new variable, and can occur in 3 places:
337*67e74705SXin Li ///   Let-expressions:           (Let (x = t) u)
338*67e74705SXin Li ///   Functions:                 (Function (x : t) u)
339*67e74705SXin Li ///   Self-applicable functions  (SFunction (x) t)
340*67e74705SXin Li ///
341*67e74705SXin Li /// If a variable occurs in any other location, it is a reference to an existing
342*67e74705SXin Li /// variable declaration -- e.g. 'x' in (x * y + z). To save space, we don't
343*67e74705SXin Li /// allocate a separate AST node for variable references; a reference is just a
344*67e74705SXin Li /// pointer to the original declaration.
345*67e74705SXin Li class Variable : public SExpr {
346*67e74705SXin Li public:
classof(const SExpr * E)347*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_Variable; }
348*67e74705SXin Li 
349*67e74705SXin Li   enum VariableKind {
350*67e74705SXin Li     VK_Let,  ///< Let-variable
351*67e74705SXin Li     VK_Fun,  ///< Function parameter
352*67e74705SXin Li     VK_SFun  ///< SFunction (self) parameter
353*67e74705SXin Li   };
354*67e74705SXin Li 
355*67e74705SXin Li   Variable(StringRef s, SExpr *D = nullptr)
SExpr(COP_Variable)356*67e74705SXin Li       : SExpr(COP_Variable), Name(s), Definition(D), Cvdecl(nullptr) {
357*67e74705SXin Li     Flags = VK_Let;
358*67e74705SXin Li   }
359*67e74705SXin Li   Variable(SExpr *D, const clang::ValueDecl *Cvd = nullptr)
SExpr(COP_Variable)360*67e74705SXin Li       : SExpr(COP_Variable), Name(Cvd ? Cvd->getName() : "_x"),
361*67e74705SXin Li         Definition(D), Cvdecl(Cvd) {
362*67e74705SXin Li     Flags = VK_Let;
363*67e74705SXin Li   }
Variable(const Variable & Vd,SExpr * D)364*67e74705SXin Li   Variable(const Variable &Vd, SExpr *D)  // rewrite constructor
365*67e74705SXin Li       : SExpr(Vd), Name(Vd.Name), Definition(D), Cvdecl(Vd.Cvdecl) {
366*67e74705SXin Li     Flags = Vd.kind();
367*67e74705SXin Li   }
368*67e74705SXin Li 
369*67e74705SXin Li   /// Return the kind of variable (let, function param, or self)
kind()370*67e74705SXin Li   VariableKind kind() const { return static_cast<VariableKind>(Flags); }
371*67e74705SXin Li 
372*67e74705SXin Li   /// Return the name of the variable, if any.
name()373*67e74705SXin Li   StringRef name() const { return Name; }
374*67e74705SXin Li 
375*67e74705SXin Li   /// Return the clang declaration for this variable, if any.
clangDecl()376*67e74705SXin Li   const clang::ValueDecl *clangDecl() const { return Cvdecl; }
377*67e74705SXin Li 
378*67e74705SXin Li   /// Return the definition of the variable.
379*67e74705SXin Li   /// For let-vars, this is the setting expression.
380*67e74705SXin Li   /// For function and self parameters, it is the type of the variable.
definition()381*67e74705SXin Li   SExpr *definition() { return Definition; }
definition()382*67e74705SXin Li   const SExpr *definition() const { return Definition; }
383*67e74705SXin Li 
setName(StringRef S)384*67e74705SXin Li   void setName(StringRef S)    { Name = S;  }
setKind(VariableKind K)385*67e74705SXin Li   void setKind(VariableKind K) { Flags = K; }
setDefinition(SExpr * E)386*67e74705SXin Li   void setDefinition(SExpr *E) { Definition = E; }
setClangDecl(const clang::ValueDecl * VD)387*67e74705SXin Li   void setClangDecl(const clang::ValueDecl *VD) { Cvdecl = VD; }
388*67e74705SXin Li 
389*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)390*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
391*67e74705SXin Li     // This routine is only called for variable references.
392*67e74705SXin Li     return Vs.reduceVariableRef(this);
393*67e74705SXin Li   }
394*67e74705SXin Li 
395*67e74705SXin Li   template <class C>
compare(const Variable * E,C & Cmp)396*67e74705SXin Li   typename C::CType compare(const Variable* E, C& Cmp) const {
397*67e74705SXin Li     return Cmp.compareVariableRefs(this, E);
398*67e74705SXin Li   }
399*67e74705SXin Li 
400*67e74705SXin Li private:
401*67e74705SXin Li   friend class Function;
402*67e74705SXin Li   friend class SFunction;
403*67e74705SXin Li   friend class BasicBlock;
404*67e74705SXin Li   friend class Let;
405*67e74705SXin Li 
406*67e74705SXin Li   StringRef Name;                  // The name of the variable.
407*67e74705SXin Li   SExpr*    Definition;            // The TIL type or definition
408*67e74705SXin Li   const clang::ValueDecl *Cvdecl;  // The clang declaration for this variable.
409*67e74705SXin Li };
410*67e74705SXin Li 
411*67e74705SXin Li 
412*67e74705SXin Li /// Placeholder for an expression that has not yet been created.
413*67e74705SXin Li /// Used to implement lazy copy and rewriting strategies.
414*67e74705SXin Li class Future : public SExpr {
415*67e74705SXin Li public:
classof(const SExpr * E)416*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_Future; }
417*67e74705SXin Li 
418*67e74705SXin Li   enum FutureStatus {
419*67e74705SXin Li     FS_pending,
420*67e74705SXin Li     FS_evaluating,
421*67e74705SXin Li     FS_done
422*67e74705SXin Li   };
423*67e74705SXin Li 
Future()424*67e74705SXin Li   Future() : SExpr(COP_Future), Status(FS_pending), Result(nullptr) {}
425*67e74705SXin Li 
426*67e74705SXin Li private:
427*67e74705SXin Li   virtual ~Future() = delete;
428*67e74705SXin Li 
429*67e74705SXin Li public:
430*67e74705SXin Li   // A lazy rewriting strategy should subclass Future and override this method.
compute()431*67e74705SXin Li   virtual SExpr *compute() { return nullptr; }
432*67e74705SXin Li 
433*67e74705SXin Li   // Return the result of this future if it exists, otherwise return null.
maybeGetResult()434*67e74705SXin Li   SExpr *maybeGetResult() const {
435*67e74705SXin Li     return Result;
436*67e74705SXin Li   }
437*67e74705SXin Li 
438*67e74705SXin Li   // Return the result of this future; forcing it if necessary.
result()439*67e74705SXin Li   SExpr *result() {
440*67e74705SXin Li     switch (Status) {
441*67e74705SXin Li     case FS_pending:
442*67e74705SXin Li       return force();
443*67e74705SXin Li     case FS_evaluating:
444*67e74705SXin Li       return nullptr; // infinite loop; illegal recursion.
445*67e74705SXin Li     case FS_done:
446*67e74705SXin Li       return Result;
447*67e74705SXin Li     }
448*67e74705SXin Li   }
449*67e74705SXin Li 
450*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)451*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
452*67e74705SXin Li     assert(Result && "Cannot traverse Future that has not been forced.");
453*67e74705SXin Li     return Vs.traverse(Result, Ctx);
454*67e74705SXin Li   }
455*67e74705SXin Li 
456*67e74705SXin Li   template <class C>
compare(const Future * E,C & Cmp)457*67e74705SXin Li   typename C::CType compare(const Future* E, C& Cmp) const {
458*67e74705SXin Li     if (!Result || !E->Result)
459*67e74705SXin Li       return Cmp.comparePointers(this, E);
460*67e74705SXin Li     return Cmp.compare(Result, E->Result);
461*67e74705SXin Li   }
462*67e74705SXin Li 
463*67e74705SXin Li private:
464*67e74705SXin Li   SExpr* force();
465*67e74705SXin Li 
466*67e74705SXin Li   FutureStatus Status;
467*67e74705SXin Li   SExpr *Result;
468*67e74705SXin Li };
469*67e74705SXin Li 
470*67e74705SXin Li 
471*67e74705SXin Li /// Placeholder for expressions that cannot be represented in the TIL.
472*67e74705SXin Li class Undefined : public SExpr {
473*67e74705SXin Li public:
classof(const SExpr * E)474*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_Undefined; }
475*67e74705SXin Li 
SExpr(COP_Undefined)476*67e74705SXin Li   Undefined(const clang::Stmt *S = nullptr) : SExpr(COP_Undefined), Cstmt(S) {}
Undefined(const Undefined & U)477*67e74705SXin Li   Undefined(const Undefined &U) : SExpr(U), Cstmt(U.Cstmt) {}
478*67e74705SXin Li 
479*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)480*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
481*67e74705SXin Li     return Vs.reduceUndefined(*this);
482*67e74705SXin Li   }
483*67e74705SXin Li 
484*67e74705SXin Li   template <class C>
compare(const Undefined * E,C & Cmp)485*67e74705SXin Li   typename C::CType compare(const Undefined* E, C& Cmp) const {
486*67e74705SXin Li     return Cmp.trueResult();
487*67e74705SXin Li   }
488*67e74705SXin Li 
489*67e74705SXin Li private:
490*67e74705SXin Li   const clang::Stmt *Cstmt;
491*67e74705SXin Li };
492*67e74705SXin Li 
493*67e74705SXin Li 
494*67e74705SXin Li /// Placeholder for a wildcard that matches any other expression.
495*67e74705SXin Li class Wildcard : public SExpr {
496*67e74705SXin Li public:
classof(const SExpr * E)497*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_Wildcard; }
498*67e74705SXin Li 
Wildcard()499*67e74705SXin Li   Wildcard() : SExpr(COP_Wildcard) {}
Wildcard(const Wildcard & W)500*67e74705SXin Li   Wildcard(const Wildcard &W) : SExpr(W) {}
501*67e74705SXin Li 
traverse(V & Vs,typename V::R_Ctx Ctx)502*67e74705SXin Li   template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
503*67e74705SXin Li     return Vs.reduceWildcard(*this);
504*67e74705SXin Li   }
505*67e74705SXin Li 
506*67e74705SXin Li   template <class C>
compare(const Wildcard * E,C & Cmp)507*67e74705SXin Li   typename C::CType compare(const Wildcard* E, C& Cmp) const {
508*67e74705SXin Li     return Cmp.trueResult();
509*67e74705SXin Li   }
510*67e74705SXin Li };
511*67e74705SXin Li 
512*67e74705SXin Li 
513*67e74705SXin Li template <class T> class LiteralT;
514*67e74705SXin Li 
515*67e74705SXin Li // Base class for literal values.
516*67e74705SXin Li class Literal : public SExpr {
517*67e74705SXin Li public:
classof(const SExpr * E)518*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_Literal; }
519*67e74705SXin Li 
Literal(const clang::Expr * C)520*67e74705SXin Li   Literal(const clang::Expr *C)
521*67e74705SXin Li      : SExpr(COP_Literal), ValType(ValueType::getValueType<void>()), Cexpr(C)
522*67e74705SXin Li   { }
Literal(ValueType VT)523*67e74705SXin Li   Literal(ValueType VT) : SExpr(COP_Literal), ValType(VT), Cexpr(nullptr) {}
Literal(const Literal & L)524*67e74705SXin Li   Literal(const Literal &L) : SExpr(L), ValType(L.ValType), Cexpr(L.Cexpr) {}
525*67e74705SXin Li 
526*67e74705SXin Li   // The clang expression for this literal.
clangExpr()527*67e74705SXin Li   const clang::Expr *clangExpr() const { return Cexpr; }
528*67e74705SXin Li 
valueType()529*67e74705SXin Li   ValueType valueType() const { return ValType; }
530*67e74705SXin Li 
as()531*67e74705SXin Li   template<class T> const LiteralT<T>& as() const {
532*67e74705SXin Li     return *static_cast<const LiteralT<T>*>(this);
533*67e74705SXin Li   }
as()534*67e74705SXin Li   template<class T> LiteralT<T>& as() {
535*67e74705SXin Li     return *static_cast<LiteralT<T>*>(this);
536*67e74705SXin Li   }
537*67e74705SXin Li 
538*67e74705SXin Li   template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx);
539*67e74705SXin Li 
540*67e74705SXin Li   template <class C>
compare(const Literal * E,C & Cmp)541*67e74705SXin Li   typename C::CType compare(const Literal* E, C& Cmp) const {
542*67e74705SXin Li     // TODO: defer actual comparison to LiteralT
543*67e74705SXin Li     return Cmp.trueResult();
544*67e74705SXin Li   }
545*67e74705SXin Li 
546*67e74705SXin Li private:
547*67e74705SXin Li   const ValueType ValType;
548*67e74705SXin Li   const clang::Expr *Cexpr;
549*67e74705SXin Li };
550*67e74705SXin Li 
551*67e74705SXin Li 
552*67e74705SXin Li // Derived class for literal values, which stores the actual value.
553*67e74705SXin Li template<class T>
554*67e74705SXin Li class LiteralT : public Literal {
555*67e74705SXin Li public:
LiteralT(T Dat)556*67e74705SXin Li   LiteralT(T Dat) : Literal(ValueType::getValueType<T>()), Val(Dat) { }
LiteralT(const LiteralT<T> & L)557*67e74705SXin Li   LiteralT(const LiteralT<T> &L) : Literal(L), Val(L.Val) { }
558*67e74705SXin Li 
value()559*67e74705SXin Li   T  value() const { return Val;}
value()560*67e74705SXin Li   T& value() { return Val; }
561*67e74705SXin Li 
562*67e74705SXin Li private:
563*67e74705SXin Li   T Val;
564*67e74705SXin Li };
565*67e74705SXin Li 
566*67e74705SXin Li 
567*67e74705SXin Li 
568*67e74705SXin Li template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)569*67e74705SXin Li typename V::R_SExpr Literal::traverse(V &Vs, typename V::R_Ctx Ctx) {
570*67e74705SXin Li   if (Cexpr)
571*67e74705SXin Li     return Vs.reduceLiteral(*this);
572*67e74705SXin Li 
573*67e74705SXin Li   switch (ValType.Base) {
574*67e74705SXin Li   case ValueType::BT_Void:
575*67e74705SXin Li     break;
576*67e74705SXin Li   case ValueType::BT_Bool:
577*67e74705SXin Li     return Vs.reduceLiteralT(as<bool>());
578*67e74705SXin Li   case ValueType::BT_Int: {
579*67e74705SXin Li     switch (ValType.Size) {
580*67e74705SXin Li     case ValueType::ST_8:
581*67e74705SXin Li       if (ValType.Signed)
582*67e74705SXin Li         return Vs.reduceLiteralT(as<int8_t>());
583*67e74705SXin Li       else
584*67e74705SXin Li         return Vs.reduceLiteralT(as<uint8_t>());
585*67e74705SXin Li     case ValueType::ST_16:
586*67e74705SXin Li       if (ValType.Signed)
587*67e74705SXin Li         return Vs.reduceLiteralT(as<int16_t>());
588*67e74705SXin Li       else
589*67e74705SXin Li         return Vs.reduceLiteralT(as<uint16_t>());
590*67e74705SXin Li     case ValueType::ST_32:
591*67e74705SXin Li       if (ValType.Signed)
592*67e74705SXin Li         return Vs.reduceLiteralT(as<int32_t>());
593*67e74705SXin Li       else
594*67e74705SXin Li         return Vs.reduceLiteralT(as<uint32_t>());
595*67e74705SXin Li     case ValueType::ST_64:
596*67e74705SXin Li       if (ValType.Signed)
597*67e74705SXin Li         return Vs.reduceLiteralT(as<int64_t>());
598*67e74705SXin Li       else
599*67e74705SXin Li         return Vs.reduceLiteralT(as<uint64_t>());
600*67e74705SXin Li     default:
601*67e74705SXin Li       break;
602*67e74705SXin Li     }
603*67e74705SXin Li   }
604*67e74705SXin Li   case ValueType::BT_Float: {
605*67e74705SXin Li     switch (ValType.Size) {
606*67e74705SXin Li     case ValueType::ST_32:
607*67e74705SXin Li       return Vs.reduceLiteralT(as<float>());
608*67e74705SXin Li     case ValueType::ST_64:
609*67e74705SXin Li       return Vs.reduceLiteralT(as<double>());
610*67e74705SXin Li     default:
611*67e74705SXin Li       break;
612*67e74705SXin Li     }
613*67e74705SXin Li   }
614*67e74705SXin Li   case ValueType::BT_String:
615*67e74705SXin Li     return Vs.reduceLiteralT(as<StringRef>());
616*67e74705SXin Li   case ValueType::BT_Pointer:
617*67e74705SXin Li     return Vs.reduceLiteralT(as<void*>());
618*67e74705SXin Li   case ValueType::BT_ValueRef:
619*67e74705SXin Li     break;
620*67e74705SXin Li   }
621*67e74705SXin Li   return Vs.reduceLiteral(*this);
622*67e74705SXin Li }
623*67e74705SXin Li 
624*67e74705SXin Li 
625*67e74705SXin Li /// A Literal pointer to an object allocated in memory.
626*67e74705SXin Li /// At compile time, pointer literals are represented by symbolic names.
627*67e74705SXin Li class LiteralPtr : public SExpr {
628*67e74705SXin Li public:
classof(const SExpr * E)629*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_LiteralPtr; }
630*67e74705SXin Li 
LiteralPtr(const clang::ValueDecl * D)631*67e74705SXin Li   LiteralPtr(const clang::ValueDecl *D) : SExpr(COP_LiteralPtr), Cvdecl(D) {}
LiteralPtr(const LiteralPtr & R)632*67e74705SXin Li   LiteralPtr(const LiteralPtr &R) : SExpr(R), Cvdecl(R.Cvdecl) {}
633*67e74705SXin Li 
634*67e74705SXin Li   // The clang declaration for the value that this pointer points to.
clangDecl()635*67e74705SXin Li   const clang::ValueDecl *clangDecl() const { return Cvdecl; }
636*67e74705SXin Li 
637*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)638*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
639*67e74705SXin Li     return Vs.reduceLiteralPtr(*this);
640*67e74705SXin Li   }
641*67e74705SXin Li 
642*67e74705SXin Li   template <class C>
compare(const LiteralPtr * E,C & Cmp)643*67e74705SXin Li   typename C::CType compare(const LiteralPtr* E, C& Cmp) const {
644*67e74705SXin Li     return Cmp.comparePointers(Cvdecl, E->Cvdecl);
645*67e74705SXin Li   }
646*67e74705SXin Li 
647*67e74705SXin Li private:
648*67e74705SXin Li   const clang::ValueDecl *Cvdecl;
649*67e74705SXin Li };
650*67e74705SXin Li 
651*67e74705SXin Li 
652*67e74705SXin Li /// A function -- a.k.a. lambda abstraction.
653*67e74705SXin Li /// Functions with multiple arguments are created by currying,
654*67e74705SXin Li /// e.g. (Function (x: Int) (Function (y: Int) (Code { return x + y })))
655*67e74705SXin Li class Function : public SExpr {
656*67e74705SXin Li public:
classof(const SExpr * E)657*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_Function; }
658*67e74705SXin Li 
Function(Variable * Vd,SExpr * Bd)659*67e74705SXin Li   Function(Variable *Vd, SExpr *Bd)
660*67e74705SXin Li       : SExpr(COP_Function), VarDecl(Vd), Body(Bd) {
661*67e74705SXin Li     Vd->setKind(Variable::VK_Fun);
662*67e74705SXin Li   }
Function(const Function & F,Variable * Vd,SExpr * Bd)663*67e74705SXin Li   Function(const Function &F, Variable *Vd, SExpr *Bd) // rewrite constructor
664*67e74705SXin Li       : SExpr(F), VarDecl(Vd), Body(Bd) {
665*67e74705SXin Li     Vd->setKind(Variable::VK_Fun);
666*67e74705SXin Li   }
667*67e74705SXin Li 
variableDecl()668*67e74705SXin Li   Variable *variableDecl()  { return VarDecl; }
variableDecl()669*67e74705SXin Li   const Variable *variableDecl() const { return VarDecl; }
670*67e74705SXin Li 
body()671*67e74705SXin Li   SExpr *body() { return Body; }
body()672*67e74705SXin Li   const SExpr *body() const { return Body; }
673*67e74705SXin Li 
674*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)675*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
676*67e74705SXin Li     // This is a variable declaration, so traverse the definition.
677*67e74705SXin Li     auto E0 = Vs.traverse(VarDecl->Definition, Vs.typeCtx(Ctx));
678*67e74705SXin Li     // Tell the rewriter to enter the scope of the function.
679*67e74705SXin Li     Variable *Nvd = Vs.enterScope(*VarDecl, E0);
680*67e74705SXin Li     auto E1 = Vs.traverse(Body, Vs.declCtx(Ctx));
681*67e74705SXin Li     Vs.exitScope(*VarDecl);
682*67e74705SXin Li     return Vs.reduceFunction(*this, Nvd, E1);
683*67e74705SXin Li   }
684*67e74705SXin Li 
685*67e74705SXin Li   template <class C>
compare(const Function * E,C & Cmp)686*67e74705SXin Li   typename C::CType compare(const Function* E, C& Cmp) const {
687*67e74705SXin Li     typename C::CType Ct =
688*67e74705SXin Li       Cmp.compare(VarDecl->definition(), E->VarDecl->definition());
689*67e74705SXin Li     if (Cmp.notTrue(Ct))
690*67e74705SXin Li       return Ct;
691*67e74705SXin Li     Cmp.enterScope(variableDecl(), E->variableDecl());
692*67e74705SXin Li     Ct = Cmp.compare(body(), E->body());
693*67e74705SXin Li     Cmp.leaveScope();
694*67e74705SXin Li     return Ct;
695*67e74705SXin Li   }
696*67e74705SXin Li 
697*67e74705SXin Li private:
698*67e74705SXin Li   Variable *VarDecl;
699*67e74705SXin Li   SExpr* Body;
700*67e74705SXin Li };
701*67e74705SXin Li 
702*67e74705SXin Li 
703*67e74705SXin Li /// A self-applicable function.
704*67e74705SXin Li /// A self-applicable function can be applied to itself.  It's useful for
705*67e74705SXin Li /// implementing objects and late binding.
706*67e74705SXin Li class SFunction : public SExpr {
707*67e74705SXin Li public:
classof(const SExpr * E)708*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_SFunction; }
709*67e74705SXin Li 
SFunction(Variable * Vd,SExpr * B)710*67e74705SXin Li   SFunction(Variable *Vd, SExpr *B)
711*67e74705SXin Li       : SExpr(COP_SFunction), VarDecl(Vd), Body(B) {
712*67e74705SXin Li     assert(Vd->Definition == nullptr);
713*67e74705SXin Li     Vd->setKind(Variable::VK_SFun);
714*67e74705SXin Li     Vd->Definition = this;
715*67e74705SXin Li   }
SFunction(const SFunction & F,Variable * Vd,SExpr * B)716*67e74705SXin Li   SFunction(const SFunction &F, Variable *Vd, SExpr *B) // rewrite constructor
717*67e74705SXin Li       : SExpr(F), VarDecl(Vd), Body(B) {
718*67e74705SXin Li     assert(Vd->Definition == nullptr);
719*67e74705SXin Li     Vd->setKind(Variable::VK_SFun);
720*67e74705SXin Li     Vd->Definition = this;
721*67e74705SXin Li   }
722*67e74705SXin Li 
variableDecl()723*67e74705SXin Li   Variable *variableDecl() { return VarDecl; }
variableDecl()724*67e74705SXin Li   const Variable *variableDecl() const { return VarDecl; }
725*67e74705SXin Li 
body()726*67e74705SXin Li   SExpr *body() { return Body; }
body()727*67e74705SXin Li   const SExpr *body() const { return Body; }
728*67e74705SXin Li 
729*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)730*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
731*67e74705SXin Li     // A self-variable points to the SFunction itself.
732*67e74705SXin Li     // A rewrite must introduce the variable with a null definition, and update
733*67e74705SXin Li     // it after 'this' has been rewritten.
734*67e74705SXin Li     Variable *Nvd = Vs.enterScope(*VarDecl, nullptr);
735*67e74705SXin Li     auto E1 = Vs.traverse(Body, Vs.declCtx(Ctx));
736*67e74705SXin Li     Vs.exitScope(*VarDecl);
737*67e74705SXin Li     // A rewrite operation will call SFun constructor to set Vvd->Definition.
738*67e74705SXin Li     return Vs.reduceSFunction(*this, Nvd, E1);
739*67e74705SXin Li   }
740*67e74705SXin Li 
741*67e74705SXin Li   template <class C>
compare(const SFunction * E,C & Cmp)742*67e74705SXin Li   typename C::CType compare(const SFunction* E, C& Cmp) const {
743*67e74705SXin Li     Cmp.enterScope(variableDecl(), E->variableDecl());
744*67e74705SXin Li     typename C::CType Ct = Cmp.compare(body(), E->body());
745*67e74705SXin Li     Cmp.leaveScope();
746*67e74705SXin Li     return Ct;
747*67e74705SXin Li   }
748*67e74705SXin Li 
749*67e74705SXin Li private:
750*67e74705SXin Li   Variable *VarDecl;
751*67e74705SXin Li   SExpr* Body;
752*67e74705SXin Li };
753*67e74705SXin Li 
754*67e74705SXin Li 
755*67e74705SXin Li /// A block of code -- e.g. the body of a function.
756*67e74705SXin Li class Code : public SExpr {
757*67e74705SXin Li public:
classof(const SExpr * E)758*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_Code; }
759*67e74705SXin Li 
Code(SExpr * T,SExpr * B)760*67e74705SXin Li   Code(SExpr *T, SExpr *B) : SExpr(COP_Code), ReturnType(T), Body(B) {}
Code(const Code & C,SExpr * T,SExpr * B)761*67e74705SXin Li   Code(const Code &C, SExpr *T, SExpr *B) // rewrite constructor
762*67e74705SXin Li       : SExpr(C), ReturnType(T), Body(B) {}
763*67e74705SXin Li 
returnType()764*67e74705SXin Li   SExpr *returnType() { return ReturnType; }
returnType()765*67e74705SXin Li   const SExpr *returnType() const { return ReturnType; }
766*67e74705SXin Li 
body()767*67e74705SXin Li   SExpr *body() { return Body; }
body()768*67e74705SXin Li   const SExpr *body() const { return Body; }
769*67e74705SXin Li 
770*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)771*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
772*67e74705SXin Li     auto Nt = Vs.traverse(ReturnType, Vs.typeCtx(Ctx));
773*67e74705SXin Li     auto Nb = Vs.traverse(Body,       Vs.lazyCtx(Ctx));
774*67e74705SXin Li     return Vs.reduceCode(*this, Nt, Nb);
775*67e74705SXin Li   }
776*67e74705SXin Li 
777*67e74705SXin Li   template <class C>
compare(const Code * E,C & Cmp)778*67e74705SXin Li   typename C::CType compare(const Code* E, C& Cmp) const {
779*67e74705SXin Li     typename C::CType Ct = Cmp.compare(returnType(), E->returnType());
780*67e74705SXin Li     if (Cmp.notTrue(Ct))
781*67e74705SXin Li       return Ct;
782*67e74705SXin Li     return Cmp.compare(body(), E->body());
783*67e74705SXin Li   }
784*67e74705SXin Li 
785*67e74705SXin Li private:
786*67e74705SXin Li   SExpr* ReturnType;
787*67e74705SXin Li   SExpr* Body;
788*67e74705SXin Li };
789*67e74705SXin Li 
790*67e74705SXin Li 
791*67e74705SXin Li /// A typed, writable location in memory
792*67e74705SXin Li class Field : public SExpr {
793*67e74705SXin Li public:
classof(const SExpr * E)794*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_Field; }
795*67e74705SXin Li 
Field(SExpr * R,SExpr * B)796*67e74705SXin Li   Field(SExpr *R, SExpr *B) : SExpr(COP_Field), Range(R), Body(B) {}
Field(const Field & C,SExpr * R,SExpr * B)797*67e74705SXin Li   Field(const Field &C, SExpr *R, SExpr *B) // rewrite constructor
798*67e74705SXin Li       : SExpr(C), Range(R), Body(B) {}
799*67e74705SXin Li 
range()800*67e74705SXin Li   SExpr *range() { return Range; }
range()801*67e74705SXin Li   const SExpr *range() const { return Range; }
802*67e74705SXin Li 
body()803*67e74705SXin Li   SExpr *body() { return Body; }
body()804*67e74705SXin Li   const SExpr *body() const { return Body; }
805*67e74705SXin Li 
806*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)807*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
808*67e74705SXin Li     auto Nr = Vs.traverse(Range, Vs.typeCtx(Ctx));
809*67e74705SXin Li     auto Nb = Vs.traverse(Body,  Vs.lazyCtx(Ctx));
810*67e74705SXin Li     return Vs.reduceField(*this, Nr, Nb);
811*67e74705SXin Li   }
812*67e74705SXin Li 
813*67e74705SXin Li   template <class C>
compare(const Field * E,C & Cmp)814*67e74705SXin Li   typename C::CType compare(const Field* E, C& Cmp) const {
815*67e74705SXin Li     typename C::CType Ct = Cmp.compare(range(), E->range());
816*67e74705SXin Li     if (Cmp.notTrue(Ct))
817*67e74705SXin Li       return Ct;
818*67e74705SXin Li     return Cmp.compare(body(), E->body());
819*67e74705SXin Li   }
820*67e74705SXin Li 
821*67e74705SXin Li private:
822*67e74705SXin Li   SExpr* Range;
823*67e74705SXin Li   SExpr* Body;
824*67e74705SXin Li };
825*67e74705SXin Li 
826*67e74705SXin Li 
827*67e74705SXin Li /// Apply an argument to a function.
828*67e74705SXin Li /// Note that this does not actually call the function.  Functions are curried,
829*67e74705SXin Li /// so this returns a closure in which the first parameter has been applied.
830*67e74705SXin Li /// Once all parameters have been applied, Call can be used to invoke the
831*67e74705SXin Li /// function.
832*67e74705SXin Li class Apply : public SExpr {
833*67e74705SXin Li public:
classof(const SExpr * E)834*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_Apply; }
835*67e74705SXin Li 
Apply(SExpr * F,SExpr * A)836*67e74705SXin Li   Apply(SExpr *F, SExpr *A) : SExpr(COP_Apply), Fun(F), Arg(A) {}
Apply(const Apply & A,SExpr * F,SExpr * Ar)837*67e74705SXin Li   Apply(const Apply &A, SExpr *F, SExpr *Ar)  // rewrite constructor
838*67e74705SXin Li       : SExpr(A), Fun(F), Arg(Ar)
839*67e74705SXin Li   {}
840*67e74705SXin Li 
fun()841*67e74705SXin Li   SExpr *fun() { return Fun; }
fun()842*67e74705SXin Li   const SExpr *fun() const { return Fun; }
843*67e74705SXin Li 
arg()844*67e74705SXin Li   SExpr *arg() { return Arg; }
arg()845*67e74705SXin Li   const SExpr *arg() const { return Arg; }
846*67e74705SXin Li 
847*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)848*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
849*67e74705SXin Li     auto Nf = Vs.traverse(Fun, Vs.subExprCtx(Ctx));
850*67e74705SXin Li     auto Na = Vs.traverse(Arg, Vs.subExprCtx(Ctx));
851*67e74705SXin Li     return Vs.reduceApply(*this, Nf, Na);
852*67e74705SXin Li   }
853*67e74705SXin Li 
854*67e74705SXin Li   template <class C>
compare(const Apply * E,C & Cmp)855*67e74705SXin Li   typename C::CType compare(const Apply* E, C& Cmp) const {
856*67e74705SXin Li     typename C::CType Ct = Cmp.compare(fun(), E->fun());
857*67e74705SXin Li     if (Cmp.notTrue(Ct))
858*67e74705SXin Li       return Ct;
859*67e74705SXin Li     return Cmp.compare(arg(), E->arg());
860*67e74705SXin Li   }
861*67e74705SXin Li 
862*67e74705SXin Li private:
863*67e74705SXin Li   SExpr* Fun;
864*67e74705SXin Li   SExpr* Arg;
865*67e74705SXin Li };
866*67e74705SXin Li 
867*67e74705SXin Li 
868*67e74705SXin Li /// Apply a self-argument to a self-applicable function.
869*67e74705SXin Li class SApply : public SExpr {
870*67e74705SXin Li public:
classof(const SExpr * E)871*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_SApply; }
872*67e74705SXin Li 
SExpr(COP_SApply)873*67e74705SXin Li   SApply(SExpr *Sf, SExpr *A = nullptr) : SExpr(COP_SApply), Sfun(Sf), Arg(A) {}
874*67e74705SXin Li   SApply(SApply &A, SExpr *Sf, SExpr *Ar = nullptr) // rewrite constructor
SExpr(A)875*67e74705SXin Li       : SExpr(A), Sfun(Sf), Arg(Ar) {}
876*67e74705SXin Li 
sfun()877*67e74705SXin Li   SExpr *sfun() { return Sfun; }
sfun()878*67e74705SXin Li   const SExpr *sfun() const { return Sfun; }
879*67e74705SXin Li 
arg()880*67e74705SXin Li   SExpr *arg() { return Arg ? Arg : Sfun; }
arg()881*67e74705SXin Li   const SExpr *arg() const { return Arg ? Arg : Sfun; }
882*67e74705SXin Li 
isDelegation()883*67e74705SXin Li   bool isDelegation() const { return Arg != nullptr; }
884*67e74705SXin Li 
885*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)886*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
887*67e74705SXin Li     auto Nf = Vs.traverse(Sfun, Vs.subExprCtx(Ctx));
888*67e74705SXin Li     typename V::R_SExpr Na = Arg ? Vs.traverse(Arg, Vs.subExprCtx(Ctx))
889*67e74705SXin Li                                        : nullptr;
890*67e74705SXin Li     return Vs.reduceSApply(*this, Nf, Na);
891*67e74705SXin Li   }
892*67e74705SXin Li 
893*67e74705SXin Li   template <class C>
compare(const SApply * E,C & Cmp)894*67e74705SXin Li   typename C::CType compare(const SApply* E, C& Cmp) const {
895*67e74705SXin Li     typename C::CType Ct = Cmp.compare(sfun(), E->sfun());
896*67e74705SXin Li     if (Cmp.notTrue(Ct) || (!arg() && !E->arg()))
897*67e74705SXin Li       return Ct;
898*67e74705SXin Li     return Cmp.compare(arg(), E->arg());
899*67e74705SXin Li   }
900*67e74705SXin Li 
901*67e74705SXin Li private:
902*67e74705SXin Li   SExpr* Sfun;
903*67e74705SXin Li   SExpr* Arg;
904*67e74705SXin Li };
905*67e74705SXin Li 
906*67e74705SXin Li 
907*67e74705SXin Li /// Project a named slot from a C++ struct or class.
908*67e74705SXin Li class Project : public SExpr {
909*67e74705SXin Li public:
classof(const SExpr * E)910*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_Project; }
911*67e74705SXin Li 
Project(SExpr * R,StringRef SName)912*67e74705SXin Li   Project(SExpr *R, StringRef SName)
913*67e74705SXin Li       : SExpr(COP_Project), Rec(R), SlotName(SName), Cvdecl(nullptr)
914*67e74705SXin Li   { }
Project(SExpr * R,const clang::ValueDecl * Cvd)915*67e74705SXin Li   Project(SExpr *R, const clang::ValueDecl *Cvd)
916*67e74705SXin Li       : SExpr(COP_Project), Rec(R), SlotName(Cvd->getName()), Cvdecl(Cvd)
917*67e74705SXin Li   { }
Project(const Project & P,SExpr * R)918*67e74705SXin Li   Project(const Project &P, SExpr *R)
919*67e74705SXin Li       : SExpr(P), Rec(R), SlotName(P.SlotName), Cvdecl(P.Cvdecl)
920*67e74705SXin Li   { }
921*67e74705SXin Li 
record()922*67e74705SXin Li   SExpr *record() { return Rec; }
record()923*67e74705SXin Li   const SExpr *record() const { return Rec; }
924*67e74705SXin Li 
clangDecl()925*67e74705SXin Li   const clang::ValueDecl *clangDecl() const { return Cvdecl; }
926*67e74705SXin Li 
isArrow()927*67e74705SXin Li   bool isArrow() const { return (Flags & 0x01) != 0; }
setArrow(bool b)928*67e74705SXin Li   void setArrow(bool b) {
929*67e74705SXin Li     if (b) Flags |= 0x01;
930*67e74705SXin Li     else Flags &= 0xFFFE;
931*67e74705SXin Li   }
932*67e74705SXin Li 
slotName()933*67e74705SXin Li   StringRef slotName() const {
934*67e74705SXin Li     if (Cvdecl)
935*67e74705SXin Li       return Cvdecl->getName();
936*67e74705SXin Li     else
937*67e74705SXin Li       return SlotName;
938*67e74705SXin Li   }
939*67e74705SXin Li 
940*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)941*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
942*67e74705SXin Li     auto Nr = Vs.traverse(Rec, Vs.subExprCtx(Ctx));
943*67e74705SXin Li     return Vs.reduceProject(*this, Nr);
944*67e74705SXin Li   }
945*67e74705SXin Li 
946*67e74705SXin Li   template <class C>
compare(const Project * E,C & Cmp)947*67e74705SXin Li   typename C::CType compare(const Project* E, C& Cmp) const {
948*67e74705SXin Li     typename C::CType Ct = Cmp.compare(record(), E->record());
949*67e74705SXin Li     if (Cmp.notTrue(Ct))
950*67e74705SXin Li       return Ct;
951*67e74705SXin Li     return Cmp.comparePointers(Cvdecl, E->Cvdecl);
952*67e74705SXin Li   }
953*67e74705SXin Li 
954*67e74705SXin Li private:
955*67e74705SXin Li   SExpr* Rec;
956*67e74705SXin Li   StringRef SlotName;
957*67e74705SXin Li   const clang::ValueDecl *Cvdecl;
958*67e74705SXin Li };
959*67e74705SXin Li 
960*67e74705SXin Li 
961*67e74705SXin Li /// Call a function (after all arguments have been applied).
962*67e74705SXin Li class Call : public SExpr {
963*67e74705SXin Li public:
classof(const SExpr * E)964*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_Call; }
965*67e74705SXin Li 
966*67e74705SXin Li   Call(SExpr *T, const clang::CallExpr *Ce = nullptr)
SExpr(COP_Call)967*67e74705SXin Li       : SExpr(COP_Call), Target(T), Cexpr(Ce) {}
Call(const Call & C,SExpr * T)968*67e74705SXin Li   Call(const Call &C, SExpr *T) : SExpr(C), Target(T), Cexpr(C.Cexpr) {}
969*67e74705SXin Li 
target()970*67e74705SXin Li   SExpr *target() { return Target; }
target()971*67e74705SXin Li   const SExpr *target() const { return Target; }
972*67e74705SXin Li 
clangCallExpr()973*67e74705SXin Li   const clang::CallExpr *clangCallExpr() const { return Cexpr; }
974*67e74705SXin Li 
975*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)976*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
977*67e74705SXin Li     auto Nt = Vs.traverse(Target, Vs.subExprCtx(Ctx));
978*67e74705SXin Li     return Vs.reduceCall(*this, Nt);
979*67e74705SXin Li   }
980*67e74705SXin Li 
981*67e74705SXin Li   template <class C>
compare(const Call * E,C & Cmp)982*67e74705SXin Li   typename C::CType compare(const Call* E, C& Cmp) const {
983*67e74705SXin Li     return Cmp.compare(target(), E->target());
984*67e74705SXin Li   }
985*67e74705SXin Li 
986*67e74705SXin Li private:
987*67e74705SXin Li   SExpr* Target;
988*67e74705SXin Li   const clang::CallExpr *Cexpr;
989*67e74705SXin Li };
990*67e74705SXin Li 
991*67e74705SXin Li 
992*67e74705SXin Li /// Allocate memory for a new value on the heap or stack.
993*67e74705SXin Li class Alloc : public SExpr {
994*67e74705SXin Li public:
classof(const SExpr * E)995*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_Call; }
996*67e74705SXin Li 
997*67e74705SXin Li   enum AllocKind {
998*67e74705SXin Li     AK_Stack,
999*67e74705SXin Li     AK_Heap
1000*67e74705SXin Li   };
1001*67e74705SXin Li 
Alloc(SExpr * D,AllocKind K)1002*67e74705SXin Li   Alloc(SExpr *D, AllocKind K) : SExpr(COP_Alloc), Dtype(D) { Flags = K; }
Alloc(const Alloc & A,SExpr * Dt)1003*67e74705SXin Li   Alloc(const Alloc &A, SExpr *Dt) : SExpr(A), Dtype(Dt) { Flags = A.kind(); }
1004*67e74705SXin Li 
kind()1005*67e74705SXin Li   AllocKind kind() const { return static_cast<AllocKind>(Flags); }
1006*67e74705SXin Li 
dataType()1007*67e74705SXin Li   SExpr *dataType() { return Dtype; }
dataType()1008*67e74705SXin Li   const SExpr *dataType() const { return Dtype; }
1009*67e74705SXin Li 
1010*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)1011*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1012*67e74705SXin Li     auto Nd = Vs.traverse(Dtype, Vs.declCtx(Ctx));
1013*67e74705SXin Li     return Vs.reduceAlloc(*this, Nd);
1014*67e74705SXin Li   }
1015*67e74705SXin Li 
1016*67e74705SXin Li   template <class C>
compare(const Alloc * E,C & Cmp)1017*67e74705SXin Li   typename C::CType compare(const Alloc* E, C& Cmp) const {
1018*67e74705SXin Li     typename C::CType Ct = Cmp.compareIntegers(kind(), E->kind());
1019*67e74705SXin Li     if (Cmp.notTrue(Ct))
1020*67e74705SXin Li       return Ct;
1021*67e74705SXin Li     return Cmp.compare(dataType(), E->dataType());
1022*67e74705SXin Li   }
1023*67e74705SXin Li 
1024*67e74705SXin Li private:
1025*67e74705SXin Li   SExpr* Dtype;
1026*67e74705SXin Li };
1027*67e74705SXin Li 
1028*67e74705SXin Li 
1029*67e74705SXin Li /// Load a value from memory.
1030*67e74705SXin Li class Load : public SExpr {
1031*67e74705SXin Li public:
classof(const SExpr * E)1032*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_Load; }
1033*67e74705SXin Li 
Load(SExpr * P)1034*67e74705SXin Li   Load(SExpr *P) : SExpr(COP_Load), Ptr(P) {}
Load(const Load & L,SExpr * P)1035*67e74705SXin Li   Load(const Load &L, SExpr *P) : SExpr(L), Ptr(P) {}
1036*67e74705SXin Li 
pointer()1037*67e74705SXin Li   SExpr *pointer() { return Ptr; }
pointer()1038*67e74705SXin Li   const SExpr *pointer() const { return Ptr; }
1039*67e74705SXin Li 
1040*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)1041*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1042*67e74705SXin Li     auto Np = Vs.traverse(Ptr, Vs.subExprCtx(Ctx));
1043*67e74705SXin Li     return Vs.reduceLoad(*this, Np);
1044*67e74705SXin Li   }
1045*67e74705SXin Li 
1046*67e74705SXin Li   template <class C>
compare(const Load * E,C & Cmp)1047*67e74705SXin Li   typename C::CType compare(const Load* E, C& Cmp) const {
1048*67e74705SXin Li     return Cmp.compare(pointer(), E->pointer());
1049*67e74705SXin Li   }
1050*67e74705SXin Li 
1051*67e74705SXin Li private:
1052*67e74705SXin Li   SExpr* Ptr;
1053*67e74705SXin Li };
1054*67e74705SXin Li 
1055*67e74705SXin Li 
1056*67e74705SXin Li /// Store a value to memory.
1057*67e74705SXin Li /// The destination is a pointer to a field, the source is the value to store.
1058*67e74705SXin Li class Store : public SExpr {
1059*67e74705SXin Li public:
classof(const SExpr * E)1060*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_Store; }
1061*67e74705SXin Li 
Store(SExpr * P,SExpr * V)1062*67e74705SXin Li   Store(SExpr *P, SExpr *V) : SExpr(COP_Store), Dest(P), Source(V) {}
Store(const Store & S,SExpr * P,SExpr * V)1063*67e74705SXin Li   Store(const Store &S, SExpr *P, SExpr *V) : SExpr(S), Dest(P), Source(V) {}
1064*67e74705SXin Li 
destination()1065*67e74705SXin Li   SExpr *destination() { return Dest; }  // Address to store to
destination()1066*67e74705SXin Li   const SExpr *destination() const { return Dest; }
1067*67e74705SXin Li 
source()1068*67e74705SXin Li   SExpr *source() { return Source; }     // Value to store
source()1069*67e74705SXin Li   const SExpr *source() const { return Source; }
1070*67e74705SXin Li 
1071*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)1072*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1073*67e74705SXin Li     auto Np = Vs.traverse(Dest,   Vs.subExprCtx(Ctx));
1074*67e74705SXin Li     auto Nv = Vs.traverse(Source, Vs.subExprCtx(Ctx));
1075*67e74705SXin Li     return Vs.reduceStore(*this, Np, Nv);
1076*67e74705SXin Li   }
1077*67e74705SXin Li 
1078*67e74705SXin Li   template <class C>
compare(const Store * E,C & Cmp)1079*67e74705SXin Li   typename C::CType compare(const Store* E, C& Cmp) const {
1080*67e74705SXin Li     typename C::CType Ct = Cmp.compare(destination(), E->destination());
1081*67e74705SXin Li     if (Cmp.notTrue(Ct))
1082*67e74705SXin Li       return Ct;
1083*67e74705SXin Li     return Cmp.compare(source(), E->source());
1084*67e74705SXin Li   }
1085*67e74705SXin Li 
1086*67e74705SXin Li private:
1087*67e74705SXin Li   SExpr* Dest;
1088*67e74705SXin Li   SExpr* Source;
1089*67e74705SXin Li };
1090*67e74705SXin Li 
1091*67e74705SXin Li 
1092*67e74705SXin Li /// If p is a reference to an array, then p[i] is a reference to the i'th
1093*67e74705SXin Li /// element of the array.
1094*67e74705SXin Li class ArrayIndex : public SExpr {
1095*67e74705SXin Li public:
classof(const SExpr * E)1096*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayIndex; }
1097*67e74705SXin Li 
ArrayIndex(SExpr * A,SExpr * N)1098*67e74705SXin Li   ArrayIndex(SExpr *A, SExpr *N) : SExpr(COP_ArrayIndex), Array(A), Index(N) {}
ArrayIndex(const ArrayIndex & E,SExpr * A,SExpr * N)1099*67e74705SXin Li   ArrayIndex(const ArrayIndex &E, SExpr *A, SExpr *N)
1100*67e74705SXin Li     : SExpr(E), Array(A), Index(N) {}
1101*67e74705SXin Li 
array()1102*67e74705SXin Li   SExpr *array() { return Array; }
array()1103*67e74705SXin Li   const SExpr *array() const { return Array; }
1104*67e74705SXin Li 
index()1105*67e74705SXin Li   SExpr *index() { return Index; }
index()1106*67e74705SXin Li   const SExpr *index() const { return Index; }
1107*67e74705SXin Li 
1108*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)1109*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1110*67e74705SXin Li     auto Na = Vs.traverse(Array, Vs.subExprCtx(Ctx));
1111*67e74705SXin Li     auto Ni = Vs.traverse(Index, Vs.subExprCtx(Ctx));
1112*67e74705SXin Li     return Vs.reduceArrayIndex(*this, Na, Ni);
1113*67e74705SXin Li   }
1114*67e74705SXin Li 
1115*67e74705SXin Li   template <class C>
compare(const ArrayIndex * E,C & Cmp)1116*67e74705SXin Li   typename C::CType compare(const ArrayIndex* E, C& Cmp) const {
1117*67e74705SXin Li     typename C::CType Ct = Cmp.compare(array(), E->array());
1118*67e74705SXin Li     if (Cmp.notTrue(Ct))
1119*67e74705SXin Li       return Ct;
1120*67e74705SXin Li     return Cmp.compare(index(), E->index());
1121*67e74705SXin Li   }
1122*67e74705SXin Li 
1123*67e74705SXin Li private:
1124*67e74705SXin Li   SExpr* Array;
1125*67e74705SXin Li   SExpr* Index;
1126*67e74705SXin Li };
1127*67e74705SXin Li 
1128*67e74705SXin Li 
1129*67e74705SXin Li /// Pointer arithmetic, restricted to arrays only.
1130*67e74705SXin Li /// If p is a reference to an array, then p + n, where n is an integer, is
1131*67e74705SXin Li /// a reference to a subarray.
1132*67e74705SXin Li class ArrayAdd : public SExpr {
1133*67e74705SXin Li public:
classof(const SExpr * E)1134*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayAdd; }
1135*67e74705SXin Li 
ArrayAdd(SExpr * A,SExpr * N)1136*67e74705SXin Li   ArrayAdd(SExpr *A, SExpr *N) : SExpr(COP_ArrayAdd), Array(A), Index(N) {}
ArrayAdd(const ArrayAdd & E,SExpr * A,SExpr * N)1137*67e74705SXin Li   ArrayAdd(const ArrayAdd &E, SExpr *A, SExpr *N)
1138*67e74705SXin Li     : SExpr(E), Array(A), Index(N) {}
1139*67e74705SXin Li 
array()1140*67e74705SXin Li   SExpr *array() { return Array; }
array()1141*67e74705SXin Li   const SExpr *array() const { return Array; }
1142*67e74705SXin Li 
index()1143*67e74705SXin Li   SExpr *index() { return Index; }
index()1144*67e74705SXin Li   const SExpr *index() const { return Index; }
1145*67e74705SXin Li 
1146*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)1147*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1148*67e74705SXin Li     auto Na = Vs.traverse(Array, Vs.subExprCtx(Ctx));
1149*67e74705SXin Li     auto Ni = Vs.traverse(Index, Vs.subExprCtx(Ctx));
1150*67e74705SXin Li     return Vs.reduceArrayAdd(*this, Na, Ni);
1151*67e74705SXin Li   }
1152*67e74705SXin Li 
1153*67e74705SXin Li   template <class C>
compare(const ArrayAdd * E,C & Cmp)1154*67e74705SXin Li   typename C::CType compare(const ArrayAdd* E, C& Cmp) const {
1155*67e74705SXin Li     typename C::CType Ct = Cmp.compare(array(), E->array());
1156*67e74705SXin Li     if (Cmp.notTrue(Ct))
1157*67e74705SXin Li       return Ct;
1158*67e74705SXin Li     return Cmp.compare(index(), E->index());
1159*67e74705SXin Li   }
1160*67e74705SXin Li 
1161*67e74705SXin Li private:
1162*67e74705SXin Li   SExpr* Array;
1163*67e74705SXin Li   SExpr* Index;
1164*67e74705SXin Li };
1165*67e74705SXin Li 
1166*67e74705SXin Li 
1167*67e74705SXin Li /// Simple arithmetic unary operations, e.g. negate and not.
1168*67e74705SXin Li /// These operations have no side-effects.
1169*67e74705SXin Li class UnaryOp : public SExpr {
1170*67e74705SXin Li public:
classof(const SExpr * E)1171*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_UnaryOp; }
1172*67e74705SXin Li 
UnaryOp(TIL_UnaryOpcode Op,SExpr * E)1173*67e74705SXin Li   UnaryOp(TIL_UnaryOpcode Op, SExpr *E) : SExpr(COP_UnaryOp), Expr0(E) {
1174*67e74705SXin Li     Flags = Op;
1175*67e74705SXin Li   }
UnaryOp(const UnaryOp & U,SExpr * E)1176*67e74705SXin Li   UnaryOp(const UnaryOp &U, SExpr *E) : SExpr(U), Expr0(E) { Flags = U.Flags; }
1177*67e74705SXin Li 
unaryOpcode()1178*67e74705SXin Li   TIL_UnaryOpcode unaryOpcode() const {
1179*67e74705SXin Li     return static_cast<TIL_UnaryOpcode>(Flags);
1180*67e74705SXin Li   }
1181*67e74705SXin Li 
expr()1182*67e74705SXin Li   SExpr *expr() { return Expr0; }
expr()1183*67e74705SXin Li   const SExpr *expr() const { return Expr0; }
1184*67e74705SXin Li 
1185*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)1186*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1187*67e74705SXin Li     auto Ne = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
1188*67e74705SXin Li     return Vs.reduceUnaryOp(*this, Ne);
1189*67e74705SXin Li   }
1190*67e74705SXin Li 
1191*67e74705SXin Li   template <class C>
compare(const UnaryOp * E,C & Cmp)1192*67e74705SXin Li   typename C::CType compare(const UnaryOp* E, C& Cmp) const {
1193*67e74705SXin Li     typename C::CType Ct =
1194*67e74705SXin Li       Cmp.compareIntegers(unaryOpcode(), E->unaryOpcode());
1195*67e74705SXin Li     if (Cmp.notTrue(Ct))
1196*67e74705SXin Li       return Ct;
1197*67e74705SXin Li     return Cmp.compare(expr(), E->expr());
1198*67e74705SXin Li   }
1199*67e74705SXin Li 
1200*67e74705SXin Li private:
1201*67e74705SXin Li   SExpr* Expr0;
1202*67e74705SXin Li };
1203*67e74705SXin Li 
1204*67e74705SXin Li 
1205*67e74705SXin Li /// Simple arithmetic binary operations, e.g. +, -, etc.
1206*67e74705SXin Li /// These operations have no side effects.
1207*67e74705SXin Li class BinaryOp : public SExpr {
1208*67e74705SXin Li public:
classof(const SExpr * E)1209*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_BinaryOp; }
1210*67e74705SXin Li 
BinaryOp(TIL_BinaryOpcode Op,SExpr * E0,SExpr * E1)1211*67e74705SXin Li   BinaryOp(TIL_BinaryOpcode Op, SExpr *E0, SExpr *E1)
1212*67e74705SXin Li       : SExpr(COP_BinaryOp), Expr0(E0), Expr1(E1) {
1213*67e74705SXin Li     Flags = Op;
1214*67e74705SXin Li   }
BinaryOp(const BinaryOp & B,SExpr * E0,SExpr * E1)1215*67e74705SXin Li   BinaryOp(const BinaryOp &B, SExpr *E0, SExpr *E1)
1216*67e74705SXin Li       : SExpr(B), Expr0(E0), Expr1(E1) {
1217*67e74705SXin Li     Flags = B.Flags;
1218*67e74705SXin Li   }
1219*67e74705SXin Li 
binaryOpcode()1220*67e74705SXin Li   TIL_BinaryOpcode binaryOpcode() const {
1221*67e74705SXin Li     return static_cast<TIL_BinaryOpcode>(Flags);
1222*67e74705SXin Li   }
1223*67e74705SXin Li 
expr0()1224*67e74705SXin Li   SExpr *expr0() { return Expr0; }
expr0()1225*67e74705SXin Li   const SExpr *expr0() const { return Expr0; }
1226*67e74705SXin Li 
expr1()1227*67e74705SXin Li   SExpr *expr1() { return Expr1; }
expr1()1228*67e74705SXin Li   const SExpr *expr1() const { return Expr1; }
1229*67e74705SXin Li 
1230*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)1231*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1232*67e74705SXin Li     auto Ne0 = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
1233*67e74705SXin Li     auto Ne1 = Vs.traverse(Expr1, Vs.subExprCtx(Ctx));
1234*67e74705SXin Li     return Vs.reduceBinaryOp(*this, Ne0, Ne1);
1235*67e74705SXin Li   }
1236*67e74705SXin Li 
1237*67e74705SXin Li   template <class C>
compare(const BinaryOp * E,C & Cmp)1238*67e74705SXin Li   typename C::CType compare(const BinaryOp* E, C& Cmp) const {
1239*67e74705SXin Li     typename C::CType Ct =
1240*67e74705SXin Li       Cmp.compareIntegers(binaryOpcode(), E->binaryOpcode());
1241*67e74705SXin Li     if (Cmp.notTrue(Ct))
1242*67e74705SXin Li       return Ct;
1243*67e74705SXin Li     Ct = Cmp.compare(expr0(), E->expr0());
1244*67e74705SXin Li     if (Cmp.notTrue(Ct))
1245*67e74705SXin Li       return Ct;
1246*67e74705SXin Li     return Cmp.compare(expr1(), E->expr1());
1247*67e74705SXin Li   }
1248*67e74705SXin Li 
1249*67e74705SXin Li private:
1250*67e74705SXin Li   SExpr* Expr0;
1251*67e74705SXin Li   SExpr* Expr1;
1252*67e74705SXin Li };
1253*67e74705SXin Li 
1254*67e74705SXin Li 
1255*67e74705SXin Li /// Cast expressions.
1256*67e74705SXin Li /// Cast expressions are essentially unary operations, but we treat them
1257*67e74705SXin Li /// as a distinct AST node because they only change the type of the result.
1258*67e74705SXin Li class Cast : public SExpr {
1259*67e74705SXin Li public:
classof(const SExpr * E)1260*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_Cast; }
1261*67e74705SXin Li 
Cast(TIL_CastOpcode Op,SExpr * E)1262*67e74705SXin Li   Cast(TIL_CastOpcode Op, SExpr *E) : SExpr(COP_Cast), Expr0(E) { Flags = Op; }
Cast(const Cast & C,SExpr * E)1263*67e74705SXin Li   Cast(const Cast &C, SExpr *E) : SExpr(C), Expr0(E) { Flags = C.Flags; }
1264*67e74705SXin Li 
castOpcode()1265*67e74705SXin Li   TIL_CastOpcode castOpcode() const {
1266*67e74705SXin Li     return static_cast<TIL_CastOpcode>(Flags);
1267*67e74705SXin Li   }
1268*67e74705SXin Li 
expr()1269*67e74705SXin Li   SExpr *expr() { return Expr0; }
expr()1270*67e74705SXin Li   const SExpr *expr() const { return Expr0; }
1271*67e74705SXin Li 
1272*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)1273*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1274*67e74705SXin Li     auto Ne = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
1275*67e74705SXin Li     return Vs.reduceCast(*this, Ne);
1276*67e74705SXin Li   }
1277*67e74705SXin Li 
1278*67e74705SXin Li   template <class C>
compare(const Cast * E,C & Cmp)1279*67e74705SXin Li   typename C::CType compare(const Cast* E, C& Cmp) const {
1280*67e74705SXin Li     typename C::CType Ct =
1281*67e74705SXin Li       Cmp.compareIntegers(castOpcode(), E->castOpcode());
1282*67e74705SXin Li     if (Cmp.notTrue(Ct))
1283*67e74705SXin Li       return Ct;
1284*67e74705SXin Li     return Cmp.compare(expr(), E->expr());
1285*67e74705SXin Li   }
1286*67e74705SXin Li 
1287*67e74705SXin Li private:
1288*67e74705SXin Li   SExpr* Expr0;
1289*67e74705SXin Li };
1290*67e74705SXin Li 
1291*67e74705SXin Li 
1292*67e74705SXin Li class SCFG;
1293*67e74705SXin Li 
1294*67e74705SXin Li 
1295*67e74705SXin Li /// Phi Node, for code in SSA form.
1296*67e74705SXin Li /// Each Phi node has an array of possible values that it can take,
1297*67e74705SXin Li /// depending on where control flow comes from.
1298*67e74705SXin Li class Phi : public SExpr {
1299*67e74705SXin Li public:
1300*67e74705SXin Li   typedef SimpleArray<SExpr *> ValArray;
1301*67e74705SXin Li 
1302*67e74705SXin Li   // In minimal SSA form, all Phi nodes are MultiVal.
1303*67e74705SXin Li   // During conversion to SSA, incomplete Phi nodes may be introduced, which
1304*67e74705SXin Li   // are later determined to be SingleVal, and are thus redundant.
1305*67e74705SXin Li   enum Status {
1306*67e74705SXin Li     PH_MultiVal = 0, // Phi node has multiple distinct values.  (Normal)
1307*67e74705SXin Li     PH_SingleVal,    // Phi node has one distinct value, and can be eliminated
1308*67e74705SXin Li     PH_Incomplete    // Phi node is incomplete
1309*67e74705SXin Li   };
1310*67e74705SXin Li 
classof(const SExpr * E)1311*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_Phi; }
1312*67e74705SXin Li 
Phi()1313*67e74705SXin Li   Phi()
1314*67e74705SXin Li     : SExpr(COP_Phi), Cvdecl(nullptr) {}
Phi(MemRegionRef A,unsigned Nvals)1315*67e74705SXin Li   Phi(MemRegionRef A, unsigned Nvals)
1316*67e74705SXin Li     : SExpr(COP_Phi), Values(A, Nvals), Cvdecl(nullptr)  {}
Phi(const Phi & P,ValArray && Vs)1317*67e74705SXin Li   Phi(const Phi &P, ValArray &&Vs)
1318*67e74705SXin Li     : SExpr(P), Values(std::move(Vs)), Cvdecl(nullptr) {}
1319*67e74705SXin Li 
values()1320*67e74705SXin Li   const ValArray &values() const { return Values; }
values()1321*67e74705SXin Li   ValArray &values() { return Values; }
1322*67e74705SXin Li 
status()1323*67e74705SXin Li   Status status() const { return static_cast<Status>(Flags); }
setStatus(Status s)1324*67e74705SXin Li   void setStatus(Status s) { Flags = s; }
1325*67e74705SXin Li 
1326*67e74705SXin Li   /// Return the clang declaration of the variable for this Phi node, if any.
clangDecl()1327*67e74705SXin Li   const clang::ValueDecl *clangDecl() const { return Cvdecl; }
1328*67e74705SXin Li 
1329*67e74705SXin Li   /// Set the clang variable associated with this Phi node.
setClangDecl(const clang::ValueDecl * Cvd)1330*67e74705SXin Li   void setClangDecl(const clang::ValueDecl *Cvd) { Cvdecl = Cvd; }
1331*67e74705SXin Li 
1332*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)1333*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1334*67e74705SXin Li     typename V::template Container<typename V::R_SExpr>
1335*67e74705SXin Li       Nvs(Vs, Values.size());
1336*67e74705SXin Li 
1337*67e74705SXin Li     for (auto *Val : Values) {
1338*67e74705SXin Li       Nvs.push_back( Vs.traverse(Val, Vs.subExprCtx(Ctx)) );
1339*67e74705SXin Li     }
1340*67e74705SXin Li     return Vs.reducePhi(*this, Nvs);
1341*67e74705SXin Li   }
1342*67e74705SXin Li 
1343*67e74705SXin Li   template <class C>
compare(const Phi * E,C & Cmp)1344*67e74705SXin Li   typename C::CType compare(const Phi *E, C &Cmp) const {
1345*67e74705SXin Li     // TODO: implement CFG comparisons
1346*67e74705SXin Li     return Cmp.comparePointers(this, E);
1347*67e74705SXin Li   }
1348*67e74705SXin Li 
1349*67e74705SXin Li private:
1350*67e74705SXin Li   ValArray Values;
1351*67e74705SXin Li   const clang::ValueDecl* Cvdecl;
1352*67e74705SXin Li };
1353*67e74705SXin Li 
1354*67e74705SXin Li 
1355*67e74705SXin Li /// Base class for basic block terminators:  Branch, Goto, and Return.
1356*67e74705SXin Li class Terminator : public SExpr {
1357*67e74705SXin Li public:
classof(const SExpr * E)1358*67e74705SXin Li   static bool classof(const SExpr *E) {
1359*67e74705SXin Li     return E->opcode() >= COP_Goto && E->opcode() <= COP_Return;
1360*67e74705SXin Li   }
1361*67e74705SXin Li 
1362*67e74705SXin Li protected:
Terminator(TIL_Opcode Op)1363*67e74705SXin Li   Terminator(TIL_Opcode Op)  : SExpr(Op) {}
Terminator(const SExpr & E)1364*67e74705SXin Li   Terminator(const SExpr &E) : SExpr(E)  {}
1365*67e74705SXin Li 
1366*67e74705SXin Li public:
1367*67e74705SXin Li   /// Return the list of basic blocks that this terminator can branch to.
1368*67e74705SXin Li   ArrayRef<BasicBlock*> successors();
1369*67e74705SXin Li 
successors()1370*67e74705SXin Li   ArrayRef<BasicBlock*> successors() const {
1371*67e74705SXin Li     return const_cast<Terminator*>(this)->successors();
1372*67e74705SXin Li   }
1373*67e74705SXin Li };
1374*67e74705SXin Li 
1375*67e74705SXin Li 
1376*67e74705SXin Li /// Jump to another basic block.
1377*67e74705SXin Li /// A goto instruction is essentially a tail-recursive call into another
1378*67e74705SXin Li /// block.  In addition to the block pointer, it specifies an index into the
1379*67e74705SXin Li /// phi nodes of that block.  The index can be used to retrieve the "arguments"
1380*67e74705SXin Li /// of the call.
1381*67e74705SXin Li class Goto : public Terminator {
1382*67e74705SXin Li public:
classof(const SExpr * E)1383*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_Goto; }
1384*67e74705SXin Li 
Goto(BasicBlock * B,unsigned I)1385*67e74705SXin Li   Goto(BasicBlock *B, unsigned I)
1386*67e74705SXin Li       : Terminator(COP_Goto), TargetBlock(B), Index(I) {}
Goto(const Goto & G,BasicBlock * B,unsigned I)1387*67e74705SXin Li   Goto(const Goto &G, BasicBlock *B, unsigned I)
1388*67e74705SXin Li       : Terminator(COP_Goto), TargetBlock(B), Index(I) {}
1389*67e74705SXin Li 
targetBlock()1390*67e74705SXin Li   const BasicBlock *targetBlock() const { return TargetBlock; }
targetBlock()1391*67e74705SXin Li   BasicBlock *targetBlock() { return TargetBlock; }
1392*67e74705SXin Li 
1393*67e74705SXin Li   /// Returns the index into the
index()1394*67e74705SXin Li   unsigned index() const { return Index; }
1395*67e74705SXin Li 
1396*67e74705SXin Li   /// Return the list of basic blocks that this terminator can branch to.
successors()1397*67e74705SXin Li   ArrayRef<BasicBlock*> successors() {
1398*67e74705SXin Li     return TargetBlock;
1399*67e74705SXin Li   }
1400*67e74705SXin Li 
1401*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)1402*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1403*67e74705SXin Li     BasicBlock *Ntb = Vs.reduceBasicBlockRef(TargetBlock);
1404*67e74705SXin Li     return Vs.reduceGoto(*this, Ntb);
1405*67e74705SXin Li   }
1406*67e74705SXin Li 
1407*67e74705SXin Li   template <class C>
compare(const Goto * E,C & Cmp)1408*67e74705SXin Li   typename C::CType compare(const Goto *E, C &Cmp) const {
1409*67e74705SXin Li     // TODO: implement CFG comparisons
1410*67e74705SXin Li     return Cmp.comparePointers(this, E);
1411*67e74705SXin Li   }
1412*67e74705SXin Li 
1413*67e74705SXin Li private:
1414*67e74705SXin Li   BasicBlock *TargetBlock;
1415*67e74705SXin Li   unsigned Index;
1416*67e74705SXin Li };
1417*67e74705SXin Li 
1418*67e74705SXin Li 
1419*67e74705SXin Li /// A conditional branch to two other blocks.
1420*67e74705SXin Li /// Note that unlike Goto, Branch does not have an index.  The target blocks
1421*67e74705SXin Li /// must be child-blocks, and cannot have Phi nodes.
1422*67e74705SXin Li class Branch : public Terminator {
1423*67e74705SXin Li public:
classof(const SExpr * E)1424*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_Branch; }
1425*67e74705SXin Li 
Branch(SExpr * C,BasicBlock * T,BasicBlock * E)1426*67e74705SXin Li   Branch(SExpr *C, BasicBlock *T, BasicBlock *E)
1427*67e74705SXin Li       : Terminator(COP_Branch), Condition(C) {
1428*67e74705SXin Li     Branches[0] = T;
1429*67e74705SXin Li     Branches[1] = E;
1430*67e74705SXin Li   }
Branch(const Branch & Br,SExpr * C,BasicBlock * T,BasicBlock * E)1431*67e74705SXin Li   Branch(const Branch &Br, SExpr *C, BasicBlock *T, BasicBlock *E)
1432*67e74705SXin Li       : Terminator(Br), Condition(C) {
1433*67e74705SXin Li     Branches[0] = T;
1434*67e74705SXin Li     Branches[1] = E;
1435*67e74705SXin Li   }
1436*67e74705SXin Li 
condition()1437*67e74705SXin Li   const SExpr *condition() const { return Condition; }
condition()1438*67e74705SXin Li   SExpr *condition() { return Condition; }
1439*67e74705SXin Li 
thenBlock()1440*67e74705SXin Li   const BasicBlock *thenBlock() const { return Branches[0]; }
thenBlock()1441*67e74705SXin Li   BasicBlock *thenBlock() { return Branches[0]; }
1442*67e74705SXin Li 
elseBlock()1443*67e74705SXin Li   const BasicBlock *elseBlock() const { return Branches[1]; }
elseBlock()1444*67e74705SXin Li   BasicBlock *elseBlock() { return Branches[1]; }
1445*67e74705SXin Li 
1446*67e74705SXin Li   /// Return the list of basic blocks that this terminator can branch to.
successors()1447*67e74705SXin Li   ArrayRef<BasicBlock*> successors() {
1448*67e74705SXin Li     return llvm::makeArrayRef(Branches);
1449*67e74705SXin Li   }
1450*67e74705SXin Li 
1451*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)1452*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1453*67e74705SXin Li     auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx));
1454*67e74705SXin Li     BasicBlock *Ntb = Vs.reduceBasicBlockRef(Branches[0]);
1455*67e74705SXin Li     BasicBlock *Nte = Vs.reduceBasicBlockRef(Branches[1]);
1456*67e74705SXin Li     return Vs.reduceBranch(*this, Nc, Ntb, Nte);
1457*67e74705SXin Li   }
1458*67e74705SXin Li 
1459*67e74705SXin Li   template <class C>
compare(const Branch * E,C & Cmp)1460*67e74705SXin Li   typename C::CType compare(const Branch *E, C &Cmp) const {
1461*67e74705SXin Li     // TODO: implement CFG comparisons
1462*67e74705SXin Li     return Cmp.comparePointers(this, E);
1463*67e74705SXin Li   }
1464*67e74705SXin Li 
1465*67e74705SXin Li private:
1466*67e74705SXin Li   SExpr*     Condition;
1467*67e74705SXin Li   BasicBlock *Branches[2];
1468*67e74705SXin Li };
1469*67e74705SXin Li 
1470*67e74705SXin Li 
1471*67e74705SXin Li /// Return from the enclosing function, passing the return value to the caller.
1472*67e74705SXin Li /// Only the exit block should end with a return statement.
1473*67e74705SXin Li class Return : public Terminator {
1474*67e74705SXin Li public:
classof(const SExpr * E)1475*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_Return; }
1476*67e74705SXin Li 
Return(SExpr * Rval)1477*67e74705SXin Li   Return(SExpr* Rval) : Terminator(COP_Return), Retval(Rval) {}
Return(const Return & R,SExpr * Rval)1478*67e74705SXin Li   Return(const Return &R, SExpr* Rval) : Terminator(R), Retval(Rval) {}
1479*67e74705SXin Li 
1480*67e74705SXin Li   /// Return an empty list.
successors()1481*67e74705SXin Li   ArrayRef<BasicBlock*> successors() {
1482*67e74705SXin Li     return None;
1483*67e74705SXin Li   }
1484*67e74705SXin Li 
returnValue()1485*67e74705SXin Li   SExpr *returnValue() { return Retval; }
returnValue()1486*67e74705SXin Li   const SExpr *returnValue() const { return Retval; }
1487*67e74705SXin Li 
1488*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)1489*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1490*67e74705SXin Li     auto Ne = Vs.traverse(Retval, Vs.subExprCtx(Ctx));
1491*67e74705SXin Li     return Vs.reduceReturn(*this, Ne);
1492*67e74705SXin Li   }
1493*67e74705SXin Li 
1494*67e74705SXin Li   template <class C>
compare(const Return * E,C & Cmp)1495*67e74705SXin Li   typename C::CType compare(const Return *E, C &Cmp) const {
1496*67e74705SXin Li     return Cmp.compare(Retval, E->Retval);
1497*67e74705SXin Li   }
1498*67e74705SXin Li 
1499*67e74705SXin Li private:
1500*67e74705SXin Li   SExpr* Retval;
1501*67e74705SXin Li };
1502*67e74705SXin Li 
1503*67e74705SXin Li 
successors()1504*67e74705SXin Li inline ArrayRef<BasicBlock*> Terminator::successors() {
1505*67e74705SXin Li   switch (opcode()) {
1506*67e74705SXin Li     case COP_Goto:   return cast<Goto>(this)->successors();
1507*67e74705SXin Li     case COP_Branch: return cast<Branch>(this)->successors();
1508*67e74705SXin Li     case COP_Return: return cast<Return>(this)->successors();
1509*67e74705SXin Li     default:
1510*67e74705SXin Li       return None;
1511*67e74705SXin Li   }
1512*67e74705SXin Li }
1513*67e74705SXin Li 
1514*67e74705SXin Li 
1515*67e74705SXin Li /// A basic block is part of an SCFG.  It can be treated as a function in
1516*67e74705SXin Li /// continuation passing style.  A block consists of a sequence of phi nodes,
1517*67e74705SXin Li /// which are "arguments" to the function, followed by a sequence of
1518*67e74705SXin Li /// instructions.  It ends with a Terminator, which is a Branch or Goto to
1519*67e74705SXin Li /// another basic block in the same SCFG.
1520*67e74705SXin Li class BasicBlock : public SExpr {
1521*67e74705SXin Li public:
1522*67e74705SXin Li   typedef SimpleArray<SExpr*>      InstrArray;
1523*67e74705SXin Li   typedef SimpleArray<BasicBlock*> BlockArray;
1524*67e74705SXin Li 
1525*67e74705SXin Li   // TopologyNodes are used to overlay tree structures on top of the CFG,
1526*67e74705SXin Li   // such as dominator and postdominator trees.  Each block is assigned an
1527*67e74705SXin Li   // ID in the tree according to a depth-first search.  Tree traversals are
1528*67e74705SXin Li   // always up, towards the parents.
1529*67e74705SXin Li   struct TopologyNode {
TopologyNodeTopologyNode1530*67e74705SXin Li     TopologyNode() : NodeID(0), SizeOfSubTree(0), Parent(nullptr) {}
1531*67e74705SXin Li 
isParentOfTopologyNode1532*67e74705SXin Li     bool isParentOf(const TopologyNode& OtherNode) {
1533*67e74705SXin Li       return OtherNode.NodeID > NodeID &&
1534*67e74705SXin Li              OtherNode.NodeID < NodeID + SizeOfSubTree;
1535*67e74705SXin Li     }
1536*67e74705SXin Li 
isParentOfOrEqualTopologyNode1537*67e74705SXin Li     bool isParentOfOrEqual(const TopologyNode& OtherNode) {
1538*67e74705SXin Li       return OtherNode.NodeID >= NodeID &&
1539*67e74705SXin Li              OtherNode.NodeID < NodeID + SizeOfSubTree;
1540*67e74705SXin Li     }
1541*67e74705SXin Li 
1542*67e74705SXin Li     int NodeID;
1543*67e74705SXin Li     int SizeOfSubTree;    // Includes this node, so must be > 1.
1544*67e74705SXin Li     BasicBlock *Parent;   // Pointer to parent.
1545*67e74705SXin Li   };
1546*67e74705SXin Li 
classof(const SExpr * E)1547*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_BasicBlock; }
1548*67e74705SXin Li 
BasicBlock(MemRegionRef A)1549*67e74705SXin Li   explicit BasicBlock(MemRegionRef A)
1550*67e74705SXin Li       : SExpr(COP_BasicBlock), Arena(A), CFGPtr(nullptr), BlockID(0),
1551*67e74705SXin Li         Visited(0), TermInstr(nullptr) {}
BasicBlock(BasicBlock & B,MemRegionRef A,InstrArray && As,InstrArray && Is,Terminator * T)1552*67e74705SXin Li   BasicBlock(BasicBlock &B, MemRegionRef A, InstrArray &&As, InstrArray &&Is,
1553*67e74705SXin Li              Terminator *T)
1554*67e74705SXin Li       : SExpr(COP_BasicBlock), Arena(A), CFGPtr(nullptr), BlockID(0),Visited(0),
1555*67e74705SXin Li         Args(std::move(As)), Instrs(std::move(Is)), TermInstr(T) {}
1556*67e74705SXin Li 
1557*67e74705SXin Li   /// Returns the block ID.  Every block has a unique ID in the CFG.
blockID()1558*67e74705SXin Li   int blockID() const { return BlockID; }
1559*67e74705SXin Li 
1560*67e74705SXin Li   /// Returns the number of predecessors.
numPredecessors()1561*67e74705SXin Li   size_t numPredecessors() const { return Predecessors.size(); }
numSuccessors()1562*67e74705SXin Li   size_t numSuccessors() const { return successors().size(); }
1563*67e74705SXin Li 
cfg()1564*67e74705SXin Li   const SCFG* cfg() const { return CFGPtr; }
cfg()1565*67e74705SXin Li   SCFG* cfg() { return CFGPtr; }
1566*67e74705SXin Li 
parent()1567*67e74705SXin Li   const BasicBlock *parent() const { return DominatorNode.Parent; }
parent()1568*67e74705SXin Li   BasicBlock *parent() { return DominatorNode.Parent; }
1569*67e74705SXin Li 
arguments()1570*67e74705SXin Li   const InstrArray &arguments() const { return Args; }
arguments()1571*67e74705SXin Li   InstrArray &arguments() { return Args; }
1572*67e74705SXin Li 
instructions()1573*67e74705SXin Li   InstrArray &instructions() { return Instrs; }
instructions()1574*67e74705SXin Li   const InstrArray &instructions() const { return Instrs; }
1575*67e74705SXin Li 
1576*67e74705SXin Li   /// Returns a list of predecessors.
1577*67e74705SXin Li   /// The order of predecessors in the list is important; each phi node has
1578*67e74705SXin Li   /// exactly one argument for each precessor, in the same order.
predecessors()1579*67e74705SXin Li   BlockArray &predecessors() { return Predecessors; }
predecessors()1580*67e74705SXin Li   const BlockArray &predecessors() const { return Predecessors; }
1581*67e74705SXin Li 
successors()1582*67e74705SXin Li   ArrayRef<BasicBlock*> successors() { return TermInstr->successors(); }
successors()1583*67e74705SXin Li   ArrayRef<BasicBlock*> successors() const { return TermInstr->successors(); }
1584*67e74705SXin Li 
terminator()1585*67e74705SXin Li   const Terminator *terminator() const { return TermInstr; }
terminator()1586*67e74705SXin Li   Terminator *terminator() { return TermInstr; }
1587*67e74705SXin Li 
setTerminator(Terminator * E)1588*67e74705SXin Li   void setTerminator(Terminator *E) { TermInstr = E; }
1589*67e74705SXin Li 
Dominates(const BasicBlock & Other)1590*67e74705SXin Li   bool Dominates(const BasicBlock &Other) {
1591*67e74705SXin Li     return DominatorNode.isParentOfOrEqual(Other.DominatorNode);
1592*67e74705SXin Li   }
1593*67e74705SXin Li 
PostDominates(const BasicBlock & Other)1594*67e74705SXin Li   bool PostDominates(const BasicBlock &Other) {
1595*67e74705SXin Li     return PostDominatorNode.isParentOfOrEqual(Other.PostDominatorNode);
1596*67e74705SXin Li   }
1597*67e74705SXin Li 
1598*67e74705SXin Li   /// Add a new argument.
addArgument(Phi * V)1599*67e74705SXin Li   void addArgument(Phi *V) {
1600*67e74705SXin Li     Args.reserveCheck(1, Arena);
1601*67e74705SXin Li     Args.push_back(V);
1602*67e74705SXin Li   }
1603*67e74705SXin Li   /// Add a new instruction.
addInstruction(SExpr * V)1604*67e74705SXin Li   void addInstruction(SExpr *V) {
1605*67e74705SXin Li     Instrs.reserveCheck(1, Arena);
1606*67e74705SXin Li     Instrs.push_back(V);
1607*67e74705SXin Li   }
1608*67e74705SXin Li   // Add a new predecessor, and return the phi-node index for it.
1609*67e74705SXin Li   // Will add an argument to all phi-nodes, initialized to nullptr.
1610*67e74705SXin Li   unsigned addPredecessor(BasicBlock *Pred);
1611*67e74705SXin Li 
1612*67e74705SXin Li   // Reserve space for Nargs arguments.
reserveArguments(unsigned Nargs)1613*67e74705SXin Li   void reserveArguments(unsigned Nargs)   { Args.reserve(Nargs, Arena); }
1614*67e74705SXin Li 
1615*67e74705SXin Li   // Reserve space for Nins instructions.
reserveInstructions(unsigned Nins)1616*67e74705SXin Li   void reserveInstructions(unsigned Nins) { Instrs.reserve(Nins, Arena); }
1617*67e74705SXin Li 
1618*67e74705SXin Li   // Reserve space for NumPreds predecessors, including space in phi nodes.
1619*67e74705SXin Li   void reservePredecessors(unsigned NumPreds);
1620*67e74705SXin Li 
1621*67e74705SXin Li   /// Return the index of BB, or Predecessors.size if BB is not a predecessor.
findPredecessorIndex(const BasicBlock * BB)1622*67e74705SXin Li   unsigned findPredecessorIndex(const BasicBlock *BB) const {
1623*67e74705SXin Li     auto I = std::find(Predecessors.cbegin(), Predecessors.cend(), BB);
1624*67e74705SXin Li     return std::distance(Predecessors.cbegin(), I);
1625*67e74705SXin Li   }
1626*67e74705SXin Li 
1627*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)1628*67e74705SXin Li   typename V::R_BasicBlock traverse(V &Vs, typename V::R_Ctx Ctx) {
1629*67e74705SXin Li     typename V::template Container<SExpr*> Nas(Vs, Args.size());
1630*67e74705SXin Li     typename V::template Container<SExpr*> Nis(Vs, Instrs.size());
1631*67e74705SXin Li 
1632*67e74705SXin Li     // Entering the basic block should do any scope initialization.
1633*67e74705SXin Li     Vs.enterBasicBlock(*this);
1634*67e74705SXin Li 
1635*67e74705SXin Li     for (auto *E : Args) {
1636*67e74705SXin Li       auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
1637*67e74705SXin Li       Nas.push_back(Ne);
1638*67e74705SXin Li     }
1639*67e74705SXin Li     for (auto *E : Instrs) {
1640*67e74705SXin Li       auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
1641*67e74705SXin Li       Nis.push_back(Ne);
1642*67e74705SXin Li     }
1643*67e74705SXin Li     auto Nt = Vs.traverse(TermInstr, Ctx);
1644*67e74705SXin Li 
1645*67e74705SXin Li     // Exiting the basic block should handle any scope cleanup.
1646*67e74705SXin Li     Vs.exitBasicBlock(*this);
1647*67e74705SXin Li 
1648*67e74705SXin Li     return Vs.reduceBasicBlock(*this, Nas, Nis, Nt);
1649*67e74705SXin Li   }
1650*67e74705SXin Li 
1651*67e74705SXin Li   template <class C>
compare(const BasicBlock * E,C & Cmp)1652*67e74705SXin Li   typename C::CType compare(const BasicBlock *E, C &Cmp) const {
1653*67e74705SXin Li     // TODO: implement CFG comparisons
1654*67e74705SXin Li     return Cmp.comparePointers(this, E);
1655*67e74705SXin Li   }
1656*67e74705SXin Li 
1657*67e74705SXin Li private:
1658*67e74705SXin Li   friend class SCFG;
1659*67e74705SXin Li 
1660*67e74705SXin Li   int  renumberInstrs(int id);  // assign unique ids to all instructions
1661*67e74705SXin Li   int  topologicalSort(SimpleArray<BasicBlock*>& Blocks, int ID);
1662*67e74705SXin Li   int  topologicalFinalSort(SimpleArray<BasicBlock*>& Blocks, int ID);
1663*67e74705SXin Li   void computeDominator();
1664*67e74705SXin Li   void computePostDominator();
1665*67e74705SXin Li 
1666*67e74705SXin Li private:
1667*67e74705SXin Li   MemRegionRef Arena;        // The arena used to allocate this block.
1668*67e74705SXin Li   SCFG         *CFGPtr;      // The CFG that contains this block.
1669*67e74705SXin Li   int          BlockID : 31; // unique id for this BB in the containing CFG.
1670*67e74705SXin Li                              // IDs are in topological order.
1671*67e74705SXin Li   bool         Visited : 1;  // Bit to determine if a block has been visited
1672*67e74705SXin Li                              // during a traversal.
1673*67e74705SXin Li   BlockArray  Predecessors;  // Predecessor blocks in the CFG.
1674*67e74705SXin Li   InstrArray  Args;          // Phi nodes.  One argument per predecessor.
1675*67e74705SXin Li   InstrArray  Instrs;        // Instructions.
1676*67e74705SXin Li   Terminator* TermInstr;     // Terminating instruction
1677*67e74705SXin Li 
1678*67e74705SXin Li   TopologyNode DominatorNode;       // The dominator tree
1679*67e74705SXin Li   TopologyNode PostDominatorNode;   // The post-dominator tree
1680*67e74705SXin Li };
1681*67e74705SXin Li 
1682*67e74705SXin Li 
1683*67e74705SXin Li /// An SCFG is a control-flow graph.  It consists of a set of basic blocks,
1684*67e74705SXin Li /// each of which terminates in a branch to another basic block.  There is one
1685*67e74705SXin Li /// entry point, and one exit point.
1686*67e74705SXin Li class SCFG : public SExpr {
1687*67e74705SXin Li public:
1688*67e74705SXin Li   typedef SimpleArray<BasicBlock *> BlockArray;
1689*67e74705SXin Li   typedef BlockArray::iterator iterator;
1690*67e74705SXin Li   typedef BlockArray::const_iterator const_iterator;
1691*67e74705SXin Li 
classof(const SExpr * E)1692*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_SCFG; }
1693*67e74705SXin Li 
SCFG(MemRegionRef A,unsigned Nblocks)1694*67e74705SXin Li   SCFG(MemRegionRef A, unsigned Nblocks)
1695*67e74705SXin Li     : SExpr(COP_SCFG), Arena(A), Blocks(A, Nblocks),
1696*67e74705SXin Li       Entry(nullptr), Exit(nullptr), NumInstructions(0), Normal(false) {
1697*67e74705SXin Li     Entry = new (A) BasicBlock(A);
1698*67e74705SXin Li     Exit  = new (A) BasicBlock(A);
1699*67e74705SXin Li     auto *V = new (A) Phi();
1700*67e74705SXin Li     Exit->addArgument(V);
1701*67e74705SXin Li     Exit->setTerminator(new (A) Return(V));
1702*67e74705SXin Li     add(Entry);
1703*67e74705SXin Li     add(Exit);
1704*67e74705SXin Li   }
SCFG(const SCFG & Cfg,BlockArray && Ba)1705*67e74705SXin Li   SCFG(const SCFG &Cfg, BlockArray &&Ba) // steals memory from Ba
1706*67e74705SXin Li       : SExpr(COP_SCFG), Arena(Cfg.Arena), Blocks(std::move(Ba)),
1707*67e74705SXin Li         Entry(nullptr), Exit(nullptr), NumInstructions(0), Normal(false) {
1708*67e74705SXin Li     // TODO: set entry and exit!
1709*67e74705SXin Li   }
1710*67e74705SXin Li 
1711*67e74705SXin Li   /// Return true if this CFG is valid.
valid()1712*67e74705SXin Li   bool valid() const { return Entry && Exit && Blocks.size() > 0; }
1713*67e74705SXin Li 
1714*67e74705SXin Li   /// Return true if this CFG has been normalized.
1715*67e74705SXin Li   /// After normalization, blocks are in topological order, and block and
1716*67e74705SXin Li   /// instruction IDs have been assigned.
normal()1717*67e74705SXin Li   bool normal() const { return Normal; }
1718*67e74705SXin Li 
begin()1719*67e74705SXin Li   iterator begin() { return Blocks.begin(); }
end()1720*67e74705SXin Li   iterator end() { return Blocks.end(); }
1721*67e74705SXin Li 
begin()1722*67e74705SXin Li   const_iterator begin() const { return cbegin(); }
end()1723*67e74705SXin Li   const_iterator end() const { return cend(); }
1724*67e74705SXin Li 
cbegin()1725*67e74705SXin Li   const_iterator cbegin() const { return Blocks.cbegin(); }
cend()1726*67e74705SXin Li   const_iterator cend() const { return Blocks.cend(); }
1727*67e74705SXin Li 
entry()1728*67e74705SXin Li   const BasicBlock *entry() const { return Entry; }
entry()1729*67e74705SXin Li   BasicBlock *entry() { return Entry; }
exit()1730*67e74705SXin Li   const BasicBlock *exit() const { return Exit; }
exit()1731*67e74705SXin Li   BasicBlock *exit() { return Exit; }
1732*67e74705SXin Li 
1733*67e74705SXin Li   /// Return the number of blocks in the CFG.
1734*67e74705SXin Li   /// Block::blockID() will return a number less than numBlocks();
numBlocks()1735*67e74705SXin Li   size_t numBlocks() const { return Blocks.size(); }
1736*67e74705SXin Li 
1737*67e74705SXin Li   /// Return the total number of instructions in the CFG.
1738*67e74705SXin Li   /// This is useful for building instruction side-tables;
1739*67e74705SXin Li   /// A call to SExpr::id() will return a number less than numInstructions().
numInstructions()1740*67e74705SXin Li   unsigned numInstructions() { return NumInstructions; }
1741*67e74705SXin Li 
add(BasicBlock * BB)1742*67e74705SXin Li   inline void add(BasicBlock *BB) {
1743*67e74705SXin Li     assert(BB->CFGPtr == nullptr);
1744*67e74705SXin Li     BB->CFGPtr = this;
1745*67e74705SXin Li     Blocks.reserveCheck(1, Arena);
1746*67e74705SXin Li     Blocks.push_back(BB);
1747*67e74705SXin Li   }
1748*67e74705SXin Li 
setEntry(BasicBlock * BB)1749*67e74705SXin Li   void setEntry(BasicBlock *BB) { Entry = BB; }
setExit(BasicBlock * BB)1750*67e74705SXin Li   void setExit(BasicBlock *BB)  { Exit = BB;  }
1751*67e74705SXin Li 
1752*67e74705SXin Li   void computeNormalForm();
1753*67e74705SXin Li 
1754*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)1755*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1756*67e74705SXin Li     Vs.enterCFG(*this);
1757*67e74705SXin Li     typename V::template Container<BasicBlock *> Bbs(Vs, Blocks.size());
1758*67e74705SXin Li 
1759*67e74705SXin Li     for (auto *B : Blocks) {
1760*67e74705SXin Li       Bbs.push_back( B->traverse(Vs, Vs.subExprCtx(Ctx)) );
1761*67e74705SXin Li     }
1762*67e74705SXin Li     Vs.exitCFG(*this);
1763*67e74705SXin Li     return Vs.reduceSCFG(*this, Bbs);
1764*67e74705SXin Li   }
1765*67e74705SXin Li 
1766*67e74705SXin Li   template <class C>
compare(const SCFG * E,C & Cmp)1767*67e74705SXin Li   typename C::CType compare(const SCFG *E, C &Cmp) const {
1768*67e74705SXin Li     // TODO: implement CFG comparisons
1769*67e74705SXin Li     return Cmp.comparePointers(this, E);
1770*67e74705SXin Li   }
1771*67e74705SXin Li 
1772*67e74705SXin Li private:
1773*67e74705SXin Li   void renumberInstrs();       // assign unique ids to all instructions
1774*67e74705SXin Li 
1775*67e74705SXin Li private:
1776*67e74705SXin Li   MemRegionRef Arena;
1777*67e74705SXin Li   BlockArray   Blocks;
1778*67e74705SXin Li   BasicBlock   *Entry;
1779*67e74705SXin Li   BasicBlock   *Exit;
1780*67e74705SXin Li   unsigned     NumInstructions;
1781*67e74705SXin Li   bool         Normal;
1782*67e74705SXin Li };
1783*67e74705SXin Li 
1784*67e74705SXin Li 
1785*67e74705SXin Li 
1786*67e74705SXin Li /// An identifier, e.g. 'foo' or 'x'.
1787*67e74705SXin Li /// This is a pseduo-term; it will be lowered to a variable or projection.
1788*67e74705SXin Li class Identifier : public SExpr {
1789*67e74705SXin Li public:
classof(const SExpr * E)1790*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_Identifier; }
1791*67e74705SXin Li 
Identifier(StringRef Id)1792*67e74705SXin Li   Identifier(StringRef Id): SExpr(COP_Identifier), Name(Id) { }
Identifier(const Identifier & I)1793*67e74705SXin Li   Identifier(const Identifier& I) : SExpr(I), Name(I.Name)  { }
1794*67e74705SXin Li 
name()1795*67e74705SXin Li   StringRef name() const { return Name; }
1796*67e74705SXin Li 
1797*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)1798*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1799*67e74705SXin Li     return Vs.reduceIdentifier(*this);
1800*67e74705SXin Li   }
1801*67e74705SXin Li 
1802*67e74705SXin Li   template <class C>
compare(const Identifier * E,C & Cmp)1803*67e74705SXin Li   typename C::CType compare(const Identifier* E, C& Cmp) const {
1804*67e74705SXin Li     return Cmp.compareStrings(name(), E->name());
1805*67e74705SXin Li   }
1806*67e74705SXin Li 
1807*67e74705SXin Li private:
1808*67e74705SXin Li   StringRef Name;
1809*67e74705SXin Li };
1810*67e74705SXin Li 
1811*67e74705SXin Li 
1812*67e74705SXin Li /// An if-then-else expression.
1813*67e74705SXin Li /// This is a pseduo-term; it will be lowered to a branch in a CFG.
1814*67e74705SXin Li class IfThenElse : public SExpr {
1815*67e74705SXin Li public:
classof(const SExpr * E)1816*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_IfThenElse; }
1817*67e74705SXin Li 
IfThenElse(SExpr * C,SExpr * T,SExpr * E)1818*67e74705SXin Li   IfThenElse(SExpr *C, SExpr *T, SExpr *E)
1819*67e74705SXin Li     : SExpr(COP_IfThenElse), Condition(C), ThenExpr(T), ElseExpr(E)
1820*67e74705SXin Li   { }
IfThenElse(const IfThenElse & I,SExpr * C,SExpr * T,SExpr * E)1821*67e74705SXin Li   IfThenElse(const IfThenElse &I, SExpr *C, SExpr *T, SExpr *E)
1822*67e74705SXin Li     : SExpr(I), Condition(C), ThenExpr(T), ElseExpr(E)
1823*67e74705SXin Li   { }
1824*67e74705SXin Li 
condition()1825*67e74705SXin Li   SExpr *condition() { return Condition; }   // Address to store to
condition()1826*67e74705SXin Li   const SExpr *condition() const { return Condition; }
1827*67e74705SXin Li 
thenExpr()1828*67e74705SXin Li   SExpr *thenExpr() { return ThenExpr; }     // Value to store
thenExpr()1829*67e74705SXin Li   const SExpr *thenExpr() const { return ThenExpr; }
1830*67e74705SXin Li 
elseExpr()1831*67e74705SXin Li   SExpr *elseExpr() { return ElseExpr; }     // Value to store
elseExpr()1832*67e74705SXin Li   const SExpr *elseExpr() const { return ElseExpr; }
1833*67e74705SXin Li 
1834*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)1835*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1836*67e74705SXin Li     auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx));
1837*67e74705SXin Li     auto Nt = Vs.traverse(ThenExpr,  Vs.subExprCtx(Ctx));
1838*67e74705SXin Li     auto Ne = Vs.traverse(ElseExpr,  Vs.subExprCtx(Ctx));
1839*67e74705SXin Li     return Vs.reduceIfThenElse(*this, Nc, Nt, Ne);
1840*67e74705SXin Li   }
1841*67e74705SXin Li 
1842*67e74705SXin Li   template <class C>
compare(const IfThenElse * E,C & Cmp)1843*67e74705SXin Li   typename C::CType compare(const IfThenElse* E, C& Cmp) const {
1844*67e74705SXin Li     typename C::CType Ct = Cmp.compare(condition(), E->condition());
1845*67e74705SXin Li     if (Cmp.notTrue(Ct))
1846*67e74705SXin Li       return Ct;
1847*67e74705SXin Li     Ct = Cmp.compare(thenExpr(), E->thenExpr());
1848*67e74705SXin Li     if (Cmp.notTrue(Ct))
1849*67e74705SXin Li       return Ct;
1850*67e74705SXin Li     return Cmp.compare(elseExpr(), E->elseExpr());
1851*67e74705SXin Li   }
1852*67e74705SXin Li 
1853*67e74705SXin Li private:
1854*67e74705SXin Li   SExpr* Condition;
1855*67e74705SXin Li   SExpr* ThenExpr;
1856*67e74705SXin Li   SExpr* ElseExpr;
1857*67e74705SXin Li };
1858*67e74705SXin Li 
1859*67e74705SXin Li 
1860*67e74705SXin Li /// A let-expression,  e.g.  let x=t; u.
1861*67e74705SXin Li /// This is a pseduo-term; it will be lowered to instructions in a CFG.
1862*67e74705SXin Li class Let : public SExpr {
1863*67e74705SXin Li public:
classof(const SExpr * E)1864*67e74705SXin Li   static bool classof(const SExpr *E) { return E->opcode() == COP_Let; }
1865*67e74705SXin Li 
Let(Variable * Vd,SExpr * Bd)1866*67e74705SXin Li   Let(Variable *Vd, SExpr *Bd) : SExpr(COP_Let), VarDecl(Vd), Body(Bd) {
1867*67e74705SXin Li     Vd->setKind(Variable::VK_Let);
1868*67e74705SXin Li   }
Let(const Let & L,Variable * Vd,SExpr * Bd)1869*67e74705SXin Li   Let(const Let &L, Variable *Vd, SExpr *Bd) : SExpr(L), VarDecl(Vd), Body(Bd) {
1870*67e74705SXin Li     Vd->setKind(Variable::VK_Let);
1871*67e74705SXin Li   }
1872*67e74705SXin Li 
variableDecl()1873*67e74705SXin Li   Variable *variableDecl()  { return VarDecl; }
variableDecl()1874*67e74705SXin Li   const Variable *variableDecl() const { return VarDecl; }
1875*67e74705SXin Li 
body()1876*67e74705SXin Li   SExpr *body() { return Body; }
body()1877*67e74705SXin Li   const SExpr *body() const { return Body; }
1878*67e74705SXin Li 
1879*67e74705SXin Li   template <class V>
traverse(V & Vs,typename V::R_Ctx Ctx)1880*67e74705SXin Li   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
1881*67e74705SXin Li     // This is a variable declaration, so traverse the definition.
1882*67e74705SXin Li     auto E0 = Vs.traverse(VarDecl->Definition, Vs.subExprCtx(Ctx));
1883*67e74705SXin Li     // Tell the rewriter to enter the scope of the let variable.
1884*67e74705SXin Li     Variable *Nvd = Vs.enterScope(*VarDecl, E0);
1885*67e74705SXin Li     auto E1 = Vs.traverse(Body, Ctx);
1886*67e74705SXin Li     Vs.exitScope(*VarDecl);
1887*67e74705SXin Li     return Vs.reduceLet(*this, Nvd, E1);
1888*67e74705SXin Li   }
1889*67e74705SXin Li 
1890*67e74705SXin Li   template <class C>
compare(const Let * E,C & Cmp)1891*67e74705SXin Li   typename C::CType compare(const Let* E, C& Cmp) const {
1892*67e74705SXin Li     typename C::CType Ct =
1893*67e74705SXin Li       Cmp.compare(VarDecl->definition(), E->VarDecl->definition());
1894*67e74705SXin Li     if (Cmp.notTrue(Ct))
1895*67e74705SXin Li       return Ct;
1896*67e74705SXin Li     Cmp.enterScope(variableDecl(), E->variableDecl());
1897*67e74705SXin Li     Ct = Cmp.compare(body(), E->body());
1898*67e74705SXin Li     Cmp.leaveScope();
1899*67e74705SXin Li     return Ct;
1900*67e74705SXin Li   }
1901*67e74705SXin Li 
1902*67e74705SXin Li private:
1903*67e74705SXin Li   Variable *VarDecl;
1904*67e74705SXin Li   SExpr* Body;
1905*67e74705SXin Li };
1906*67e74705SXin Li 
1907*67e74705SXin Li 
1908*67e74705SXin Li 
1909*67e74705SXin Li const SExpr *getCanonicalVal(const SExpr *E);
1910*67e74705SXin Li SExpr* simplifyToCanonicalVal(SExpr *E);
1911*67e74705SXin Li void simplifyIncompleteArg(til::Phi *Ph);
1912*67e74705SXin Li 
1913*67e74705SXin Li 
1914*67e74705SXin Li } // end namespace til
1915*67e74705SXin Li } // end namespace threadSafety
1916*67e74705SXin Li } // end namespace clang
1917*67e74705SXin Li 
1918*67e74705SXin Li #endif
1919