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