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