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