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/ExprCXX.h"
47 #include "llvm/Support/AlignOf.h"
48 #include "llvm/Support/Allocator.h"
55 namespace threadSafety {
59 // Simple wrapper class to abstract away from the details of memory management.
60 // SExprs are allocated in pools, and deallocated all at once.
71 MemRegionRef() : Allocator(nullptr) {}
72 MemRegionRef(llvm::BumpPtrAllocator *A) : Allocator(A) {}
74 void *allocate(size_t Sz) {
75 return Allocator->Allocate(Sz, llvm::AlignOf<AlignmentType>::Alignment);
78 template <typename T> T *allocateT() { return Allocator->Allocate<T>(); }
80 template <typename T> T *allocateT(size_t NumElems) {
81 return Allocator->Allocate<T>(NumElems);
85 llvm::BumpPtrAllocator *Allocator;
89 } // end namespace til
90 } // end namespace threadSafety
91 } // end namespace clang
94 inline void *operator new(size_t Sz,
95 clang::threadSafety::til::MemRegionRef &R) {
96 return R.allocate(Sz);
101 namespace threadSafety {
104 using llvm::StringRef;
106 // A simple fixed size array class that does not manage its own memory,
107 // suitable for use with bump pointer allocation.
108 template <class T> class SimpleArray {
110 SimpleArray() : Data(nullptr), Size(0), Capacity(0) {}
111 SimpleArray(T *Dat, size_t Cp, size_t Sz = 0)
112 : Data(Dat), Size(0), Capacity(Cp) {}
113 SimpleArray(MemRegionRef A, size_t Cp)
114 : Data(A.allocateT<T>(Cp)), Size(0), Capacity(Cp) {}
115 SimpleArray(SimpleArray<T> &&A)
116 : Data(A.Data), Size(A.Size), Capacity(A.Capacity) {
122 T *resize(size_t Ncp, MemRegionRef A) {
124 Data = A.allocateT<T>(Ncp);
125 memcpy(Data, Odata, sizeof(T) * Size);
130 typedef const T *const_iterator;
132 size_t size() const { return Size; }
133 size_t capacity() const { return Capacity; }
135 T &operator[](unsigned I) { return Data[I]; }
136 const T &operator[](unsigned I) const { return Data[I]; }
138 iterator begin() { return Data; }
139 iterator end() { return Data + Size; }
141 const_iterator cbegin() const { return Data; }
142 const_iterator cend() const { return Data + Size; }
144 void push_back(const T &Elem) {
145 assert(Size < Capacity);
149 template <class Iter> unsigned append(Iter I, Iter E) {
152 for (; J < Capacity && I != E; ++J, ++I)
159 SimpleArray(const SimpleArray<T> &A) { }
168 #define TIL_OPCODE_DEF(X) COP_##X,
169 #include "clang/Analysis/Analyses/ThreadSafetyOps.def"
170 #undef TIL_OPCODE_DEF
175 typedef clang::BinaryOperatorKind TIL_BinaryOpcode;
176 typedef clang::UnaryOperatorKind TIL_UnaryOpcode;
177 typedef clang::CastKind TIL_CastOpcode;
182 TRV_Lazy, // subexpression may need to be traversed lazily
183 TRV_Tail // subexpression occurs in a tail position
187 // Base class for AST nodes in the typed intermediate language.
190 TIL_Opcode opcode() const { return static_cast<TIL_Opcode>(Opcode); }
192 // Subclasses of SExpr must define the following:
194 // This(const This& E, ...) {
195 // copy constructor: construct copy of E, with some additional arguments.
198 // template <class V> typename V::R_SExpr traverse(V &Visitor) {
199 // traverse all subexpressions, following the traversal/rewriter interface
202 // template <class C> typename C::CType compare(CType* E, C& Cmp) {
203 // compare all subexpressions, following the comparator interface
206 void *operator new(size_t S, clang::threadSafety::til::MemRegionRef &R) {
207 return ::operator new(S, R);
211 SExpr(TIL_Opcode Op) : Opcode(Op), Reserved(0), Flags(0) {}
212 SExpr(const SExpr &E) : Opcode(E.Opcode), Reserved(0), Flags(E.Flags) {}
214 const unsigned char Opcode;
215 unsigned char Reserved;
216 unsigned short Flags;
221 // SExpr objects must be created in an arena and cannot be deleted.
222 void *operator new(size_t) = delete;
223 void operator delete(void *) = delete;
227 // Class for owning references to SExprs.
228 // Includes attach/detach logic for counting variable references and lazy
229 // rewriting strategies.
232 SExprRef() : Ptr(nullptr) { }
233 SExprRef(std::nullptr_t P) : Ptr(nullptr) { }
234 SExprRef(SExprRef &&R) : Ptr(R.Ptr) { R.Ptr = nullptr; }
236 // Defined after Variable and Future, below.
237 inline SExprRef(SExpr *P);
240 SExpr *get() { return Ptr; }
241 const SExpr *get() const { return Ptr; }
243 SExpr *operator->() { return get(); }
244 const SExpr *operator->() const { return get(); }
246 SExpr &operator*() { return *Ptr; }
247 const SExpr &operator*() const { return *Ptr; }
249 bool operator==(const SExprRef &R) const { return Ptr == R.Ptr; }
250 bool operator!=(const SExprRef &R) const { return !operator==(R); }
251 bool operator==(const SExpr *P) const { return Ptr == P; }
252 bool operator!=(const SExpr *P) const { return !operator==(P); }
253 bool operator==(std::nullptr_t) const { return Ptr == nullptr; }
254 bool operator!=(std::nullptr_t) const { return Ptr != nullptr; }
256 inline void reset(SExpr *E);
259 inline void attach();
260 inline void detach();
266 // Contains various helper functions for SExprs.
267 namespace ThreadSafetyTIL {
268 static bool isTrivial(SExpr *E) {
269 unsigned Op = E->opcode();
270 return Op == COP_Variable || Op == COP_Literal || Op == COP_LiteralPtr;
279 // A named variable, e.g. "x".
281 // There are two distinct places in which a Variable can appear in the AST.
282 // A variable declaration introduces a new variable, and can occur in 3 places:
283 // Let-expressions: (Let (x = t) u)
284 // Functions: (Function (x : t) u)
285 // Self-applicable functions (SFunction (x) t)
287 // If a variable occurs in any other location, it is a reference to an existing
288 // variable declaration -- e.g. 'x' in (x * y + z). To save space, we don't
289 // allocate a separate AST node for variable references; a reference is just a
290 // pointer to the original declaration.
291 class Variable : public SExpr {
293 static bool classof(const SExpr *E) { return E->opcode() == COP_Variable; }
295 // Let-variable, function parameter, or self-variable
302 // These are defined after SExprRef contructor, below
303 inline Variable(VariableKind K, SExpr *D = nullptr,
304 const clang::ValueDecl *Cvd = nullptr);
305 inline Variable(const clang::ValueDecl *Cvd, SExpr *D = nullptr);
306 inline Variable(const Variable &Vd, SExpr *D);
308 VariableKind kind() const { return static_cast<VariableKind>(Flags); }
310 const StringRef name() const { return Cvdecl ? Cvdecl->getName() : "_x"; }
311 const clang::ValueDecl *clangDecl() const { return Cvdecl; }
313 // Returns the definition (for let vars) or type (for parameter & self vars)
314 SExpr *definition() { return Definition.get(); }
316 void attachVar() const { ++NumUses; }
317 void detachVar() const { assert(NumUses > 0); --NumUses; }
319 unsigned getID() const { return Id; }
320 unsigned getBlockID() const { return BlockID; }
322 void setID(unsigned Bid, unsigned I) {
323 BlockID = static_cast<unsigned short>(Bid);
324 Id = static_cast<unsigned short>(I);
327 template <class V> typename V::R_SExpr traverse(V &Visitor) {
328 // This routine is only called for variable references.
329 return Visitor.reduceVariableRef(this);
332 template <class C> typename C::CType compare(Variable* E, C& Cmp) {
333 return Cmp.compareVariableRefs(this, E);
337 friend class Function;
338 friend class SFunction;
339 friend class BasicBlock;
341 // Function, SFunction, and BasicBlock will reset the kind.
342 void setKind(VariableKind K) { Flags = K; }
344 SExprRef Definition; // The TIL type or definition
345 const clang::ValueDecl *Cvdecl; // The clang declaration for this variable.
347 unsigned short BlockID;
349 mutable unsigned NumUses;
353 // Placeholder for an expression that has not yet been created.
354 // Used to implement lazy copy and rewriting strategies.
355 class Future : public SExpr {
357 static bool classof(const SExpr *E) { return E->opcode() == COP_Future; }
366 SExpr(COP_Future), Status(FS_pending), Result(nullptr), Location(nullptr)
368 virtual ~Future() = delete;
370 // Registers the location in the AST where this future is stored.
371 // Forcing the future will automatically update the AST.
372 static inline void registerLocation(SExprRef *Member) {
373 if (Future *F = dyn_cast_or_null<Future>(Member->get()))
374 F->Location = Member;
377 // A lazy rewriting strategy should subclass Future and override this method.
378 virtual SExpr *create() { return nullptr; }
380 // Return the result of this future if it exists, otherwise return null.
381 SExpr *maybeGetResult() {
385 // Return the result of this future; forcing it if necessary.
392 return nullptr; // infinite loop; illegal recursion.
398 template <class V> typename V::R_SExpr traverse(V &Visitor) {
399 assert(Result && "Cannot traverse Future that has not been forced.");
400 return Visitor.traverse(Result);
403 template <class C> typename C::CType compare(Future* E, C& Cmp) {
404 if (!Result || !E->Result)
405 return Cmp.comparePointers(this, E);
406 return Cmp.compare(Result, E->Result);
420 void SExprRef::attach() {
424 TIL_Opcode Op = Ptr->opcode();
425 if (Op == COP_Variable) {
426 cast<Variable>(Ptr)->attachVar();
428 else if (Op == COP_Future) {
429 cast<Future>(Ptr)->registerLocation(this);
433 void SExprRef::detach() {
434 if (Ptr && Ptr->opcode() == COP_Variable) {
435 cast<Variable>(Ptr)->detachVar();
439 SExprRef::SExprRef(SExpr *P) : Ptr(P) {
444 SExprRef::~SExprRef() {
448 void SExprRef::reset(SExpr *P) {
457 Variable::Variable(VariableKind K, SExpr *D, const clang::ValueDecl *Cvd)
458 : SExpr(COP_Variable), Definition(D), Cvdecl(Cvd),
459 BlockID(0), Id(0), NumUses(0) {
463 Variable::Variable(const clang::ValueDecl *Cvd, SExpr *D)
464 : SExpr(COP_Variable), Definition(D), Cvdecl(Cvd),
465 BlockID(0), Id(0), NumUses(0) {
469 Variable::Variable(const Variable &Vd, SExpr *D) // rewrite constructor
470 : SExpr(Vd), Definition(D), Cvdecl(Vd.Cvdecl),
471 BlockID(0), Id(0), NumUses(0) {
476 void Future::force() {
477 Status = FS_evaluating;
488 // Placeholder for C++ expressions that cannot be represented in the TIL.
489 class Undefined : public SExpr {
491 static bool classof(const SExpr *E) { return E->opcode() == COP_Undefined; }
493 Undefined(const clang::Stmt *S = nullptr) : SExpr(COP_Undefined), Cstmt(S) {}
494 Undefined(const Undefined &U) : SExpr(U), Cstmt(U.Cstmt) {}
496 template <class V> typename V::R_SExpr traverse(V &Visitor) {
497 return Visitor.reduceUndefined(*this);
500 template <class C> typename C::CType compare(Undefined* E, C& Cmp) {
501 return Cmp.comparePointers(Cstmt, E->Cstmt);
505 const clang::Stmt *Cstmt;
509 // Placeholder for a wildcard that matches any other expression.
510 class Wildcard : public SExpr {
512 static bool classof(const SExpr *E) { return E->opcode() == COP_Wildcard; }
514 Wildcard() : SExpr(COP_Wildcard) {}
515 Wildcard(const Wildcard &W) : SExpr(W) {}
517 template <class V> typename V::R_SExpr traverse(V &Visitor) {
518 return Visitor.reduceWildcard(*this);
521 template <class C> typename C::CType compare(Wildcard* E, C& Cmp) {
522 return Cmp.trueResult();
527 // Base class for literal values.
528 class Literal : public SExpr {
530 static bool classof(const SExpr *E) { return E->opcode() == COP_Literal; }
532 Literal(const clang::Expr *C) : SExpr(COP_Literal), Cexpr(C) {}
533 Literal(const Literal &L) : SExpr(L), Cexpr(L.Cexpr) {}
535 // The clang expression for this literal.
536 const clang::Expr *clangExpr() { return Cexpr; }
538 template <class V> typename V::R_SExpr traverse(V &Visitor) {
539 return Visitor.reduceLiteral(*this);
542 template <class C> typename C::CType compare(Literal* E, C& Cmp) {
543 // TODO -- use value, not pointer equality
544 return Cmp.comparePointers(Cexpr, E->Cexpr);
548 const clang::Expr *Cexpr;
552 // Literal pointer to an object allocated in memory.
553 // At compile time, pointer literals are represented by symbolic names.
554 class LiteralPtr : public SExpr {
556 static bool classof(const SExpr *E) { return E->opcode() == COP_LiteralPtr; }
558 LiteralPtr(const clang::ValueDecl *D) : SExpr(COP_LiteralPtr), Cvdecl(D) {}
559 LiteralPtr(const LiteralPtr &R) : SExpr(R), Cvdecl(R.Cvdecl) {}
561 // The clang declaration for the value that this pointer points to.
562 const clang::ValueDecl *clangDecl() { return Cvdecl; }
564 template <class V> typename V::R_SExpr traverse(V &Visitor) {
565 return Visitor.reduceLiteralPtr(*this);
568 template <class C> typename C::CType compare(LiteralPtr* E, C& Cmp) {
569 return Cmp.comparePointers(Cvdecl, E->Cvdecl);
573 const clang::ValueDecl *Cvdecl;
580 // A function -- a.k.a. lambda abstraction.
581 // Functions with multiple arguments are created by currying,
582 // e.g. (function (x: Int) (function (y: Int) (add x y)))
583 class Function : public SExpr {
585 static bool classof(const SExpr *E) { return E->opcode() == COP_Function; }
587 Function(Variable *Vd, SExpr *Bd)
588 : SExpr(COP_Function), VarDecl(Vd), Body(Bd) {
589 Vd->setKind(Variable::VK_Fun);
591 Function(const Function &F, Variable *Vd, SExpr *Bd) // rewrite constructor
592 : SExpr(F), VarDecl(Vd), Body(Bd) {
593 Vd->setKind(Variable::VK_Fun);
596 Variable *variableDecl() { return VarDecl; }
597 const Variable *variableDecl() const { return VarDecl; }
599 SExpr *body() { return Body.get(); }
600 const SExpr *body() const { return Body.get(); }
602 template <class V> typename V::R_SExpr traverse(V &Visitor) {
603 // This is a variable declaration, so traverse the definition.
604 typename V::R_SExpr E0 = Visitor.traverse(VarDecl->Definition, TRV_Lazy);
605 // Tell the rewriter to enter the scope of the function.
606 Variable *Nvd = Visitor.enterScope(*VarDecl, E0);
607 typename V::R_SExpr E1 = Visitor.traverse(Body);
608 Visitor.exitScope(*VarDecl);
609 return Visitor.reduceFunction(*this, Nvd, E1);
612 template <class C> typename C::CType compare(Function* E, C& Cmp) {
613 typename C::CType Ct =
614 Cmp.compare(VarDecl->definition(), E->VarDecl->definition());
617 Cmp.enterScope(variableDecl(), E->variableDecl());
618 Ct = Cmp.compare(body(), E->body());
629 // A self-applicable function.
630 // A self-applicable function can be applied to itself. It's useful for
631 // implementing objects and late binding
632 class SFunction : public SExpr {
634 static bool classof(const SExpr *E) { return E->opcode() == COP_SFunction; }
636 SFunction(Variable *Vd, SExpr *B)
637 : SExpr(COP_SFunction), VarDecl(Vd), Body(B) {
638 assert(Vd->Definition == nullptr);
639 Vd->setKind(Variable::VK_SFun);
640 Vd->Definition.reset(this);
642 SFunction(const SFunction &F, Variable *Vd, SExpr *B) // rewrite constructor
646 assert(Vd->Definition == nullptr);
647 Vd->setKind(Variable::VK_SFun);
648 Vd->Definition.reset(this);
651 Variable *variableDecl() { return VarDecl; }
652 const Variable *variableDecl() const { return VarDecl; }
654 SExpr *body() { return Body.get(); }
655 const SExpr *body() const { return Body.get(); }
657 template <class V> typename V::R_SExpr traverse(V &Visitor) {
658 // A self-variable points to the SFunction itself.
659 // A rewrite must introduce the variable with a null definition, and update
660 // it after 'this' has been rewritten.
661 Variable *Nvd = Visitor.enterScope(*VarDecl, nullptr /* def */);
662 typename V::R_SExpr E1 = Visitor.traverse(Body);
663 Visitor.exitScope(*VarDecl);
664 // A rewrite operation will call SFun constructor to set Vvd->Definition.
665 return Visitor.reduceSFunction(*this, Nvd, E1);
668 template <class C> typename C::CType compare(SFunction* E, C& Cmp) {
669 Cmp.enterScope(variableDecl(), E->variableDecl());
670 typename C::CType Ct = Cmp.compare(body(), E->body());
681 // A block of code -- e.g. the body of a function.
682 class Code : public SExpr {
684 static bool classof(const SExpr *E) { return E->opcode() == COP_Code; }
686 Code(SExpr *T, SExpr *B) : SExpr(COP_Code), ReturnType(T), Body(B) {}
687 Code(const Code &C, SExpr *T, SExpr *B) // rewrite constructor
688 : SExpr(C), ReturnType(T), Body(B) {}
690 SExpr *returnType() { return ReturnType.get(); }
691 const SExpr *returnType() const { return ReturnType.get(); }
693 SExpr *body() { return Body.get(); }
694 const SExpr *body() const { return Body.get(); }
696 template <class V> typename V::R_SExpr traverse(V &Visitor) {
697 typename V::R_SExpr Nt = Visitor.traverse(ReturnType, TRV_Lazy);
698 typename V::R_SExpr Nb = Visitor.traverse(Body, TRV_Lazy);
699 return Visitor.reduceCode(*this, Nt, Nb);
702 template <class C> typename C::CType compare(Code* E, C& Cmp) {
703 typename C::CType Ct = Cmp.compare(returnType(), E->returnType());
706 return Cmp.compare(body(), E->body());
715 // Apply an argument to a function
716 class Apply : public SExpr {
718 static bool classof(const SExpr *E) { return E->opcode() == COP_Apply; }
720 Apply(SExpr *F, SExpr *A) : SExpr(COP_Apply), Fun(F), Arg(A) {}
721 Apply(const Apply &A, SExpr *F, SExpr *Ar) // rewrite constructor
722 : SExpr(A), Fun(F), Arg(Ar)
725 SExpr *fun() { return Fun.get(); }
726 const SExpr *fun() const { return Fun.get(); }
728 SExpr *arg() { return Arg.get(); }
729 const SExpr *arg() const { return Arg.get(); }
731 template <class V> typename V::R_SExpr traverse(V &Visitor) {
732 typename V::R_SExpr Nf = Visitor.traverse(Fun);
733 typename V::R_SExpr Na = Visitor.traverse(Arg);
734 return Visitor.reduceApply(*this, Nf, Na);
737 template <class C> typename C::CType compare(Apply* E, C& Cmp) {
738 typename C::CType Ct = Cmp.compare(fun(), E->fun());
741 return Cmp.compare(arg(), E->arg());
750 // Apply a self-argument to a self-applicable function
751 class SApply : public SExpr {
753 static bool classof(const SExpr *E) { return E->opcode() == COP_SApply; }
755 SApply(SExpr *Sf, SExpr *A = nullptr)
756 : SExpr(COP_SApply), Sfun(Sf), Arg(A)
758 SApply(SApply &A, SExpr *Sf, SExpr *Ar = nullptr) // rewrite constructor
759 : SExpr(A), Sfun(Sf), Arg(Ar)
762 SExpr *sfun() { return Sfun.get(); }
763 const SExpr *sfun() const { return Sfun.get(); }
765 SExpr *arg() { return Arg.get() ? Arg.get() : Sfun.get(); }
766 const SExpr *arg() const { return Arg.get() ? Arg.get() : Sfun.get(); }
768 bool isDelegation() const { return Arg == nullptr; }
770 template <class V> typename V::R_SExpr traverse(V &Visitor) {
771 typename V::R_SExpr Nf = Visitor.traverse(Sfun);
772 typename V::R_SExpr Na = Arg.get() ? Visitor.traverse(Arg) : nullptr;
773 return Visitor.reduceSApply(*this, Nf, Na);
776 template <class C> typename C::CType compare(SApply* E, C& Cmp) {
777 typename C::CType Ct = Cmp.compare(sfun(), E->sfun());
778 if (Cmp.notTrue(Ct) || (!arg() && !E->arg()))
780 return Cmp.compare(arg(), E->arg());
789 // Project a named slot from a C++ struct or class.
790 class Project : public SExpr {
792 static bool classof(const SExpr *E) { return E->opcode() == COP_Project; }
794 Project(SExpr *R, clang::ValueDecl *Cvd)
795 : SExpr(COP_Project), Rec(R), Cvdecl(Cvd) {}
796 Project(const Project &P, SExpr *R) : SExpr(P), Rec(R), Cvdecl(P.Cvdecl) {}
798 SExpr *record() { return Rec.get(); }
799 const SExpr *record() const { return Rec.get(); }
801 const clang::ValueDecl *clangValueDecl() const { return Cvdecl; }
803 StringRef slotName() const { return Cvdecl->getName(); }
805 template <class V> typename V::R_SExpr traverse(V &Visitor) {
806 typename V::R_SExpr Nr = Visitor.traverse(Rec);
807 return Visitor.reduceProject(*this, Nr);
810 template <class C> typename C::CType compare(Project* E, C& Cmp) {
811 typename C::CType Ct = Cmp.compare(record(), E->record());
814 return Cmp.comparePointers(Cvdecl, E->Cvdecl);
819 clang::ValueDecl *Cvdecl;
823 // Call a function (after all arguments have been applied).
824 class Call : public SExpr {
826 static bool classof(const SExpr *E) { return E->opcode() == COP_Call; }
828 Call(SExpr *T, const clang::CallExpr *Ce = nullptr)
829 : SExpr(COP_Call), Target(T), Cexpr(Ce) {}
830 Call(const Call &C, SExpr *T) : SExpr(C), Target(T), Cexpr(C.Cexpr) {}
832 SExpr *target() { return Target.get(); }
833 const SExpr *target() const { return Target.get(); }
835 const clang::CallExpr *clangCallExpr() { return Cexpr; }
837 template <class V> typename V::R_SExpr traverse(V &Visitor) {
838 typename V::R_SExpr Nt = Visitor.traverse(Target);
839 return Visitor.reduceCall(*this, Nt);
842 template <class C> typename C::CType compare(Call* E, C& Cmp) {
843 return Cmp.compare(target(), E->target());
848 const clang::CallExpr *Cexpr;
852 // Allocate memory for a new value on the heap or stack.
853 class Alloc : public SExpr {
855 static bool classof(const SExpr *E) { return E->opcode() == COP_Call; }
862 Alloc(SExpr* D, AllocKind K) : SExpr(COP_Alloc), Dtype(D) {
865 Alloc(const Alloc &A, SExpr* Dt) : SExpr(A), Dtype(Dt) {
869 AllocKind kind() const { return static_cast<AllocKind>(Flags); }
871 SExpr* dataType() { return Dtype.get(); }
872 const SExpr* dataType() const { return Dtype.get(); }
874 template <class V> typename V::R_SExpr traverse(V &Visitor) {
875 typename V::R_SExpr Nd = Visitor.traverse(Dtype);
876 return Visitor.reduceAlloc(*this, Nd);
879 template <class C> typename C::CType compare(Alloc* E, C& Cmp) {
880 typename C::CType Ct = Cmp.compareIntegers(kind(), E->kind());
883 return Cmp.compare(dataType(), E->dataType());
891 // Load a value from memory.
892 class Load : public SExpr {
894 static bool classof(const SExpr *E) { return E->opcode() == COP_Load; }
896 Load(SExpr *P) : SExpr(COP_Load), Ptr(P) {}
897 Load(const Load &L, SExpr *P) : SExpr(L), Ptr(P) {}
899 SExpr *pointer() { return Ptr.get(); }
900 const SExpr *pointer() const { return Ptr.get(); }
902 template <class V> typename V::R_SExpr traverse(V &Visitor) {
903 typename V::R_SExpr Np = Visitor.traverse(Ptr);
904 return Visitor.reduceLoad(*this, Np);
907 template <class C> typename C::CType compare(Load* E, C& Cmp) {
908 return Cmp.compare(pointer(), E->pointer());
916 // Store a value to memory.
917 class Store : public SExpr {
919 static bool classof(const SExpr *E) { return E->opcode() == COP_Store; }
921 Store(SExpr *P, SExpr *V) : SExpr(COP_Store), Dest(P), Source(V) {}
922 Store(const Store &S, SExpr *P, SExpr *V) : SExpr(S), Dest(P), Source(V) {}
924 SExpr *destination() { return Dest.get(); } // Address to store to
925 const SExpr *destination() const { return Dest.get(); }
927 SExpr *source() { return Source.get(); } // Value to store
928 const SExpr *source() const { return Source.get(); }
930 template <class V> typename V::R_SExpr traverse(V &Visitor) {
931 typename V::R_SExpr Np = Visitor.traverse(Dest);
932 typename V::R_SExpr Nv = Visitor.traverse(Source);
933 return Visitor.reduceStore(*this, Np, Nv);
936 template <class C> typename C::CType compare(Store* E, C& Cmp) {
937 typename C::CType Ct = Cmp.compare(destination(), E->destination());
940 return Cmp.compare(source(), E->source());
948 // Simple unary operation -- e.g. !, ~, etc.
949 class UnaryOp : public SExpr {
951 static bool classof(const SExpr *E) { return E->opcode() == COP_UnaryOp; }
953 UnaryOp(TIL_UnaryOpcode Op, SExpr *E) : SExpr(COP_UnaryOp), Expr0(E) {
956 UnaryOp(const UnaryOp &U, SExpr *E) : SExpr(U) { Flags = U.Flags; }
958 TIL_UnaryOpcode unaryOpcode() { return static_cast<TIL_UnaryOpcode>(Flags); }
960 SExpr *expr() { return Expr0.get(); }
961 const SExpr *expr() const { return Expr0.get(); }
963 template <class V> typename V::R_SExpr traverse(V &Visitor) {
964 typename V::R_SExpr Ne = Visitor.traverse(Expr0);
965 return Visitor.reduceUnaryOp(*this, Ne);
968 template <class C> typename C::CType compare(UnaryOp* E, C& Cmp) {
969 typename C::CType Ct =
970 Cmp.compareIntegers(unaryOpcode(), E->unaryOpcode());
973 return Cmp.compare(expr(), E->expr());
981 // Simple binary operation -- e.g. +, -, etc.
982 class BinaryOp : public SExpr {
984 static bool classof(const SExpr *E) { return E->opcode() == COP_BinaryOp; }
986 BinaryOp(TIL_BinaryOpcode Op, SExpr *E0, SExpr *E1)
987 : SExpr(COP_BinaryOp), Expr0(E0), Expr1(E1) {
990 BinaryOp(const BinaryOp &B, SExpr *E0, SExpr *E1)
991 : SExpr(B), Expr0(E0), Expr1(E1) {
995 TIL_BinaryOpcode binaryOpcode() {
996 return static_cast<TIL_BinaryOpcode>(Flags);
999 SExpr *expr0() { return Expr0.get(); }
1000 const SExpr *expr0() const { return Expr0.get(); }
1002 SExpr *expr1() { return Expr1.get(); }
1003 const SExpr *expr1() const { return Expr1.get(); }
1005 template <class V> typename V::R_SExpr traverse(V &Visitor) {
1006 typename V::R_SExpr Ne0 = Visitor.traverse(Expr0);
1007 typename V::R_SExpr Ne1 = Visitor.traverse(Expr1);
1008 return Visitor.reduceBinaryOp(*this, Ne0, Ne1);
1011 template <class C> typename C::CType compare(BinaryOp* E, C& Cmp) {
1012 typename C::CType Ct =
1013 Cmp.compareIntegers(binaryOpcode(), E->binaryOpcode());
1014 if (Cmp.notTrue(Ct))
1016 Ct = Cmp.compare(expr0(), E->expr0());
1017 if (Cmp.notTrue(Ct))
1019 return Cmp.compare(expr1(), E->expr1());
1029 class Cast : public SExpr {
1031 static bool classof(const SExpr *E) { return E->opcode() == COP_Cast; }
1033 Cast(TIL_CastOpcode Op, SExpr *E) : SExpr(COP_Cast), Expr0(E) { Flags = Op; }
1034 Cast(const Cast &C, SExpr *E) : SExpr(C), Expr0(E) { Flags = C.Flags; }
1036 TIL_BinaryOpcode castOpcode() {
1037 return static_cast<TIL_BinaryOpcode>(Flags);
1040 SExpr *expr() { return Expr0.get(); }
1041 const SExpr *expr() const { return Expr0.get(); }
1043 template <class V> typename V::R_SExpr traverse(V &Visitor) {
1044 typename V::R_SExpr Ne = Visitor.traverse(Expr0);
1045 return Visitor.reduceCast(*this, Ne);
1048 template <class C> typename C::CType compare(Cast* E, C& Cmp) {
1049 typename C::CType Ct =
1050 Cmp.compareIntegers(castOpcode(), E->castOpcode());
1051 if (Cmp.notTrue(Ct))
1053 return Cmp.compare(expr(), E->expr());
1066 // An SCFG is a control-flow graph. It consists of a set of basic blocks, each
1067 // of which terminates in a branch to another basic block. There is one
1068 // entry point, and one exit point.
1069 class SCFG : public SExpr {
1071 typedef SimpleArray<BasicBlock*> BlockArray;
1073 static bool classof(const SExpr *E) { return E->opcode() == COP_SCFG; }
1075 SCFG(MemRegionRef A, unsigned Nblocks)
1076 : SExpr(COP_SCFG), Blocks(A, Nblocks), Entry(nullptr), Exit(nullptr) {}
1077 SCFG(const SCFG &Cfg, BlockArray &&Ba) // steals memory from Ba
1079 Blocks(std::move(Ba)),
1082 // TODO: set entry and exit!
1085 typedef BlockArray::iterator iterator;
1086 typedef BlockArray::const_iterator const_iterator;
1088 iterator begin() { return Blocks.begin(); }
1089 iterator end() { return Blocks.end(); }
1091 const_iterator cbegin() const { return Blocks.cbegin(); }
1092 const_iterator cend() const { return Blocks.cend(); }
1094 BasicBlock *entry() const { return Entry; }
1095 BasicBlock *exit() const { return Exit; }
1097 void add(BasicBlock *BB) { Blocks.push_back(BB); }
1098 void setEntry(BasicBlock *BB) { Entry = BB; }
1099 void setExit(BasicBlock *BB) { Exit = BB; }
1101 template <class V> typename V::R_SExpr traverse(V &Visitor);
1103 template <class C> typename C::CType compare(SCFG* E, C& Cmp) {
1104 // TODO -- implement CFG comparisons
1105 return Cmp.comparePointers(this, E);
1115 // A basic block is part of an SCFG, and can be treated as a function in
1116 // continuation passing style. It consists of a sequence of phi nodes, which
1117 // are "arguments" to the function, followed by a sequence of instructions.
1118 // Both arguments and instructions define new variables. It ends with a
1119 // branch or goto to another basic block in the same SCFG.
1122 typedef SimpleArray<Variable*> VarArray;
1124 BasicBlock(MemRegionRef A, unsigned Nargs, unsigned Nins,
1125 SExpr *Term = nullptr)
1126 : BlockID(0), Parent(nullptr), Args(A, Nargs), Instrs(A, Nins),
1128 BasicBlock(const BasicBlock &B, VarArray &&As, VarArray &&Is, SExpr *T)
1129 : BlockID(0), Parent(nullptr),
1130 Args(std::move(As)), Instrs(std::move(Is)), Terminator(T)
1133 unsigned blockID() const { return BlockID; }
1134 BasicBlock *parent() const { return Parent; }
1136 const VarArray &arguments() const { return Args; }
1137 VarArray &arguments() { return Args; }
1139 const VarArray &instructions() const { return Instrs; }
1140 VarArray &instructions() { return Instrs; }
1142 const SExpr *terminator() const { return Terminator.get(); }
1143 SExpr *terminator() { return Terminator.get(); }
1145 void setParent(BasicBlock *P) { Parent = P; }
1146 void setBlockID(unsigned i) { BlockID = i; }
1147 void setTerminator(SExpr *E) { Terminator.reset(E); }
1148 void addArgument(Variable *V) { Args.push_back(V); }
1149 void addInstr(Variable *V) { Args.push_back(V); }
1151 template <class V> BasicBlock *traverse(V &Visitor) {
1152 typename V::template Container<Variable*> Nas(Visitor, Args.size());
1153 typename V::template Container<Variable*> Nis(Visitor, Instrs.size());
1155 for (auto A : Args) {
1156 typename V::R_SExpr Ne = Visitor.traverse(A->Definition);
1157 Variable *Nvd = Visitor.enterScope(*A, Ne);
1160 for (auto I : Instrs) {
1161 typename V::R_SExpr Ne = Visitor.traverse(I->Definition);
1162 Variable *Nvd = Visitor.enterScope(*I, Ne);
1165 typename V::R_SExpr Nt = Visitor.traverse(Terminator);
1167 // TODO: use reverse iterator
1168 for (unsigned J = 0, JN = Instrs.size(); J < JN; ++J)
1169 Visitor.exitScope(*Instrs[JN-J]);
1170 for (unsigned I = 0, IN = Instrs.size(); I < IN; ++I)
1171 Visitor.exitScope(*Args[IN-I]);
1173 return Visitor.reduceBasicBlock(*this, Nas, Nis, Nt);
1176 template <class C> typename C::CType compare(BasicBlock* E, C& Cmp) {
1177 // TODO: implement CFG comparisons
1178 return Cmp.comparePointers(this, E);
1185 BasicBlock *Parent; // The parent block is the enclosing lexical scope.
1186 // The parent dominates this block.
1187 VarArray Args; // Phi nodes
1189 SExprRef Terminator;
1194 typename V::R_SExpr SCFG::traverse(V &Visitor) {
1195 Visitor.enterCFG(*this);
1196 typename V::template Container<BasicBlock *> Bbs(Visitor, Blocks.size());
1197 for (auto B : Blocks) {
1198 BasicBlock *Nbb = B->traverse(Visitor);
1201 Visitor.exitCFG(*this);
1202 return Visitor.reduceSCFG(*this, Bbs);
1207 class Phi : public SExpr {
1209 // TODO: change to SExprRef
1210 typedef SimpleArray<SExpr*> ValArray;
1212 static bool classof(const SExpr *E) { return E->opcode() == COP_Phi; }
1214 Phi(MemRegionRef A, unsigned Nvals)
1215 : SExpr(COP_Phi), Values(A, Nvals)
1217 Phi(const Phi &P, ValArray &&Vs) // steals memory of Vs
1218 : SExpr(COP_Phi), Values(std::move(Vs))
1221 const ValArray &values() const { return Values; }
1222 ValArray &values() { return Values; }
1224 template <class V> typename V::R_SExpr traverse(V &Visitor) {
1225 typename V::template Container<typename V::R_SExpr> Nvs(Visitor,
1227 for (auto Val : Values) {
1228 typename V::R_SExpr Nv = Visitor.traverse(Val);
1231 return Visitor.reducePhi(*this, Nvs);
1234 template <class C> typename C::CType compare(Phi* E, C& Cmp) {
1235 // TODO -- implement CFG comparisons
1236 return Cmp.comparePointers(this, E);
1244 class Goto : public SExpr {
1246 static bool classof(const SExpr *E) { return E->opcode() == COP_Goto; }
1248 Goto(BasicBlock *B, unsigned Index)
1249 : SExpr(COP_Goto), TargetBlock(B), Index(0) {}
1250 Goto(const Goto &G, BasicBlock *B, unsigned I)
1251 : SExpr(COP_Goto), TargetBlock(B), Index(I) {}
1253 BasicBlock *targetBlock() const { return TargetBlock; }
1254 unsigned index() const { return Index; }
1256 template <class V> typename V::R_SExpr traverse(V &Visitor) {
1257 // TODO -- rewrite indices properly
1258 BasicBlock *Ntb = Visitor.reduceBasicBlockRef(TargetBlock);
1259 return Visitor.reduceGoto(*this, Ntb, Index);
1262 template <class C> typename C::CType compare(Goto* E, C& Cmp) {
1263 // TODO -- implement CFG comparisons
1264 return Cmp.comparePointers(this, E);
1268 BasicBlock *TargetBlock;
1269 unsigned Index; // Index into Phi nodes of target block.
1273 class Branch : public SExpr {
1275 static bool classof(const SExpr *E) { return E->opcode() == COP_Branch; }
1277 Branch(SExpr *C, BasicBlock *T, BasicBlock *E)
1278 : SExpr(COP_Branch), Condition(C), ThenBlock(T), ElseBlock(E) {}
1279 Branch(const Branch &Br, SExpr *C, BasicBlock *T, BasicBlock *E)
1280 : SExpr(COP_Branch), Condition(C), ThenBlock(T), ElseBlock(E) {}
1282 SExpr *condition() { return Condition; }
1283 BasicBlock *thenBlock() { return ThenBlock; }
1284 BasicBlock *elseBlock() { return ElseBlock; }
1286 template <class V> typename V::R_SExpr traverse(V &Visitor) {
1287 typename V::R_SExpr Nc = Visitor.traverse(Condition);
1288 BasicBlock *Ntb = Visitor.reduceBasicBlockRef(ThenBlock);
1289 BasicBlock *Nte = Visitor.reduceBasicBlockRef(ElseBlock);
1290 return Visitor.reduceBranch(*this, Nc, Ntb, Nte);
1293 template <class C> typename C::CType compare(Branch* E, C& Cmp) {
1294 // TODO -- implement CFG comparisons
1295 return Cmp.comparePointers(this, E);
1300 BasicBlock *ThenBlock;
1301 BasicBlock *ElseBlock;
1306 // Defines an interface used to traverse SExprs. Traversals have been made as
1307 // generic as possible, and are intended to handle any kind of pass over the
1308 // AST, e.g. visiters, copying, non-destructive rewriting, destructive
1309 // (in-place) rewriting, hashing, typing, etc.
1311 // Traversals implement the functional notion of a "fold" operation on SExprs.
1312 // Each SExpr class provides a traverse method, which does the following:
1313 // * e->traverse(v):
1314 // // compute a result r_i for each subexpression e_i
1315 // for (i = 1..n) r_i = v.traverse(e_i);
1316 // // combine results into a result for e, where X is the class of e
1317 // return v.reduceX(*e, r_1, .. r_n).
1319 // A visitor can control the traversal by overriding the following methods:
1321 // return v.traverseByCase(e), which returns v.traverseX(e)
1322 // * v.traverseX(e): (X is the class of e)
1323 // return e->traverse(v).
1324 // * v.reduceX(*e, r_1, .. r_n):
1325 // compute a result for a node of type X
1327 // The reduceX methods control the kind of traversal (visitor, copy, etc.).
1328 // These are separated into a separate class R for the purpose of code reuse.
1329 // The full reducer interface also has methods to handle scopes
1330 template <class Self, class R> class Traversal : public R {
1332 Self *self() { return reinterpret_cast<Self *>(this); }
1334 // Traverse an expression -- returning a result of type R_SExpr.
1335 // Override this method to do something for every expression, regardless
1336 // of which kind it is. TraversalKind indicates the context in which
1337 // the expression occurs, and can be:
1339 // TRV_Lazy -- e may need to be traversed lazily, using a Future.
1340 // TRV_Tail -- e occurs in a tail position
1341 typename R::R_SExpr traverse(SExprRef &E, TraversalKind K = TRV_Normal) {
1342 return traverse(E.get(), K);
1345 typename R::R_SExpr traverse(SExpr *E, TraversalKind K = TRV_Normal) {
1346 return traverseByCase(E);
1349 // Helper method to call traverseX(e) on the appropriate type.
1350 typename R::R_SExpr traverseByCase(SExpr *E) {
1351 switch (E->opcode()) {
1352 #define TIL_OPCODE_DEF(X) \
1354 return self()->traverse##X(cast<X>(E));
1355 #include "clang/Analysis/Analyses/ThreadSafetyOps.def"
1356 #undef TIL_OPCODE_DEF
1358 return self()->reduceNull();
1362 // Traverse e, by static dispatch on the type "X" of e.
1363 // Override these methods to do something for a particular kind of term.
1364 #define TIL_OPCODE_DEF(X) \
1365 typename R::R_SExpr traverse##X(X *e) { return e->traverse(*self()); }
1366 #include "clang/Analysis/Analyses/ThreadSafetyOps.def"
1367 #undef TIL_OPCODE_DEF
1371 // Implements a Reducer that makes a deep copy of an SExpr.
1372 // The default behavior of reduce##X(...) is to create a copy of the original.
1373 // Subclasses can override reduce##X to implement non-destructive rewriting
1379 void setArena(MemRegionRef A) { Arena = A; }
1381 // R_SExpr is the result type for a traversal.
1382 // A copy or non-destructive rewrite returns a newly allocated term.
1383 typedef SExpr *R_SExpr;
1385 // Container is a minimal interface used to store results when traversing
1386 // SExprs of variable arity, such as Phi, Goto, and SCFG.
1387 template <class T> class Container {
1389 // Allocate a new container with a capacity for n elements.
1390 Container(CopyReducer &R, unsigned N) : Elems(R.Arena, N) {}
1392 // Push a new element onto the container.
1393 void push_back(T E) { Elems.push_back(E); }
1396 friend class CopyReducer;
1397 SimpleArray<T> Elems;
1401 R_SExpr reduceNull() {
1404 // R_SExpr reduceFuture(...) is never used.
1406 R_SExpr reduceUndefined(Undefined &Orig) {
1407 return new (Arena) Undefined(Orig);
1409 R_SExpr reduceWildcard(Wildcard &Orig) {
1410 return new (Arena) Wildcard(Orig);
1413 R_SExpr reduceLiteral(Literal &Orig) {
1414 return new (Arena) Literal(Orig);
1416 R_SExpr reduceLiteralPtr(LiteralPtr &Orig) {
1417 return new (Arena) LiteralPtr(Orig);
1420 R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) {
1421 return new (Arena) Function(Orig, Nvd, E0);
1423 R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) {
1424 return new (Arena) SFunction(Orig, Nvd, E0);
1426 R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) {
1427 return new (Arena) Code(Orig, E0, E1);
1430 R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) {
1431 return new (Arena) Apply(Orig, E0, E1);
1433 R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) {
1434 return new (Arena) SApply(Orig, E0, E1);
1436 R_SExpr reduceProject(Project &Orig, R_SExpr E0) {
1437 return new (Arena) Project(Orig, E0);
1439 R_SExpr reduceCall(Call &Orig, R_SExpr E0) {
1440 return new (Arena) Call(Orig, E0);
1443 R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) {
1444 return new (Arena) Alloc(Orig, E0);
1446 R_SExpr reduceLoad(Load &Orig, R_SExpr E0) {
1447 return new (Arena) Load(Orig, E0);
1449 R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) {
1450 return new (Arena) Store(Orig, E0, E1);
1452 R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) {
1453 return new (Arena) UnaryOp(Orig, E0);
1455 R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) {
1456 return new (Arena) BinaryOp(Orig, E0, E1);
1458 R_SExpr reduceCast(Cast &Orig, R_SExpr E0) {
1459 return new (Arena) Cast(Orig, E0);
1462 R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> &Bbs) {
1463 return new (Arena) SCFG(Orig, std::move(Bbs.Elems));
1465 R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) {
1466 return new (Arena) Phi(Orig, std::move(As.Elems));
1468 R_SExpr reduceGoto(Goto &Orig, BasicBlock *B, unsigned Index) {
1469 return new (Arena) Goto(Orig, B, Index);
1471 R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) {
1472 return new (Arena) Branch(O, C, B0, B1);
1475 BasicBlock *reduceBasicBlock(BasicBlock &Orig, Container<Variable *> &As,
1476 Container<Variable *> &Is, R_SExpr T) {
1477 return new (Arena) BasicBlock(Orig, std::move(As.Elems),
1478 std::move(Is.Elems), T);
1481 // Create a new variable from orig, and push it onto the lexical scope.
1482 Variable *enterScope(Variable &Orig, R_SExpr E0) {
1483 return new (Arena) Variable(Orig, E0);
1485 // Exit the lexical scope of orig.
1486 void exitScope(const Variable &Orig) {}
1488 void enterCFG(SCFG &Cfg) {}
1489 void exitCFG(SCFG &Cfg) {}
1491 // Map Variable references to their rewritten definitions.
1492 Variable *reduceVariableRef(Variable *Ovd) { return Ovd; }
1494 // Map BasicBlock references to their rewritten defs.
1495 BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; }
1502 class SExprCopier : public Traversal<SExprCopier, CopyReducer> {
1504 SExprCopier(MemRegionRef A) { setArena(A); }
1506 // Create a copy of e in region a.
1507 static SExpr *copy(SExpr *E, MemRegionRef A) {
1508 SExprCopier Copier(A);
1509 return Copier.traverse(E);
1514 // Implements a Reducer that visits each subexpression, and returns either
1516 class VisitReducer {
1520 // A visitor returns a bool, representing success or failure.
1521 typedef bool R_SExpr;
1523 // A visitor "container" is a single bool, which accumulates success.
1524 template <class T> class Container {
1526 Container(VisitReducer &R, unsigned N) : Success(true) {}
1527 void push_back(bool E) { Success = Success && E; }
1530 friend class VisitReducer;
1535 R_SExpr reduceNull() { return true; }
1536 R_SExpr reduceUndefined(Undefined &Orig) { return true; }
1537 R_SExpr reduceWildcard(Wildcard &Orig) { return true; }
1539 R_SExpr reduceLiteral(Literal &Orig) { return true; }
1540 R_SExpr reduceLiteralPtr(Literal &Orig) { return true; }
1542 R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) {
1545 R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) {
1548 R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) {
1551 R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) {
1554 R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) {
1557 R_SExpr reduceProject(Project &Orig, R_SExpr E0) { return E0; }
1558 R_SExpr reduceCall(Call &Orig, R_SExpr E0) { return E0; }
1559 R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) { return E0; }
1560 R_SExpr reduceLoad(Load &Orig, R_SExpr E0) { return E0; }
1561 R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) { return E0 && E1; }
1562 R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) { return E0; }
1563 R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) {
1566 R_SExpr reduceCast(Cast &Orig, R_SExpr E0) { return E0; }
1568 R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> Bbs) {
1571 R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) {
1574 R_SExpr reduceGoto(Goto &Orig, BasicBlock *B, unsigned Index) {
1577 R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) {
1581 BasicBlock *reduceBasicBlock(BasicBlock &Orig, Container<Variable *> &As,
1582 Container<Variable *> &Is, R_SExpr T) {
1583 return (As.Success && Is.Success && T) ? &Orig : nullptr;
1586 Variable *enterScope(Variable &Orig, R_SExpr E0) {
1587 return E0 ? &Orig : nullptr;
1589 void exitScope(const Variable &Orig) {}
1591 void enterCFG(SCFG &Cfg) {}
1592 void exitCFG(SCFG &Cfg) {}
1594 Variable *reduceVariableRef(Variable *Ovd) { return Ovd; }
1596 BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; }
1600 // A visitor will visit each node, and halt if any reducer returns false.
1601 template <class Self>
1602 class SExprVisitor : public Traversal<Self, VisitReducer> {
1604 SExprVisitor() : Success(true) {}
1606 bool traverse(SExpr *E, TraversalKind K = TRV_Normal) {
1607 Success = Success && this->traverseByCase(E);
1611 static bool visit(SExpr *E) {
1612 SExprVisitor Visitor;
1613 return Visitor.traverse(E);
1621 // Basic class for comparison operations over expressions.
1622 template <typename Self>
1625 Self *self() { return reinterpret_cast<Self *>(this); }
1628 bool compareByCase(SExpr *E1, SExpr* E2) {
1629 switch (E1->opcode()) {
1630 #define TIL_OPCODE_DEF(X) \
1632 return cast<X>(E1)->compare(cast<X>(E2), *self());
1633 #include "clang/Analysis/Analyses/ThreadSafetyOps.def"
1634 #undef TIL_OPCODE_DEF
1642 class EqualsComparator : public Comparator<EqualsComparator> {
1644 // Result type for the comparison, e.g. bool for simple equality,
1645 // or int for lexigraphic comparison (-1, 0, 1). Must have one value which
1649 CType trueResult() { return true; }
1650 bool notTrue(CType ct) { return !ct; }
1652 bool compareIntegers(unsigned i, unsigned j) { return i == j; }
1653 bool comparePointers(const void* P, const void* Q) { return P == Q; }
1655 bool compare(SExpr *E1, SExpr* E2) {
1656 if (E1->opcode() != E2->opcode())
1658 return compareByCase(E1, E2);
1661 // TODO -- handle alpha-renaming of variables
1662 void enterScope(Variable* V1, Variable* V2) { }
1663 void leaveScope() { }
1665 bool compareVariableRefs(Variable* V1, Variable* V2) {
1669 static bool compareExprs(SExpr *E1, SExpr* E2) {
1670 EqualsComparator Eq;
1671 return Eq.compare(E1, E2);
1676 // Pretty printer for TIL expressions
1677 template <typename Self, typename StreamType>
1678 class PrettyPrinter {
1680 static void print(SExpr *E, StreamType &SS) {
1682 printer.printSExpr(E, SS, Prec_MAX);
1686 Self *self() { return reinterpret_cast<Self *>(this); }
1688 void newline(StreamType &SS) {
1692 // TODO: further distinguish between binary operations.
1693 static const unsigned Prec_Atom = 0;
1694 static const unsigned Prec_Postfix = 1;
1695 static const unsigned Prec_Unary = 2;
1696 static const unsigned Prec_Binary = 3;
1697 static const unsigned Prec_Other = 4;
1698 static const unsigned Prec_Decl = 5;
1699 static const unsigned Prec_MAX = 6;
1701 // Return the precedence of a given node, for use in pretty printing.
1702 unsigned precedence(SExpr *E) {
1703 switch (E->opcode()) {
1704 case COP_Future: return Prec_Atom;
1705 case COP_Undefined: return Prec_Atom;
1706 case COP_Wildcard: return Prec_Atom;
1708 case COP_Literal: return Prec_Atom;
1709 case COP_LiteralPtr: return Prec_Atom;
1710 case COP_Variable: return Prec_Atom;
1711 case COP_Function: return Prec_Decl;
1712 case COP_SFunction: return Prec_Decl;
1713 case COP_Code: return Prec_Decl;
1715 case COP_Apply: return Prec_Postfix;
1716 case COP_SApply: return Prec_Postfix;
1717 case COP_Project: return Prec_Postfix;
1719 case COP_Call: return Prec_Postfix;
1720 case COP_Alloc: return Prec_Other;
1721 case COP_Load: return Prec_Postfix;
1722 case COP_Store: return Prec_Other;
1724 case COP_UnaryOp: return Prec_Unary;
1725 case COP_BinaryOp: return Prec_Binary;
1726 case COP_Cast: return Prec_Unary;
1728 case COP_SCFG: return Prec_Decl;
1729 case COP_Phi: return Prec_Atom;
1730 case COP_Goto: return Prec_Atom;
1731 case COP_Branch: return Prec_Atom;
1732 case COP_MAX: return Prec_MAX;
1737 void printSExpr(SExpr *E, StreamType &SS, unsigned P) {
1739 self()->printNull(SS);
1742 if (self()->precedence(E) > P) {
1743 // Wrap expr in () if necessary.
1745 self()->printSExpr(E, SS, Prec_MAX);
1750 switch (E->opcode()) {
1751 #define TIL_OPCODE_DEF(X) \
1753 self()->print##X(cast<X>(E), SS); \
1755 #include "clang/Analysis/Analyses/ThreadSafetyOps.def"
1756 #undef TIL_OPCODE_DEF
1762 void printNull(StreamType &SS) {
1766 void printFuture(Future *E, StreamType &SS) {
1767 self()->printSExpr(E->maybeGetResult(), SS, Prec_Atom);
1770 void printUndefined(Undefined *E, StreamType &SS) {
1774 void printWildcard(Wildcard *E, StreamType &SS) {
1778 void printLiteral(Literal *E, StreamType &SS) {
1779 // TODO: actually pretty print the literal.
1783 void printLiteralPtr(LiteralPtr *E, StreamType &SS) {
1784 SS << E->clangDecl()->getName();
1787 void printVariable(Variable *E, StreamType &SS) {
1788 SS << E->name() << E->getBlockID() << "_" << E->getID();
1791 void printFunction(Function *E, StreamType &SS, unsigned sugared = 0) {
1794 SS << "\\("; // Lambda
1796 SS << "("; // Slot declarations
1799 SS << ", "; // Curried functions
1802 self()->printVariable(E->variableDecl(), SS);
1804 self()->printSExpr(E->variableDecl()->definition(), SS, Prec_MAX);
1806 SExpr *B = E->body();
1807 if (B && B->opcode() == COP_Function)
1808 self()->printFunction(cast<Function>(B), SS, 2);
1810 self()->printSExpr(B, SS, Prec_Decl);
1813 void printSFunction(SFunction *E, StreamType &SS) {
1815 self()->printVariable(E->variableDecl(), SS);
1817 self()->printSExpr(E->body(), SS, Prec_Decl);
1820 void printCode(Code *E, StreamType &SS) {
1822 self()->printSExpr(E->returnType(), SS, Prec_Decl-1);
1824 self()->printSExpr(E->body(), SS, Prec_Decl);
1827 void printApply(Apply *E, StreamType &SS, bool sugared = false) {
1828 SExpr *F = E->fun();
1829 if (F->opcode() == COP_Apply) {
1830 printApply(cast<Apply>(F), SS, true);
1833 self()->printSExpr(F, SS, Prec_Postfix);
1836 self()->printSExpr(E->arg(), SS, Prec_MAX);
1841 void printSApply(SApply *E, StreamType &SS) {
1842 self()->printSExpr(E->sfun(), SS, Prec_Postfix);
1844 self()->printSExpr(E->arg(), SS, Prec_MAX);
1848 void printProject(Project *E, StreamType &SS) {
1849 self()->printSExpr(E->record(), SS, Prec_Postfix);
1851 SS << E->slotName();
1854 void printCall(Call *E, StreamType &SS) {
1855 SExpr *T = E->target();
1856 if (T->opcode() == COP_Apply) {
1857 self()->printApply(cast<Apply>(T), SS, true);
1861 self()->printSExpr(T, SS, Prec_Postfix);
1866 void printAlloc(Alloc *E, StreamType &SS) {
1868 self()->printSExpr(E->dataType(), SS, Prec_Other-1);
1871 void printLoad(Load *E, StreamType &SS) {
1872 self()->printSExpr(E->pointer(), SS, Prec_Postfix);
1876 void printStore(Store *E, StreamType &SS) {
1877 self()->printSExpr(E->destination(), SS, Prec_Other-1);
1879 self()->printSExpr(E->source(), SS, Prec_Other-1);
1882 void printUnaryOp(UnaryOp *E, StreamType &SS) {
1883 self()->printSExpr(E->expr(), SS, Prec_Unary);
1886 void printBinaryOp(BinaryOp *E, StreamType &SS) {
1887 self()->printSExpr(E->expr0(), SS, Prec_Binary-1);
1888 SS << " " << clang::BinaryOperator::getOpcodeStr(E->binaryOpcode()) << " ";
1889 self()->printSExpr(E->expr1(), SS, Prec_Binary-1);
1892 void printCast(Cast *E, StreamType &SS) {
1894 self()->printSExpr(E->expr(), SS, Prec_Unary);
1897 void printSCFG(SCFG *E, StreamType &SS) {
1899 for (auto BBI : *E) {
1900 SS << "BB_" << BBI->blockID() << ":";
1902 for (auto A : BBI->arguments()) {
1904 self()->printVariable(A, SS);
1906 self()->printSExpr(A->definition(), SS, Prec_MAX);
1910 for (auto I : BBI->instructions()) {
1912 self()->printVariable(I, SS);
1914 self()->printSExpr(I->definition(), SS, Prec_MAX);
1918 SExpr *T = BBI->terminator();
1920 self()->printSExpr(T, SS, Prec_MAX);
1930 void printPhi(Phi *E, StreamType &SS) {
1933 for (auto V : E->values()) {
1937 self()->printSExpr(V, SS, Prec_MAX);
1942 void printGoto(Goto *E, StreamType &SS) {
1944 SS << E->targetBlock()->blockID();
1949 void printBranch(Branch *E, StreamType &SS) {
1951 self()->printSExpr(E->condition(), SS, Prec_MAX);
1953 SS << E->thenBlock()->blockID();
1955 SS << E->elseBlock()->blockID();
1959 } // end namespace til
1963 } // end namespace threadSafety
1964 } // end namespace clang
1966 #endif // THREAD_SAFETY_TIL_H