1 //===- ThreadSafetyTIL.h ---------------------------------------*- C++ --*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines a simple intermediate language that is used by the
11 // thread safety analysis (See ThreadSafety.cpp). The thread safety analysis
12 // works by comparing mutex expressions, e.g.
14 // class A { Mutex mu; int dat GUARDED_BY(this->mu); }
18 // (*b).a.mu.lock(); // locks (*b).a.mu
19 // b->a.dat = 0; // substitute &b->a for 'this';
20 // // requires lock on (&b->a)->mu
21 // (b->a.mu).unlock(); // unlocks (b->a.mu)
24 // As illustrated by the above example, clang Exprs are not well-suited to
25 // represent mutex expressions directly, since there is no easy way to compare
26 // Exprs for equivalence. The thread safety analysis thus lowers clang Exprs
27 // into a simple intermediate language (IL). The IL supports:
29 // (1) comparisons for semantic equality of expressions
30 // (2) SSA renaming of variables
31 // (3) wildcards and pattern matching over expressions
32 // (4) hash-based expression lookup
34 // The IL is currently very experimental, is intended only for use within
35 // the thread safety analysis, and is subject to change without notice.
36 // After the API stabilizes and matures, it may be appropriate to make this
37 // more generally available to other analyses.
39 // UNDER CONSTRUCTION. USE AT YOUR OWN RISK.
41 //===----------------------------------------------------------------------===//
43 #ifndef LLVM_CLANG_THREAD_SAFETY_TIL_H
44 #define LLVM_CLANG_THREAD_SAFETY_TIL_H
46 #include "clang/AST/DeclCXX.h"
47 #include "clang/AST/ExprCXX.h"
48 #include "clang/AST/StmtCXX.h"
49 #include "clang/AST/Type.h"
50 #include "llvm/ADT/StringRef.h"
51 #include "llvm/Support/AlignOf.h"
52 #include "llvm/Support/Allocator.h"
59 namespace threadSafety {
63 // Simple wrapper class to abstract away from the details of memory management.
64 // SExprs are allocated in pools, and deallocated all at once.
75 MemRegionRef() : Allocator(nullptr) {}
76 MemRegionRef(llvm::BumpPtrAllocator *A) : Allocator(A) {}
78 void *allocate(size_t Sz) {
79 return Allocator->Allocate(Sz, llvm::AlignOf<AlignmentType>::Alignment);
82 template <typename T> T *allocateT() { return Allocator->Allocate<T>(); }
84 template <typename T> T *allocateT(size_t NumElems) {
85 return Allocator->Allocate<T>(NumElems);
89 llvm::BumpPtrAllocator *Allocator;
93 } // end namespace til
94 } // end namespace threadSafety
95 } // end namespace clang
98 inline void *operator new(size_t Sz,
99 clang::threadSafety::til::MemRegionRef &R) {
100 return R.allocate(Sz);
105 namespace threadSafety {
108 using llvm::StringRef;
110 // A simple fixed size array class that does not manage its own memory,
111 // suitable for use with bump pointer allocation.
112 template <class T> class SimpleArray {
114 SimpleArray() : Data(nullptr), Size(0), Capacity(0) {}
115 SimpleArray(T *Dat, size_t Cp, size_t Sz = 0)
116 : Data(Dat), Size(0), Capacity(Cp) {}
117 SimpleArray(MemRegionRef A, size_t Cp)
118 : Data(A.allocateT<T>(Cp)), Size(0), Capacity(Cp) {}
119 SimpleArray(SimpleArray<T> &&A)
120 : Data(A.Data), Size(A.Size), Capacity(A.Capacity) {
126 T *resize(size_t Ncp, MemRegionRef A) {
128 Data = A.allocateT<T>(Ncp);
129 memcpy(Data, Odata, sizeof(T) * Size);
134 typedef const T *const_iterator;
136 size_t size() const { return Size; }
137 size_t capacity() const { return Capacity; }
139 T &operator[](unsigned I) { return Data[I]; }
140 const T &operator[](unsigned I) const { return Data[I]; }
142 iterator begin() { return Data; }
143 iterator end() { return Data + Size; }
145 const_iterator cbegin() const { return Data; }
146 const_iterator cend() const { return Data + Size; }
148 void push_back(const T &Elem) {
149 assert(Size < Capacity);
153 template <class Iter> unsigned append(Iter I, Iter E) {
156 for (; J < Capacity && I != E; ++J, ++I)
163 SimpleArray(const SimpleArray<T> &A) { }
172 #define TIL_OPCODE_DEF(X) COP_##X,
173 #include "clang/Analysis/Analyses/ThreadSafetyOps.def"
174 #undef TIL_OPCODE_DEF
179 typedef clang::BinaryOperatorKind TIL_BinaryOpcode;
180 typedef clang::UnaryOperatorKind TIL_UnaryOpcode;
181 typedef clang::CastKind TIL_CastOpcode;
186 TRV_Lazy, // subexpression may need to be traversed lazily
187 TRV_Tail // subexpression occurs in a tail position
191 // Base class for AST nodes in the typed intermediate language.
194 TIL_Opcode opcode() const { return static_cast<TIL_Opcode>(Opcode); }
196 // Subclasses of SExpr must define the following:
198 // This(const This& E, ...) {
199 // copy constructor: construct copy of E, with some additional arguments.
202 // template <class V> typename V::R_SExpr traverse(V &Visitor) {
203 // traverse all subexpressions, following the traversal/rewriter interface
206 // template <class C> typename C::CType compare(CType* E, C& Cmp) {
207 // compare all subexpressions, following the comparator interface
210 void *operator new(size_t S, clang::threadSafety::til::MemRegionRef &R) {
211 return ::operator new(S, R);
215 SExpr(TIL_Opcode Op) : Opcode(Op), Reserved(0), Flags(0) {}
216 SExpr(const SExpr &E) : Opcode(E.Opcode), Reserved(0), Flags(E.Flags) {}
218 const unsigned char Opcode;
219 unsigned char Reserved;
220 unsigned short Flags;
225 // SExpr objects must be created in an arena and cannot be deleted.
226 void *operator new(size_t) = delete;
227 void operator delete(void *) = delete;
231 // Class for owning references to SExprs.
232 // Includes attach/detach logic for counting variable references and lazy
233 // rewriting strategies.
236 SExprRef() : Ptr(nullptr) { }
237 SExprRef(std::nullptr_t P) : Ptr(nullptr) { }
238 SExprRef(SExprRef &&R) : Ptr(R.Ptr) { R.Ptr = nullptr; }
240 // Defined after Variable and Future, below.
241 inline SExprRef(SExpr *P);
244 SExpr *get() { return Ptr; }
245 const SExpr *get() const { return Ptr; }
247 SExpr *operator->() { return get(); }
248 const SExpr *operator->() const { return get(); }
250 SExpr &operator*() { return *Ptr; }
251 const SExpr &operator*() const { return *Ptr; }
253 bool operator==(const SExprRef &R) const { return Ptr == R.Ptr; }
254 bool operator!=(const SExprRef &R) const { return !operator==(R); }
255 bool operator==(const SExpr *P) const { return Ptr == P; }
256 bool operator!=(const SExpr *P) const { return !operator==(P); }
257 bool operator==(std::nullptr_t) const { return Ptr == nullptr; }
258 bool operator!=(std::nullptr_t) const { return Ptr != nullptr; }
260 inline void reset(SExpr *E);
263 inline void attach();
264 inline void detach();
270 // Contains various helper functions for SExprs.
271 namespace ThreadSafetyTIL {
272 static bool isTrivial(SExpr *E) {
273 unsigned Op = E->opcode();
274 return Op == COP_Variable || Op == COP_Literal || Op == COP_LiteralPtr;
283 // A named variable, e.g. "x".
285 // There are two distinct places in which a Variable can appear in the AST.
286 // A variable declaration introduces a new variable, and can occur in 3 places:
287 // Let-expressions: (Let (x = t) u)
288 // Functions: (Function (x : t) u)
289 // Self-applicable functions (SFunction (x) t)
291 // If a variable occurs in any other location, it is a reference to an existing
292 // variable declaration -- e.g. 'x' in (x * y + z). To save space, we don't
293 // allocate a separate AST node for variable references; a reference is just a
294 // pointer to the original declaration.
295 class Variable : public SExpr {
297 static bool classof(const SExpr *E) { return E->opcode() == COP_Variable; }
299 // Let-variable, function parameter, or self-variable
306 // These are defined after SExprRef contructor, below
307 inline Variable(VariableKind K, SExpr *D = nullptr,
308 const clang::ValueDecl *Cvd = nullptr);
309 inline Variable(const clang::ValueDecl *Cvd, SExpr *D = nullptr);
310 inline Variable(const Variable &Vd, SExpr *D);
312 VariableKind kind() const { return static_cast<VariableKind>(Flags); }
314 const StringRef name() const { return Cvdecl ? Cvdecl->getName() : "_x"; }
315 const clang::ValueDecl *clangDecl() const { return Cvdecl; }
317 // Returns the definition (for let vars) or type (for parameter & self vars)
318 SExpr *definition() { return Definition.get(); }
320 void attachVar() const { ++NumUses; }
321 void detachVar() const { assert(NumUses > 0); --NumUses; }
323 unsigned getID() const { return Id; }
324 unsigned getBlockID() const { return BlockID; }
326 void setID(unsigned Bid, unsigned I) {
327 BlockID = static_cast<unsigned short>(Bid);
328 Id = static_cast<unsigned short>(I);
331 template <class V> typename V::R_SExpr traverse(V &Visitor) {
332 // This routine is only called for variable references.
333 return Visitor.reduceVariableRef(this);
336 template <class C> typename C::CType compare(Variable* E, C& Cmp) {
337 return Cmp.compareVariableRefs(this, E);
341 friend class Function;
342 friend class SFunction;
343 friend class BasicBlock;
345 // Function, SFunction, and BasicBlock will reset the kind.
346 void setKind(VariableKind K) { Flags = K; }
348 SExprRef Definition; // The TIL type or definition
349 const clang::ValueDecl *Cvdecl; // The clang declaration for this variable.
351 unsigned short BlockID;
353 mutable unsigned NumUses;
357 // Placeholder for an expression that has not yet been created.
358 // Used to implement lazy copy and rewriting strategies.
359 class Future : public SExpr {
361 static bool classof(const SExpr *E) { return E->opcode() == COP_Future; }
370 SExpr(COP_Future), Status(FS_pending), Result(nullptr), Location(nullptr)
372 virtual ~Future() = delete;
374 // Registers the location in the AST where this future is stored.
375 // Forcing the future will automatically update the AST.
376 static inline void registerLocation(SExprRef *Member) {
377 if (Future *F = dyn_cast_or_null<Future>(Member->get()))
378 F->Location = Member;
381 // A lazy rewriting strategy should subclass Future and override this method.
382 virtual SExpr *create() { return nullptr; }
384 // Return the result of this future if it exists, otherwise return null.
385 SExpr *maybeGetResult() {
389 // Return the result of this future; forcing it if necessary.
396 return nullptr; // infinite loop; illegal recursion.
402 template <class V> typename V::R_SExpr traverse(V &Visitor) {
403 assert(Result && "Cannot traverse Future that has not been forced.");
404 return Visitor.traverse(Result);
407 template <class C> typename C::CType compare(Future* E, C& Cmp) {
408 if (!Result || !E->Result)
409 return Cmp.comparePointers(this, E);
410 return Cmp.compare(Result, E->Result);
424 void SExprRef::attach() {
428 TIL_Opcode Op = Ptr->opcode();
429 if (Op == COP_Variable) {
430 cast<Variable>(Ptr)->attachVar();
432 else if (Op == COP_Future) {
433 cast<Future>(Ptr)->registerLocation(this);
437 void SExprRef::detach() {
438 if (Ptr && Ptr->opcode() == COP_Variable) {
439 cast<Variable>(Ptr)->detachVar();
443 SExprRef::SExprRef(SExpr *P) : Ptr(P) {
448 SExprRef::~SExprRef() {
452 void SExprRef::reset(SExpr *P) {
461 Variable::Variable(VariableKind K, SExpr *D, const clang::ValueDecl *Cvd)
462 : SExpr(COP_Variable), Definition(D), Cvdecl(Cvd),
463 BlockID(0), Id(0), NumUses(0) {
467 Variable::Variable(const clang::ValueDecl *Cvd, SExpr *D)
468 : SExpr(COP_Variable), Definition(D), Cvdecl(Cvd),
469 BlockID(0), Id(0), NumUses(0) {
473 Variable::Variable(const Variable &Vd, SExpr *D) // rewrite constructor
474 : SExpr(Vd), Definition(D), Cvdecl(Vd.Cvdecl),
475 BlockID(0), Id(0), NumUses(0) {
480 void Future::force() {
481 Status = FS_evaluating;
492 // Placeholder for C++ expressions that cannot be represented in the TIL.
493 class Undefined : public SExpr {
495 static bool classof(const SExpr *E) { return E->opcode() == COP_Undefined; }
497 Undefined(const clang::Stmt *S = nullptr) : SExpr(COP_Undefined), Cstmt(S) {}
498 Undefined(const Undefined &U) : SExpr(U), Cstmt(U.Cstmt) {}
500 template <class V> typename V::R_SExpr traverse(V &Visitor) {
501 return Visitor.reduceUndefined(*this);
504 template <class C> typename C::CType compare(Undefined* E, C& Cmp) {
505 return Cmp.comparePointers(Cstmt, E->Cstmt);
509 const clang::Stmt *Cstmt;
513 // Placeholder for a wildcard that matches any other expression.
514 class Wildcard : public SExpr {
516 static bool classof(const SExpr *E) { return E->opcode() == COP_Wildcard; }
518 Wildcard() : SExpr(COP_Wildcard) {}
519 Wildcard(const Wildcard &W) : SExpr(W) {}
521 template <class V> typename V::R_SExpr traverse(V &Visitor) {
522 return Visitor.reduceWildcard(*this);
525 template <class C> typename C::CType compare(Wildcard* E, C& Cmp) {
526 return Cmp.trueResult();
531 // Base class for literal values.
532 class Literal : public SExpr {
534 static bool classof(const SExpr *E) { return E->opcode() == COP_Literal; }
536 Literal(const clang::Expr *C) : SExpr(COP_Literal), Cexpr(C) {}
537 Literal(const Literal &L) : SExpr(L), Cexpr(L.Cexpr) {}
539 // The clang expression for this literal.
540 const clang::Expr *clangExpr() { return Cexpr; }
542 template <class V> typename V::R_SExpr traverse(V &Visitor) {
543 return Visitor.reduceLiteral(*this);
546 template <class C> typename C::CType compare(Literal* E, C& Cmp) {
547 // TODO -- use value, not pointer equality
548 return Cmp.comparePointers(Cexpr, E->Cexpr);
552 const clang::Expr *Cexpr;
556 // Literal pointer to an object allocated in memory.
557 // At compile time, pointer literals are represented by symbolic names.
558 class LiteralPtr : public SExpr {
560 static bool classof(const SExpr *E) { return E->opcode() == COP_LiteralPtr; }
562 LiteralPtr(const clang::ValueDecl *D) : SExpr(COP_LiteralPtr), Cvdecl(D) {}
563 LiteralPtr(const LiteralPtr &R) : SExpr(R), Cvdecl(R.Cvdecl) {}
565 // The clang declaration for the value that this pointer points to.
566 const clang::ValueDecl *clangDecl() { return Cvdecl; }
568 template <class V> typename V::R_SExpr traverse(V &Visitor) {
569 return Visitor.reduceLiteralPtr(*this);
572 template <class C> typename C::CType compare(LiteralPtr* E, C& Cmp) {
573 return Cmp.comparePointers(Cvdecl, E->Cvdecl);
577 const clang::ValueDecl *Cvdecl;
584 // A function -- a.k.a. lambda abstraction.
585 // Functions with multiple arguments are created by currying,
586 // e.g. (function (x: Int) (function (y: Int) (add x y)))
587 class Function : public SExpr {
589 static bool classof(const SExpr *E) { return E->opcode() == COP_Function; }
591 Function(Variable *Vd, SExpr *Bd)
592 : SExpr(COP_Function), VarDecl(Vd), Body(Bd) {
593 Vd->setKind(Variable::VK_Fun);
595 Function(const Function &F, Variable *Vd, SExpr *Bd) // rewrite constructor
596 : SExpr(F), VarDecl(Vd), Body(Bd) {
597 Vd->setKind(Variable::VK_Fun);
600 Variable *variableDecl() { return VarDecl; }
601 const Variable *variableDecl() const { return VarDecl; }
603 SExpr *body() { return Body.get(); }
604 const SExpr *body() const { return Body.get(); }
606 template <class V> typename V::R_SExpr traverse(V &Visitor) {
607 // This is a variable declaration, so traverse the definition.
608 typename V::R_SExpr E0 = Visitor.traverse(VarDecl->Definition, TRV_Lazy);
609 // Tell the rewriter to enter the scope of the function.
610 Variable *Nvd = Visitor.enterScope(*VarDecl, E0);
611 typename V::R_SExpr E1 = Visitor.traverse(Body);
612 Visitor.exitScope(*VarDecl);
613 return Visitor.reduceFunction(*this, Nvd, E1);
616 template <class C> typename C::CType compare(Function* E, C& Cmp) {
617 typename C::CType Ct =
618 Cmp.compare(VarDecl->definition(), E->VarDecl->definition());
621 Cmp.enterScope(variableDecl(), E->variableDecl());
622 Ct = Cmp.compare(body(), E->body());
633 // A self-applicable function.
634 // A self-applicable function can be applied to itself. It's useful for
635 // implementing objects and late binding
636 class SFunction : public SExpr {
638 static bool classof(const SExpr *E) { return E->opcode() == COP_SFunction; }
640 SFunction(Variable *Vd, SExpr *B)
641 : SExpr(COP_SFunction), VarDecl(Vd), Body(B) {
642 assert(Vd->Definition == nullptr);
643 Vd->setKind(Variable::VK_SFun);
644 Vd->Definition.reset(this);
646 SFunction(const SFunction &F, Variable *Vd, SExpr *B) // rewrite constructor
650 assert(Vd->Definition == nullptr);
651 Vd->setKind(Variable::VK_SFun);
652 Vd->Definition.reset(this);
655 Variable *variableDecl() { return VarDecl; }
656 const Variable *variableDecl() const { return VarDecl; }
658 SExpr *body() { return Body.get(); }
659 const SExpr *body() const { return Body.get(); }
661 template <class V> typename V::R_SExpr traverse(V &Visitor) {
662 // A self-variable points to the SFunction itself.
663 // A rewrite must introduce the variable with a null definition, and update
664 // it after 'this' has been rewritten.
665 Variable *Nvd = Visitor.enterScope(*VarDecl, nullptr /* def */);
666 typename V::R_SExpr E1 = Visitor.traverse(Body);
667 Visitor.exitScope(*VarDecl);
668 // A rewrite operation will call SFun constructor to set Vvd->Definition.
669 return Visitor.reduceSFunction(*this, Nvd, E1);
672 template <class C> typename C::CType compare(SFunction* E, C& Cmp) {
673 Cmp.enterScope(variableDecl(), E->variableDecl());
674 typename C::CType Ct = Cmp.compare(body(), E->body());
685 // A block of code -- e.g. the body of a function.
686 class Code : public SExpr {
688 static bool classof(const SExpr *E) { return E->opcode() == COP_Code; }
690 Code(SExpr *T, SExpr *B) : SExpr(COP_Code), ReturnType(T), Body(B) {}
691 Code(const Code &C, SExpr *T, SExpr *B) // rewrite constructor
692 : SExpr(C), ReturnType(T), Body(B) {}
694 SExpr *returnType() { return ReturnType.get(); }
695 const SExpr *returnType() const { return ReturnType.get(); }
697 SExpr *body() { return Body.get(); }
698 const SExpr *body() const { return Body.get(); }
700 template <class V> typename V::R_SExpr traverse(V &Visitor) {
701 typename V::R_SExpr Nt = Visitor.traverse(ReturnType, TRV_Lazy);
702 typename V::R_SExpr Nb = Visitor.traverse(Body, TRV_Lazy);
703 return Visitor.reduceCode(*this, Nt, Nb);
706 template <class C> typename C::CType compare(Code* E, C& Cmp) {
707 typename C::CType Ct = Cmp.compare(returnType(), E->returnType());
710 return Cmp.compare(body(), E->body());
719 // Apply an argument to a function
720 class Apply : public SExpr {
722 static bool classof(const SExpr *E) { return E->opcode() == COP_Apply; }
724 Apply(SExpr *F, SExpr *A) : SExpr(COP_Apply), Fun(F), Arg(A) {}
725 Apply(const Apply &A, SExpr *F, SExpr *Ar) // rewrite constructor
726 : SExpr(A), Fun(F), Arg(Ar)
729 SExpr *fun() { return Fun.get(); }
730 const SExpr *fun() const { return Fun.get(); }
732 SExpr *arg() { return Arg.get(); }
733 const SExpr *arg() const { return Arg.get(); }
735 template <class V> typename V::R_SExpr traverse(V &Visitor) {
736 typename V::R_SExpr Nf = Visitor.traverse(Fun);
737 typename V::R_SExpr Na = Visitor.traverse(Arg);
738 return Visitor.reduceApply(*this, Nf, Na);
741 template <class C> typename C::CType compare(Apply* E, C& Cmp) {
742 typename C::CType Ct = Cmp.compare(fun(), E->fun());
745 return Cmp.compare(arg(), E->arg());
754 // Apply a self-argument to a self-applicable function
755 class SApply : public SExpr {
757 static bool classof(const SExpr *E) { return E->opcode() == COP_SApply; }
759 SApply(SExpr *Sf, SExpr *A = nullptr)
760 : SExpr(COP_SApply), Sfun(Sf), Arg(A)
762 SApply(SApply &A, SExpr *Sf, SExpr *Ar = nullptr) // rewrite constructor
763 : SExpr(A), Sfun(Sf), Arg(Ar)
766 SExpr *sfun() { return Sfun.get(); }
767 const SExpr *sfun() const { return Sfun.get(); }
769 SExpr *arg() { return Arg.get() ? Arg.get() : Sfun.get(); }
770 const SExpr *arg() const { return Arg.get() ? Arg.get() : Sfun.get(); }
772 bool isDelegation() const { return Arg == nullptr; }
774 template <class V> typename V::R_SExpr traverse(V &Visitor) {
775 typename V::R_SExpr Nf = Visitor.traverse(Sfun);
776 typename V::R_SExpr Na = Arg.get() ? Visitor.traverse(Arg) : nullptr;
777 return Visitor.reduceSApply(*this, Nf, Na);
780 template <class C> typename C::CType compare(SApply* E, C& Cmp) {
781 typename C::CType Ct = Cmp.compare(sfun(), E->sfun());
782 if (Cmp.notTrue(Ct) || (!arg() && !E->arg()))
784 return Cmp.compare(arg(), E->arg());
793 // Project a named slot from a C++ struct or class.
794 class Project : public SExpr {
796 static bool classof(const SExpr *E) { return E->opcode() == COP_Project; }
798 Project(SExpr *R, clang::ValueDecl *Cvd)
799 : SExpr(COP_Project), Rec(R), Cvdecl(Cvd) {}
800 Project(const Project &P, SExpr *R) : SExpr(P), Rec(R), Cvdecl(P.Cvdecl) {}
802 SExpr *record() { return Rec.get(); }
803 const SExpr *record() const { return Rec.get(); }
805 const clang::ValueDecl *clangValueDecl() const { return Cvdecl; }
807 StringRef slotName() const { return Cvdecl->getName(); }
809 template <class V> typename V::R_SExpr traverse(V &Visitor) {
810 typename V::R_SExpr Nr = Visitor.traverse(Rec);
811 return Visitor.reduceProject(*this, Nr);
814 template <class C> typename C::CType compare(Project* E, C& Cmp) {
815 typename C::CType Ct = Cmp.compare(record(), E->record());
818 return Cmp.comparePointers(Cvdecl, E->Cvdecl);
823 clang::ValueDecl *Cvdecl;
827 // Call a function (after all arguments have been applied).
828 class Call : public SExpr {
830 static bool classof(const SExpr *E) { return E->opcode() == COP_Call; }
832 Call(SExpr *T, const clang::CallExpr *Ce = nullptr)
833 : SExpr(COP_Call), Target(T), Cexpr(Ce) {}
834 Call(const Call &C, SExpr *T) : SExpr(C), Target(T), Cexpr(C.Cexpr) {}
836 SExpr *target() { return Target.get(); }
837 const SExpr *target() const { return Target.get(); }
839 const clang::CallExpr *clangCallExpr() { return Cexpr; }
841 template <class V> typename V::R_SExpr traverse(V &Visitor) {
842 typename V::R_SExpr Nt = Visitor.traverse(Target);
843 return Visitor.reduceCall(*this, Nt);
846 template <class C> typename C::CType compare(Call* E, C& Cmp) {
847 return Cmp.compare(target(), E->target());
852 const clang::CallExpr *Cexpr;
856 // Allocate memory for a new value on the heap or stack.
857 class Alloc : public SExpr {
859 static bool classof(const SExpr *E) { return E->opcode() == COP_Call; }
866 Alloc(SExpr* D, AllocKind K) : SExpr(COP_Alloc), Dtype(D) {
869 Alloc(const Alloc &A, SExpr* Dt) : SExpr(A), Dtype(Dt) {
873 AllocKind kind() const { return static_cast<AllocKind>(Flags); }
875 SExpr* dataType() { return Dtype.get(); }
876 const SExpr* dataType() const { return Dtype.get(); }
878 template <class V> typename V::R_SExpr traverse(V &Visitor) {
879 typename V::R_SExpr Nd = Visitor.traverse(Dtype);
880 return Visitor.reduceAlloc(*this, Nd);
883 template <class C> typename C::CType compare(Alloc* E, C& Cmp) {
884 typename C::CType Ct = Cmp.compareIntegers(kind(), E->kind());
887 return Cmp.compare(dataType(), E->dataType());
895 // Load a value from memory.
896 class Load : public SExpr {
898 static bool classof(const SExpr *E) { return E->opcode() == COP_Load; }
900 Load(SExpr *P) : SExpr(COP_Load), Ptr(P) {}
901 Load(const Load &L, SExpr *P) : SExpr(L), Ptr(P) {}
903 SExpr *pointer() { return Ptr.get(); }
904 const SExpr *pointer() const { return Ptr.get(); }
906 template <class V> typename V::R_SExpr traverse(V &Visitor) {
907 typename V::R_SExpr Np = Visitor.traverse(Ptr);
908 return Visitor.reduceLoad(*this, Np);
911 template <class C> typename C::CType compare(Load* E, C& Cmp) {
912 return Cmp.compare(pointer(), E->pointer());
920 // Store a value to memory.
921 class Store : public SExpr {
923 static bool classof(const SExpr *E) { return E->opcode() == COP_Store; }
925 Store(SExpr *P, SExpr *V) : SExpr(COP_Store), Dest(P), Source(V) {}
926 Store(const Store &S, SExpr *P, SExpr *V) : SExpr(S), Dest(P), Source(V) {}
928 SExpr *destination() { return Dest.get(); } // Address to store to
929 const SExpr *destination() const { return Dest.get(); }
931 SExpr *source() { return Source.get(); } // Value to store
932 const SExpr *source() const { return Source.get(); }
934 template <class V> typename V::R_SExpr traverse(V &Visitor) {
935 typename V::R_SExpr Np = Visitor.traverse(Dest);
936 typename V::R_SExpr Nv = Visitor.traverse(Source);
937 return Visitor.reduceStore(*this, Np, Nv);
940 template <class C> typename C::CType compare(Store* E, C& Cmp) {
941 typename C::CType Ct = Cmp.compare(destination(), E->destination());
944 return Cmp.compare(source(), E->source());
952 // Simple unary operation -- e.g. !, ~, etc.
953 class UnaryOp : public SExpr {
955 static bool classof(const SExpr *E) { return E->opcode() == COP_UnaryOp; }
957 UnaryOp(TIL_UnaryOpcode Op, SExpr *E) : SExpr(COP_UnaryOp), Expr0(E) {
960 UnaryOp(const UnaryOp &U, SExpr *E) : SExpr(U) { Flags = U.Flags; }
962 TIL_UnaryOpcode unaryOpcode() { return static_cast<TIL_UnaryOpcode>(Flags); }
964 SExpr *expr() { return Expr0.get(); }
965 const SExpr *expr() const { return Expr0.get(); }
967 template <class V> typename V::R_SExpr traverse(V &Visitor) {
968 typename V::R_SExpr Ne = Visitor.traverse(Expr0);
969 return Visitor.reduceUnaryOp(*this, Ne);
972 template <class C> typename C::CType compare(UnaryOp* E, C& Cmp) {
973 typename C::CType Ct =
974 Cmp.compareIntegers(unaryOpcode(), E->unaryOpcode());
977 return Cmp.compare(expr(), E->expr());
985 // Simple binary operation -- e.g. +, -, etc.
986 class BinaryOp : public SExpr {
988 static bool classof(const SExpr *E) { return E->opcode() == COP_BinaryOp; }
990 BinaryOp(TIL_BinaryOpcode Op, SExpr *E0, SExpr *E1)
991 : SExpr(COP_BinaryOp), Expr0(E0), Expr1(E1) {
994 BinaryOp(const BinaryOp &B, SExpr *E0, SExpr *E1)
995 : SExpr(B), Expr0(E0), Expr1(E1) {
999 TIL_BinaryOpcode binaryOpcode() {
1000 return static_cast<TIL_BinaryOpcode>(Flags);
1003 SExpr *expr0() { return Expr0.get(); }
1004 const SExpr *expr0() const { return Expr0.get(); }
1006 SExpr *expr1() { return Expr1.get(); }
1007 const SExpr *expr1() const { return Expr1.get(); }
1009 template <class V> typename V::R_SExpr traverse(V &Visitor) {
1010 typename V::R_SExpr Ne0 = Visitor.traverse(Expr0);
1011 typename V::R_SExpr Ne1 = Visitor.traverse(Expr1);
1012 return Visitor.reduceBinaryOp(*this, Ne0, Ne1);
1015 template <class C> typename C::CType compare(BinaryOp* E, C& Cmp) {
1016 typename C::CType Ct =
1017 Cmp.compareIntegers(binaryOpcode(), E->binaryOpcode());
1018 if (Cmp.notTrue(Ct))
1020 Ct = Cmp.compare(expr0(), E->expr0());
1021 if (Cmp.notTrue(Ct))
1023 return Cmp.compare(expr1(), E->expr1());
1033 class Cast : public SExpr {
1035 static bool classof(const SExpr *E) { return E->opcode() == COP_Cast; }
1037 Cast(TIL_CastOpcode Op, SExpr *E) : SExpr(COP_Cast), Expr0(E) { Flags = Op; }
1038 Cast(const Cast &C, SExpr *E) : SExpr(C), Expr0(E) { Flags = C.Flags; }
1040 TIL_BinaryOpcode castOpcode() {
1041 return static_cast<TIL_BinaryOpcode>(Flags);
1044 SExpr *expr() { return Expr0.get(); }
1045 const SExpr *expr() const { return Expr0.get(); }
1047 template <class V> typename V::R_SExpr traverse(V &Visitor) {
1048 typename V::R_SExpr Ne = Visitor.traverse(Expr0);
1049 return Visitor.reduceCast(*this, Ne);
1052 template <class C> typename C::CType compare(Cast* E, C& Cmp) {
1053 typename C::CType Ct =
1054 Cmp.compareIntegers(castOpcode(), E->castOpcode());
1055 if (Cmp.notTrue(Ct))
1057 return Cmp.compare(expr(), E->expr());
1070 // An SCFG is a control-flow graph. It consists of a set of basic blocks, each
1071 // of which terminates in a branch to another basic block. There is one
1072 // entry point, and one exit point.
1073 class SCFG : public SExpr {
1075 typedef SimpleArray<BasicBlock*> BlockArray;
1077 static bool classof(const SExpr *E) { return E->opcode() == COP_SCFG; }
1079 SCFG(MemRegionRef A, unsigned Nblocks)
1080 : SExpr(COP_SCFG), Blocks(A, Nblocks), Entry(nullptr), Exit(nullptr) {}
1081 SCFG(const SCFG &Cfg, BlockArray &&Ba) // steals memory from Ba
1083 Blocks(std::move(Ba)),
1086 // TODO: set entry and exit!
1089 typedef BlockArray::iterator iterator;
1090 typedef BlockArray::const_iterator const_iterator;
1092 iterator begin() { return Blocks.begin(); }
1093 iterator end() { return Blocks.end(); }
1095 const_iterator cbegin() const { return Blocks.cbegin(); }
1096 const_iterator cend() const { return Blocks.cend(); }
1098 BasicBlock *entry() const { return Entry; }
1099 BasicBlock *exit() const { return Exit; }
1101 void add(BasicBlock *BB) { Blocks.push_back(BB); }
1102 void setEntry(BasicBlock *BB) { Entry = BB; }
1103 void setExit(BasicBlock *BB) { Exit = BB; }
1105 template <class V> typename V::R_SExpr traverse(V &Visitor);
1107 template <class C> typename C::CType compare(SCFG* E, C& Cmp) {
1108 // TODO -- implement CFG comparisons
1109 return Cmp.comparePointers(this, E);
1119 // A basic block is part of an SCFG, and can be treated as a function in
1120 // continuation passing style. It consists of a sequence of phi nodes, which
1121 // are "arguments" to the function, followed by a sequence of instructions.
1122 // Both arguments and instructions define new variables. It ends with a
1123 // branch or goto to another basic block in the same SCFG.
1126 typedef SimpleArray<Variable*> VarArray;
1128 BasicBlock(MemRegionRef A, unsigned Nargs, unsigned Nins,
1129 SExpr *Term = nullptr)
1130 : BlockID(0), Parent(nullptr), Args(A, Nargs), Instrs(A, Nins),
1132 BasicBlock(const BasicBlock &B, VarArray &&As, VarArray &&Is, SExpr *T)
1133 : BlockID(0), Parent(nullptr),
1134 Args(std::move(As)), Instrs(std::move(Is)), Terminator(T)
1137 unsigned blockID() const { return BlockID; }
1138 BasicBlock *parent() const { return Parent; }
1140 const VarArray &arguments() const { return Args; }
1141 VarArray &arguments() { return Args; }
1143 const VarArray &instructions() const { return Instrs; }
1144 VarArray &instructions() { return Instrs; }
1146 const SExpr *terminator() const { return Terminator.get(); }
1147 SExpr *terminator() { return Terminator.get(); }
1149 void setParent(BasicBlock *P) { Parent = P; }
1150 void setBlockID(unsigned i) { BlockID = i; }
1151 void setTerminator(SExpr *E) { Terminator.reset(E); }
1152 void addArgument(Variable *V) { Args.push_back(V); }
1153 void addInstr(Variable *V) { Args.push_back(V); }
1155 template <class V> BasicBlock *traverse(V &Visitor) {
1156 typename V::template Container<Variable*> Nas(Visitor, Args.size());
1157 typename V::template Container<Variable*> Nis(Visitor, Instrs.size());
1159 for (auto A : Args) {
1160 typename V::R_SExpr Ne = Visitor.traverse(A->Definition);
1161 Variable *Nvd = Visitor.enterScope(*A, Ne);
1164 for (auto I : Instrs) {
1165 typename V::R_SExpr Ne = Visitor.traverse(I->Definition);
1166 Variable *Nvd = Visitor.enterScope(*I, Ne);
1169 typename V::R_SExpr Nt = Visitor.traverse(Terminator);
1171 // TODO: use reverse iterator
1172 for (unsigned J = 0, JN = Instrs.size(); J < JN; ++J)
1173 Visitor.exitScope(*Instrs[JN-J]);
1174 for (unsigned I = 0, IN = Instrs.size(); I < IN; ++I)
1175 Visitor.exitScope(*Args[IN-I]);
1177 return Visitor.reduceBasicBlock(*this, Nas, Nis, Nt);
1180 template <class C> typename C::CType compare(BasicBlock* E, C& Cmp) {
1181 // TODO: implement CFG comparisons
1182 return Cmp.comparePointers(this, E);
1189 BasicBlock *Parent; // The parent block is the enclosing lexical scope.
1190 // The parent dominates this block.
1191 VarArray Args; // Phi nodes
1193 SExprRef Terminator;
1198 typename V::R_SExpr SCFG::traverse(V &Visitor) {
1199 Visitor.enterCFG(*this);
1200 typename V::template Container<BasicBlock *> Bbs(Visitor, Blocks.size());
1201 for (auto B : Blocks) {
1202 BasicBlock *Nbb = B->traverse(Visitor);
1205 Visitor.exitCFG(*this);
1206 return Visitor.reduceSCFG(*this, Bbs);
1211 class Phi : public SExpr {
1213 // TODO: change to SExprRef
1214 typedef SimpleArray<SExpr*> ValArray;
1216 static bool classof(const SExpr *E) { return E->opcode() == COP_Phi; }
1218 Phi(MemRegionRef A, unsigned Nvals)
1219 : SExpr(COP_Phi), Values(A, Nvals)
1221 Phi(const Phi &P, ValArray &&Vs) // steals memory of Vs
1222 : SExpr(COP_Phi), Values(std::move(Vs))
1225 const ValArray &values() const { return Values; }
1226 ValArray &values() { return Values; }
1228 template <class V> typename V::R_SExpr traverse(V &Visitor) {
1229 typename V::template Container<typename V::R_SExpr> Nvs(Visitor,
1231 for (auto Val : Values) {
1232 typename V::R_SExpr Nv = Visitor.traverse(Val);
1235 return Visitor.reducePhi(*this, Nvs);
1238 template <class C> typename C::CType compare(Phi* E, C& Cmp) {
1239 // TODO -- implement CFG comparisons
1240 return Cmp.comparePointers(this, E);
1248 class Goto : public SExpr {
1250 static bool classof(const SExpr *E) { return E->opcode() == COP_Goto; }
1252 Goto(BasicBlock *B, unsigned Index)
1253 : SExpr(COP_Goto), TargetBlock(B), Index(0) {}
1254 Goto(const Goto &G, BasicBlock *B, unsigned I)
1255 : SExpr(COP_Goto), TargetBlock(B), Index(I) {}
1257 BasicBlock *targetBlock() const { return TargetBlock; }
1258 unsigned index() const { return Index; }
1260 template <class V> typename V::R_SExpr traverse(V &Visitor) {
1261 // TODO -- rewrite indices properly
1262 BasicBlock *Ntb = Visitor.reduceBasicBlockRef(TargetBlock);
1263 return Visitor.reduceGoto(*this, Ntb, Index);
1266 template <class C> typename C::CType compare(Goto* E, C& Cmp) {
1267 // TODO -- implement CFG comparisons
1268 return Cmp.comparePointers(this, E);
1272 BasicBlock *TargetBlock;
1273 unsigned Index; // Index into Phi nodes of target block.
1277 class Branch : public SExpr {
1279 static bool classof(const SExpr *E) { return E->opcode() == COP_Branch; }
1281 Branch(SExpr *C, BasicBlock *T, BasicBlock *E)
1282 : SExpr(COP_Branch), Condition(C), ThenBlock(T), ElseBlock(E) {}
1283 Branch(const Branch &Br, SExpr *C, BasicBlock *T, BasicBlock *E)
1284 : SExpr(COP_Branch), Condition(C), ThenBlock(T), ElseBlock(E) {}
1286 SExpr *condition() { return Condition; }
1287 BasicBlock *thenBlock() { return ThenBlock; }
1288 BasicBlock *elseBlock() { return ElseBlock; }
1290 template <class V> typename V::R_SExpr traverse(V &Visitor) {
1291 typename V::R_SExpr Nc = Visitor.traverse(Condition);
1292 BasicBlock *Ntb = Visitor.reduceBasicBlockRef(ThenBlock);
1293 BasicBlock *Nte = Visitor.reduceBasicBlockRef(ElseBlock);
1294 return Visitor.reduceBranch(*this, Nc, Ntb, Nte);
1297 template <class C> typename C::CType compare(Branch* E, C& Cmp) {
1298 // TODO -- implement CFG comparisons
1299 return Cmp.comparePointers(this, E);
1304 BasicBlock *ThenBlock;
1305 BasicBlock *ElseBlock;
1310 // Defines an interface used to traverse SExprs. Traversals have been made as
1311 // generic as possible, and are intended to handle any kind of pass over the
1312 // AST, e.g. visiters, copying, non-destructive rewriting, destructive
1313 // (in-place) rewriting, hashing, typing, etc.
1315 // Traversals implement the functional notion of a "fold" operation on SExprs.
1316 // Each SExpr class provides a traverse method, which does the following:
1317 // * e->traverse(v):
1318 // // compute a result r_i for each subexpression e_i
1319 // for (i = 1..n) r_i = v.traverse(e_i);
1320 // // combine results into a result for e, where X is the class of e
1321 // return v.reduceX(*e, r_1, .. r_n).
1323 // A visitor can control the traversal by overriding the following methods:
1325 // return v.traverseByCase(e), which returns v.traverseX(e)
1326 // * v.traverseX(e): (X is the class of e)
1327 // return e->traverse(v).
1328 // * v.reduceX(*e, r_1, .. r_n):
1329 // compute a result for a node of type X
1331 // The reduceX methods control the kind of traversal (visitor, copy, etc.).
1332 // These are separated into a separate class R for the purpose of code reuse.
1333 // The full reducer interface also has methods to handle scopes
1334 template <class Self, class R> class Traversal : public R {
1336 Self *self() { return reinterpret_cast<Self *>(this); }
1338 // Traverse an expression -- returning a result of type R_SExpr.
1339 // Override this method to do something for every expression, regardless
1340 // of which kind it is. TraversalKind indicates the context in which
1341 // the expression occurs, and can be:
1343 // TRV_Lazy -- e may need to be traversed lazily, using a Future.
1344 // TRV_Tail -- e occurs in a tail position
1345 typename R::R_SExpr traverse(SExprRef &E, TraversalKind K = TRV_Normal) {
1346 return traverse(E.get(), K);
1349 typename R::R_SExpr traverse(SExpr *E, TraversalKind K = TRV_Normal) {
1350 return traverseByCase(E);
1353 // Helper method to call traverseX(e) on the appropriate type.
1354 typename R::R_SExpr traverseByCase(SExpr *E) {
1355 switch (E->opcode()) {
1356 #define TIL_OPCODE_DEF(X) \
1358 return self()->traverse##X(cast<X>(E));
1359 #include "clang/Analysis/Analyses/ThreadSafetyOps.def"
1360 #undef TIL_OPCODE_DEF
1362 return self()->reduceNull();
1366 // Traverse e, by static dispatch on the type "X" of e.
1367 // Override these methods to do something for a particular kind of term.
1368 #define TIL_OPCODE_DEF(X) \
1369 typename R::R_SExpr traverse##X(X *e) { return e->traverse(*self()); }
1370 #include "clang/Analysis/Analyses/ThreadSafetyOps.def"
1371 #undef TIL_OPCODE_DEF
1375 // Implements a Reducer that makes a deep copy of an SExpr.
1376 // The default behavior of reduce##X(...) is to create a copy of the original.
1377 // Subclasses can override reduce##X to implement non-destructive rewriting
1383 void setArena(MemRegionRef A) { Arena = A; }
1385 // R_SExpr is the result type for a traversal.
1386 // A copy or non-destructive rewrite returns a newly allocated term.
1387 typedef SExpr *R_SExpr;
1389 // Container is a minimal interface used to store results when traversing
1390 // SExprs of variable arity, such as Phi, Goto, and SCFG.
1391 template <class T> class Container {
1393 // Allocate a new container with a capacity for n elements.
1394 Container(CopyReducer &R, unsigned N) : Elems(R.Arena, N) {}
1396 // Push a new element onto the container.
1397 void push_back(T E) { Elems.push_back(E); }
1400 friend class CopyReducer;
1401 SimpleArray<T> Elems;
1405 R_SExpr reduceNull() {
1408 // R_SExpr reduceFuture(...) is never used.
1410 R_SExpr reduceUndefined(Undefined &Orig) {
1411 return new (Arena) Undefined(Orig);
1413 R_SExpr reduceWildcard(Wildcard &Orig) {
1414 return new (Arena) Wildcard(Orig);
1417 R_SExpr reduceLiteral(Literal &Orig) {
1418 return new (Arena) Literal(Orig);
1420 R_SExpr reduceLiteralPtr(LiteralPtr &Orig) {
1421 return new (Arena) LiteralPtr(Orig);
1424 R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) {
1425 return new (Arena) Function(Orig, Nvd, E0);
1427 R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) {
1428 return new (Arena) SFunction(Orig, Nvd, E0);
1430 R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) {
1431 return new (Arena) Code(Orig, E0, E1);
1434 R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) {
1435 return new (Arena) Apply(Orig, E0, E1);
1437 R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) {
1438 return new (Arena) SApply(Orig, E0, E1);
1440 R_SExpr reduceProject(Project &Orig, R_SExpr E0) {
1441 return new (Arena) Project(Orig, E0);
1443 R_SExpr reduceCall(Call &Orig, R_SExpr E0) {
1444 return new (Arena) Call(Orig, E0);
1447 R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) {
1448 return new (Arena) Alloc(Orig, E0);
1450 R_SExpr reduceLoad(Load &Orig, R_SExpr E0) {
1451 return new (Arena) Load(Orig, E0);
1453 R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) {
1454 return new (Arena) Store(Orig, E0, E1);
1456 R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) {
1457 return new (Arena) UnaryOp(Orig, E0);
1459 R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) {
1460 return new (Arena) BinaryOp(Orig, E0, E1);
1462 R_SExpr reduceCast(Cast &Orig, R_SExpr E0) {
1463 return new (Arena) Cast(Orig, E0);
1466 R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> &Bbs) {
1467 return new (Arena) SCFG(Orig, std::move(Bbs.Elems));
1469 R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) {
1470 return new (Arena) Phi(Orig, std::move(As.Elems));
1472 R_SExpr reduceGoto(Goto &Orig, BasicBlock *B, unsigned Index) {
1473 return new (Arena) Goto(Orig, B, Index);
1475 R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) {
1476 return new (Arena) Branch(O, C, B0, B1);
1479 BasicBlock *reduceBasicBlock(BasicBlock &Orig, Container<Variable *> &As,
1480 Container<Variable *> &Is, R_SExpr T) {
1481 return new (Arena) BasicBlock(Orig, std::move(As.Elems),
1482 std::move(Is.Elems), T);
1485 // Create a new variable from orig, and push it onto the lexical scope.
1486 Variable *enterScope(Variable &Orig, R_SExpr E0) {
1487 return new (Arena) Variable(Orig, E0);
1489 // Exit the lexical scope of orig.
1490 void exitScope(const Variable &Orig) {}
1492 void enterCFG(SCFG &Cfg) {}
1493 void exitCFG(SCFG &Cfg) {}
1495 // Map Variable references to their rewritten definitions.
1496 Variable *reduceVariableRef(Variable *Ovd) { return Ovd; }
1498 // Map BasicBlock references to their rewritten defs.
1499 BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; }
1506 class SExprCopier : public Traversal<SExprCopier, CopyReducer> {
1508 SExprCopier(MemRegionRef A) { setArena(A); }
1510 // Create a copy of e in region a.
1511 static SExpr *copy(SExpr *E, MemRegionRef A) {
1512 SExprCopier Copier(A);
1513 return Copier.traverse(E);
1518 // Implements a Reducer that visits each subexpression, and returns either
1520 class VisitReducer {
1524 // A visitor returns a bool, representing success or failure.
1525 typedef bool R_SExpr;
1527 // A visitor "container" is a single bool, which accumulates success.
1528 template <class T> class Container {
1530 Container(VisitReducer &R, unsigned N) : Success(true) {}
1531 void push_back(bool E) { Success = Success && E; }
1534 friend class VisitReducer;
1539 R_SExpr reduceNull() { return true; }
1540 R_SExpr reduceUndefined(Undefined &Orig) { return true; }
1541 R_SExpr reduceWildcard(Wildcard &Orig) { return true; }
1543 R_SExpr reduceLiteral(Literal &Orig) { return true; }
1544 R_SExpr reduceLiteralPtr(Literal &Orig) { return true; }
1546 R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) {
1549 R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) {
1552 R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) {
1555 R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) {
1558 R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) {
1561 R_SExpr reduceProject(Project &Orig, R_SExpr E0) { return E0; }
1562 R_SExpr reduceCall(Call &Orig, R_SExpr E0) { return E0; }
1563 R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) { return E0; }
1564 R_SExpr reduceLoad(Load &Orig, R_SExpr E0) { return E0; }
1565 R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) { return E0 && E1; }
1566 R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) { return E0; }
1567 R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) {
1570 R_SExpr reduceCast(Cast &Orig, R_SExpr E0) { return E0; }
1572 R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> Bbs) {
1575 R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) {
1578 R_SExpr reduceGoto(Goto &Orig, BasicBlock *B, unsigned Index) {
1581 R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) {
1585 BasicBlock *reduceBasicBlock(BasicBlock &Orig, Container<Variable *> &As,
1586 Container<Variable *> &Is, R_SExpr T) {
1587 return (As.Success && Is.Success && T) ? &Orig : nullptr;
1590 Variable *enterScope(Variable &Orig, R_SExpr E0) {
1591 return E0 ? &Orig : nullptr;
1593 void exitScope(const Variable &Orig) {}
1595 void enterCFG(SCFG &Cfg) {}
1596 void exitCFG(SCFG &Cfg) {}
1598 Variable *reduceVariableRef(Variable *Ovd) { return Ovd; }
1600 BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; }
1604 // A visitor will visit each node, and halt if any reducer returns false.
1605 template <class Self>
1606 class SExprVisitor : public Traversal<Self, VisitReducer> {
1608 SExprVisitor() : Success(true) {}
1610 bool traverse(SExpr *E, TraversalKind K = TRV_Normal) {
1611 Success = Success && this->traverseByCase(E);
1615 static bool visit(SExpr *E) {
1616 SExprVisitor Visitor;
1617 return Visitor.traverse(E);
1625 // Basic class for comparison operations over expressions.
1626 template <typename Self>
1629 Self *self() { return reinterpret_cast<Self *>(this); }
1632 bool compareByCase(SExpr *E1, SExpr* E2) {
1633 switch (E1->opcode()) {
1634 #define TIL_OPCODE_DEF(X) \
1636 return cast<X>(E1)->compare(cast<X>(E2), *self());
1637 #include "clang/Analysis/Analyses/ThreadSafetyOps.def"
1638 #undef TIL_OPCODE_DEF
1646 class EqualsComparator : public Comparator<EqualsComparator> {
1648 // Result type for the comparison, e.g. bool for simple equality,
1649 // or int for lexigraphic comparison (-1, 0, 1). Must have one value which
1653 CType trueResult() { return true; }
1654 bool notTrue(CType ct) { return !ct; }
1656 bool compareIntegers(unsigned i, unsigned j) { return i == j; }
1657 bool comparePointers(const void* P, const void* Q) { return P == Q; }
1659 bool compare(SExpr *E1, SExpr* E2) {
1660 if (E1->opcode() != E2->opcode())
1662 return compareByCase(E1, E2);
1665 // TODO -- handle alpha-renaming of variables
1666 void enterScope(Variable* V1, Variable* V2) { }
1667 void leaveScope() { }
1669 bool compareVariableRefs(Variable* V1, Variable* V2) {
1673 static bool compareExprs(SExpr *E1, SExpr* E2) {
1674 EqualsComparator Eq;
1675 return Eq.compare(E1, E2);
1680 // Pretty printer for TIL expressions
1681 template <typename Self, typename StreamType>
1682 class PrettyPrinter {
1684 static void print(SExpr *E, StreamType &SS) {
1686 printer.printSExpr(E, SS, Prec_MAX);
1690 Self *self() { return reinterpret_cast<Self *>(this); }
1692 void newline(StreamType &SS) {
1696 // TODO: further distinguish between binary operations.
1697 static const unsigned Prec_Atom = 0;
1698 static const unsigned Prec_Postfix = 1;
1699 static const unsigned Prec_Unary = 2;
1700 static const unsigned Prec_Binary = 3;
1701 static const unsigned Prec_Other = 4;
1702 static const unsigned Prec_Decl = 5;
1703 static const unsigned Prec_MAX = 6;
1705 // Return the precedence of a given node, for use in pretty printing.
1706 unsigned precedence(SExpr *E) {
1707 switch (E->opcode()) {
1708 case COP_Future: return Prec_Atom;
1709 case COP_Undefined: return Prec_Atom;
1710 case COP_Wildcard: return Prec_Atom;
1712 case COP_Literal: return Prec_Atom;
1713 case COP_LiteralPtr: return Prec_Atom;
1714 case COP_Variable: return Prec_Atom;
1715 case COP_Function: return Prec_Decl;
1716 case COP_SFunction: return Prec_Decl;
1717 case COP_Code: return Prec_Decl;
1719 case COP_Apply: return Prec_Postfix;
1720 case COP_SApply: return Prec_Postfix;
1721 case COP_Project: return Prec_Postfix;
1723 case COP_Call: return Prec_Postfix;
1724 case COP_Alloc: return Prec_Other;
1725 case COP_Load: return Prec_Postfix;
1726 case COP_Store: return Prec_Other;
1728 case COP_UnaryOp: return Prec_Unary;
1729 case COP_BinaryOp: return Prec_Binary;
1730 case COP_Cast: return Prec_Unary;
1732 case COP_SCFG: return Prec_Decl;
1733 case COP_Phi: return Prec_Atom;
1734 case COP_Goto: return Prec_Atom;
1735 case COP_Branch: return Prec_Atom;
1736 case COP_MAX: return Prec_MAX;
1741 void printSExpr(SExpr *E, StreamType &SS, unsigned P) {
1743 self()->printNull(SS);
1746 if (self()->precedence(E) > P) {
1747 // Wrap expr in () if necessary.
1749 self()->printSExpr(E, SS, Prec_MAX);
1754 switch (E->opcode()) {
1755 #define TIL_OPCODE_DEF(X) \
1757 self()->print##X(cast<X>(E), SS); \
1759 #include "clang/Analysis/Analyses/ThreadSafetyOps.def"
1760 #undef TIL_OPCODE_DEF
1766 void printNull(StreamType &SS) {
1770 void printFuture(Future *E, StreamType &SS) {
1771 self()->printSExpr(E->maybeGetResult(), SS, Prec_Atom);
1774 void printUndefined(Undefined *E, StreamType &SS) {
1778 void printWildcard(Wildcard *E, StreamType &SS) {
1782 void printLiteral(Literal *E, StreamType &SS) {
1783 // TODO: actually pretty print the literal.
1787 void printLiteralPtr(LiteralPtr *E, StreamType &SS) {
1788 SS << E->clangDecl()->getName();
1791 void printVariable(Variable *E, StreamType &SS) {
1792 SS << E->name() << E->getBlockID() << "_" << E->getID();
1795 void printFunction(Function *E, StreamType &SS, unsigned sugared = 0) {
1798 SS << "\\("; // Lambda
1800 SS << "("; // Slot declarations
1803 SS << ", "; // Curried functions
1806 self()->printVariable(E->variableDecl(), SS);
1808 self()->printSExpr(E->variableDecl()->definition(), SS, Prec_MAX);
1810 SExpr *B = E->body();
1811 if (B && B->opcode() == COP_Function)
1812 self()->printFunction(cast<Function>(B), SS, 2);
1814 self()->printSExpr(B, SS, Prec_Decl);
1817 void printSFunction(SFunction *E, StreamType &SS) {
1819 self()->printVariable(E->variableDecl(), SS);
1821 self()->printSExpr(E->body(), SS, Prec_Decl);
1824 void printCode(Code *E, StreamType &SS) {
1826 self()->printSExpr(E->returnType(), SS, Prec_Decl-1);
1828 self()->printSExpr(E->body(), SS, Prec_Decl);
1831 void printApply(Apply *E, StreamType &SS, bool sugared = false) {
1832 SExpr *F = E->fun();
1833 if (F->opcode() == COP_Apply) {
1834 printApply(cast<Apply>(F), SS, true);
1837 self()->printSExpr(F, SS, Prec_Postfix);
1840 self()->printSExpr(E->arg(), SS, Prec_MAX);
1845 void printSApply(SApply *E, StreamType &SS) {
1846 self()->printSExpr(E->sfun(), SS, Prec_Postfix);
1848 self()->printSExpr(E->arg(), SS, Prec_MAX);
1852 void printProject(Project *E, StreamType &SS) {
1853 self()->printSExpr(E->record(), SS, Prec_Postfix);
1855 SS << E->slotName();
1858 void printCall(Call *E, StreamType &SS) {
1859 SExpr *T = E->target();
1860 if (T->opcode() == COP_Apply) {
1861 self()->printApply(cast<Apply>(T), SS, true);
1865 self()->printSExpr(T, SS, Prec_Postfix);
1870 void printAlloc(Alloc *E, StreamType &SS) {
1872 self()->printSExpr(E->dataType(), SS, Prec_Other-1);
1875 void printLoad(Load *E, StreamType &SS) {
1876 self()->printSExpr(E->pointer(), SS, Prec_Postfix);
1880 void printStore(Store *E, StreamType &SS) {
1881 self()->printSExpr(E->destination(), SS, Prec_Other-1);
1883 self()->printSExpr(E->source(), SS, Prec_Other-1);
1886 void printUnaryOp(UnaryOp *E, StreamType &SS) {
1887 self()->printSExpr(E->expr(), SS, Prec_Unary);
1890 void printBinaryOp(BinaryOp *E, StreamType &SS) {
1891 self()->printSExpr(E->expr0(), SS, Prec_Binary-1);
1892 SS << " " << clang::BinaryOperator::getOpcodeStr(E->binaryOpcode()) << " ";
1893 self()->printSExpr(E->expr1(), SS, Prec_Binary-1);
1896 void printCast(Cast *E, StreamType &SS) {
1898 self()->printSExpr(E->expr(), SS, Prec_Unary);
1901 void printSCFG(SCFG *E, StreamType &SS) {
1903 for (auto BBI : *E) {
1904 SS << "BB_" << BBI->blockID() << ":";
1906 for (auto A : BBI->arguments()) {
1908 self()->printVariable(A, SS);
1910 self()->printSExpr(A->definition(), SS, Prec_MAX);
1914 for (auto I : BBI->instructions()) {
1916 self()->printVariable(I, SS);
1918 self()->printSExpr(I->definition(), SS, Prec_MAX);
1922 SExpr *T = BBI->terminator();
1924 self()->printSExpr(T, SS, Prec_MAX);
1934 void printPhi(Phi *E, StreamType &SS) {
1937 for (auto V : E->values()) {
1941 self()->printSExpr(V, SS, Prec_MAX);
1946 void printGoto(Goto *E, StreamType &SS) {
1948 SS << E->targetBlock()->blockID();
1953 void printBranch(Branch *E, StreamType &SS) {
1955 self()->printSExpr(E->condition(), SS, Prec_MAX);
1957 SS << E->thenBlock()->blockID();
1959 SS << E->elseBlock()->blockID();
1963 } // end namespace til
1967 } // end namespace threadSafety
1968 } // end namespace clang
1970 #endif // THREAD_SAFETY_TIL_H