1 //===- ThreadSafetyTraverse.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 framework for doing generic traversals and rewriting
11 // operations over the Thread Safety TIL.
13 // UNDER CONSTRUCTION. USE AT YOUR OWN RISK.
15 //===----------------------------------------------------------------------===//
17 #ifndef LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H
18 #define LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H
20 #include "ThreadSafetyTIL.h"
23 namespace threadSafety {
26 // Defines an interface used to traverse SExprs. Traversals have been made as
27 // generic as possible, and are intended to handle any kind of pass over the
28 // AST, e.g. visiters, copying, non-destructive rewriting, destructive
29 // (in-place) rewriting, hashing, typing, etc.
31 // Traversals implement the functional notion of a "fold" operation on SExprs.
32 // Each SExpr class provides a traverse method, which does the following:
34 // // compute a result r_i for each subexpression e_i
35 // for (i = 1..n) r_i = v.traverse(e_i);
36 // // combine results into a result for e, where X is the class of e
37 // return v.reduceX(*e, r_1, .. r_n).
39 // A visitor can control the traversal by overriding the following methods:
41 // return v.traverseByCase(e), which returns v.traverseX(e)
42 // * v.traverseX(e): (X is the class of e)
43 // return e->traverse(v).
44 // * v.reduceX(*e, r_1, .. r_n):
45 // compute a result for a node of type X
47 // The reduceX methods control the kind of traversal (visitor, copy, etc.).
48 // They are defined in derived classes.
50 // Class R defines the basic interface types (R_SExpr).
51 template <class Self, class R>
54 Self *self() { return static_cast<Self *>(this); }
56 // Traverse an expression -- returning a result of type R_SExpr.
57 // Override this method to do something for every expression, regardless
58 // of which kind it is.
59 typename R::R_SExpr traverse(SExprRef &E, typename R::R_Ctx Ctx) {
60 return traverse(E.get(), Ctx);
63 typename R::R_SExpr traverse(SExpr *E, typename R::R_Ctx Ctx) {
64 return traverseByCase(E, Ctx);
67 // Helper method to call traverseX(e) on the appropriate type.
68 typename R::R_SExpr traverseByCase(SExpr *E, typename R::R_Ctx Ctx) {
69 switch (E->opcode()) {
70 #define TIL_OPCODE_DEF(X) \
72 return self()->traverse##X(cast<X>(E), Ctx);
73 #include "ThreadSafetyOps.def"
78 // Traverse e, by static dispatch on the type "X" of e.
79 // Override these methods to do something for a particular kind of term.
80 #define TIL_OPCODE_DEF(X) \
81 typename R::R_SExpr traverse##X(X *e, typename R::R_Ctx Ctx) { \
82 return e->traverse(*self(), Ctx); \
84 #include "ThreadSafetyOps.def"
89 // Base class for simple reducers that don't much care about the context.
90 class SimpleReducerBase {
99 // R_Ctx defines a "context" for the traversal, which encodes information
100 // about where a term appears. This can be used to encoding the
101 // "current continuation" for CPS transforms, or other information.
102 typedef TraversalKind R_Ctx;
104 // Create context for an ordinary subexpression.
105 R_Ctx subExprCtx(R_Ctx Ctx) { return TRV_Normal; }
107 // Create context for a subexpression that occurs in a declaration position
108 // (e.g. function body).
109 R_Ctx declCtx(R_Ctx Ctx) { return TRV_Decl; }
111 // Create context for a subexpression that occurs in a position that
112 // should be reduced lazily. (e.g. code body).
113 R_Ctx lazyCtx(R_Ctx Ctx) { return TRV_Lazy; }
115 // Create context for a subexpression that occurs in a type position.
116 R_Ctx typeCtx(R_Ctx Ctx) { return TRV_Type; }
120 // Base class for traversals that rewrite an SExpr to another SExpr.
121 class CopyReducerBase : public SimpleReducerBase {
123 // R_SExpr is the result type for a traversal.
124 // A copy or non-destructive rewrite returns a newly allocated term.
125 typedef SExpr *R_SExpr;
126 typedef BasicBlock *R_BasicBlock;
128 // Container is a minimal interface used to store results when traversing
129 // SExprs of variable arity, such as Phi, Goto, and SCFG.
130 template <class T> class Container {
132 // Allocate a new container with a capacity for n elements.
133 Container(CopyReducerBase &S, unsigned N) : Elems(S.Arena, N) {}
135 // Push a new element onto the container.
136 void push_back(T E) { Elems.push_back(E); }
138 SimpleArray<T> Elems;
141 CopyReducerBase(MemRegionRef A) : Arena(A) {}
148 // Implements a traversal that makes a deep copy of an SExpr.
149 // The default behavior of reduce##X(...) is to create a copy of the original.
150 // Subclasses can override reduce##X to implement non-destructive rewriting
153 class CopyReducer : public Traversal<Self, CopyReducerBase>,
154 public CopyReducerBase {
156 CopyReducer(MemRegionRef A) : CopyReducerBase(A) {}
159 R_SExpr reduceNull() {
162 // R_SExpr reduceFuture(...) is never used.
164 R_SExpr reduceUndefined(Undefined &Orig) {
165 return new (Arena) Undefined(Orig);
167 R_SExpr reduceWildcard(Wildcard &Orig) {
168 return new (Arena) Wildcard(Orig);
171 R_SExpr reduceLiteral(Literal &Orig) {
172 return new (Arena) Literal(Orig);
175 R_SExpr reduceLiteralT(LiteralT<T> &Orig) {
176 return new (Arena) LiteralT<T>(Orig);
178 R_SExpr reduceLiteralPtr(LiteralPtr &Orig) {
179 return new (Arena) LiteralPtr(Orig);
182 R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) {
183 return new (Arena) Function(Orig, Nvd, E0);
185 R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) {
186 return new (Arena) SFunction(Orig, Nvd, E0);
188 R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) {
189 return new (Arena) Code(Orig, E0, E1);
191 R_SExpr reduceField(Field &Orig, R_SExpr E0, R_SExpr E1) {
192 return new (Arena) Field(Orig, E0, E1);
195 R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) {
196 return new (Arena) Apply(Orig, E0, E1);
198 R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) {
199 return new (Arena) SApply(Orig, E0, E1);
201 R_SExpr reduceProject(Project &Orig, R_SExpr E0) {
202 return new (Arena) Project(Orig, E0);
204 R_SExpr reduceCall(Call &Orig, R_SExpr E0) {
205 return new (Arena) Call(Orig, E0);
208 R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) {
209 return new (Arena) Alloc(Orig, E0);
211 R_SExpr reduceLoad(Load &Orig, R_SExpr E0) {
212 return new (Arena) Load(Orig, E0);
214 R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) {
215 return new (Arena) Store(Orig, E0, E1);
217 R_SExpr reduceArrayIndex(ArrayIndex &Orig, R_SExpr E0, R_SExpr E1) {
218 return new (Arena) ArrayIndex(Orig, E0, E1);
220 R_SExpr reduceArrayAdd(ArrayAdd &Orig, R_SExpr E0, R_SExpr E1) {
221 return new (Arena) ArrayAdd(Orig, E0, E1);
223 R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) {
224 return new (Arena) UnaryOp(Orig, E0);
226 R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) {
227 return new (Arena) BinaryOp(Orig, E0, E1);
229 R_SExpr reduceCast(Cast &Orig, R_SExpr E0) {
230 return new (Arena) Cast(Orig, E0);
233 R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> &Bbs) {
234 return nullptr; // FIXME: implement CFG rewriting
236 R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container<Variable *> &As,
237 Container<Variable *> &Is, R_SExpr T) {
238 return nullptr; // FIXME: implement CFG rewriting
240 R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) {
241 return new (Arena) Phi(Orig, std::move(As.Elems));
243 R_SExpr reduceGoto(Goto &Orig, BasicBlock *B) {
244 return new (Arena) Goto(Orig, B, 0); // FIXME: set index
246 R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) {
247 return new (Arena) Branch(O, C, B0, B1, 0, 0); // FIXME: set indices
250 R_SExpr reduceIdentifier(Identifier &Orig) {
251 return new (Arena) Identifier(Orig);
253 R_SExpr reduceIfThenElse(IfThenElse &Orig, R_SExpr C, R_SExpr T, R_SExpr E) {
254 return new (Arena) IfThenElse(Orig, C, T, E);
256 R_SExpr reduceLet(Let &Orig, Variable *Nvd, R_SExpr B) {
257 return new (Arena) Let(Orig, Nvd, B);
260 // Create a new variable from orig, and push it onto the lexical scope.
261 Variable *enterScope(Variable &Orig, R_SExpr E0) {
262 return new (Arena) Variable(Orig, E0);
264 // Exit the lexical scope of orig.
265 void exitScope(const Variable &Orig) {}
267 void enterCFG(SCFG &Cfg) {}
268 void exitCFG(SCFG &Cfg) {}
269 void enterBasicBlock(BasicBlock &BB) {}
270 void exitBasicBlock(BasicBlock &BB) {}
272 // Map Variable references to their rewritten definitions.
273 Variable *reduceVariableRef(Variable *Ovd) { return Ovd; }
275 // Map BasicBlock references to their rewritten definitions.
276 BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; }
280 class SExprCopier : public CopyReducer<SExprCopier> {
282 typedef SExpr *R_SExpr;
284 SExprCopier(MemRegionRef A) : CopyReducer(A) { }
286 // Create a copy of e in region a.
287 static SExpr *copy(SExpr *E, MemRegionRef A) {
288 SExprCopier Copier(A);
289 return Copier.traverse(E, TRV_Normal);
295 // Base class for visit traversals.
296 class VisitReducerBase : public SimpleReducerBase {
298 // A visitor returns a bool, representing success or failure.
299 typedef bool R_SExpr;
300 typedef bool R_BasicBlock;
302 // A visitor "container" is a single bool, which accumulates success.
303 template <class T> class Container {
305 Container(VisitReducerBase &S, unsigned N) : Success(true) {}
306 void push_back(bool E) { Success = Success && E; }
313 // Implements a traversal that visits each subexpression, and returns either
315 template <class Self>
316 class VisitReducer : public Traversal<Self, VisitReducerBase>,
317 public VisitReducerBase {
322 R_SExpr reduceNull() { return true; }
323 R_SExpr reduceUndefined(Undefined &Orig) { return true; }
324 R_SExpr reduceWildcard(Wildcard &Orig) { return true; }
326 R_SExpr reduceLiteral(Literal &Orig) { return true; }
328 R_SExpr reduceLiteralT(LiteralT<T> &Orig) { return true; }
329 R_SExpr reduceLiteralPtr(Literal &Orig) { return true; }
331 R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) {
334 R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) {
337 R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) {
340 R_SExpr reduceField(Field &Orig, R_SExpr E0, R_SExpr E1) {
343 R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) {
346 R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) {
349 R_SExpr reduceProject(Project &Orig, R_SExpr E0) { return E0; }
350 R_SExpr reduceCall(Call &Orig, R_SExpr E0) { return E0; }
351 R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) { return E0; }
352 R_SExpr reduceLoad(Load &Orig, R_SExpr E0) { return E0; }
353 R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) { return E0 && E1; }
354 R_SExpr reduceArrayIndex(Store &Orig, R_SExpr E0, R_SExpr E1) {
357 R_SExpr reduceArrayAdd(Store &Orig, R_SExpr E0, R_SExpr E1) {
360 R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) { return E0; }
361 R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) {
364 R_SExpr reduceCast(Cast &Orig, R_SExpr E0) { return E0; }
366 R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> Bbs) {
369 R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container<Variable *> &As,
370 Container<Variable *> &Is, R_SExpr T) {
371 return (As.Success && Is.Success && T);
373 R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) {
376 R_SExpr reduceGoto(Goto &Orig, BasicBlock *B) {
379 R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) {
383 R_SExpr reduceIdentifier(Identifier &Orig) {
386 R_SExpr reduceIfThenElse(IfThenElse &Orig, R_SExpr C, R_SExpr T, R_SExpr E) {
389 R_SExpr reduceLet(Let &Orig, Variable *Nvd, R_SExpr B) {
393 Variable *enterScope(Variable &Orig, R_SExpr E0) { return &Orig; }
394 void exitScope(const Variable &Orig) {}
395 void enterCFG(SCFG &Cfg) {}
396 void exitCFG(SCFG &Cfg) {}
397 void enterBasicBlock(BasicBlock &BB) {}
398 void exitBasicBlock(BasicBlock &BB) {}
400 Variable *reduceVariableRef (Variable *Ovd) { return Ovd; }
401 BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; }
404 bool traverse(SExpr *E, TraversalKind K = TRV_Normal) {
405 Success = Success && this->traverseByCase(E);
409 static bool visit(SExpr *E) {
411 return Visitor.traverse(E, TRV_Normal);
419 // Basic class for comparison operations over expressions.
420 template <typename Self>
423 Self *self() { return reinterpret_cast<Self *>(this); }
426 bool compareByCase(SExpr *E1, SExpr* E2) {
427 switch (E1->opcode()) {
428 #define TIL_OPCODE_DEF(X) \
430 return cast<X>(E1)->compare(cast<X>(E2), *self());
431 #include "ThreadSafetyOps.def"
432 #undef TIL_OPCODE_DEF
438 class EqualsComparator : public Comparator<EqualsComparator> {
440 // Result type for the comparison, e.g. bool for simple equality,
441 // or int for lexigraphic comparison (-1, 0, 1). Must have one value which
445 CType trueResult() { return true; }
446 bool notTrue(CType ct) { return !ct; }
448 bool compareIntegers(unsigned i, unsigned j) { return i == j; }
449 bool compareStrings (StringRef s, StringRef r) { return s == r; }
450 bool comparePointers(const void* P, const void* Q) { return P == Q; }
452 bool compare(SExpr *E1, SExpr* E2) {
453 if (E1->opcode() != E2->opcode())
455 return compareByCase(E1, E2);
458 // TODO -- handle alpha-renaming of variables
459 void enterScope(Variable* V1, Variable* V2) { }
460 void leaveScope() { }
462 bool compareVariableRefs(Variable* V1, Variable* V2) {
466 static bool compareExprs(SExpr *E1, SExpr* E2) {
468 return Eq.compare(E1, E2);
473 // Pretty printer for TIL expressions
474 template <typename Self, typename StreamType>
475 class PrettyPrinter {
477 bool Verbose; // Print out additional information
478 bool Cleanup; // Omit redundant decls.
481 PrettyPrinter(bool V = false, bool C = true) : Verbose(V), Cleanup(C) { }
483 static void print(SExpr *E, StreamType &SS) {
485 printer.printSExpr(E, SS, Prec_MAX);
489 Self *self() { return reinterpret_cast<Self *>(this); }
491 void newline(StreamType &SS) {
495 // TODO: further distinguish between binary operations.
496 static const unsigned Prec_Atom = 0;
497 static const unsigned Prec_Postfix = 1;
498 static const unsigned Prec_Unary = 2;
499 static const unsigned Prec_Binary = 3;
500 static const unsigned Prec_Other = 4;
501 static const unsigned Prec_Decl = 5;
502 static const unsigned Prec_MAX = 6;
504 // Return the precedence of a given node, for use in pretty printing.
505 unsigned precedence(SExpr *E) {
506 switch (E->opcode()) {
507 case COP_Future: return Prec_Atom;
508 case COP_Undefined: return Prec_Atom;
509 case COP_Wildcard: return Prec_Atom;
511 case COP_Literal: return Prec_Atom;
512 case COP_LiteralPtr: return Prec_Atom;
513 case COP_Variable: return Prec_Atom;
514 case COP_Function: return Prec_Decl;
515 case COP_SFunction: return Prec_Decl;
516 case COP_Code: return Prec_Decl;
517 case COP_Field: return Prec_Decl;
519 case COP_Apply: return Prec_Postfix;
520 case COP_SApply: return Prec_Postfix;
521 case COP_Project: return Prec_Postfix;
523 case COP_Call: return Prec_Postfix;
524 case COP_Alloc: return Prec_Other;
525 case COP_Load: return Prec_Postfix;
526 case COP_Store: return Prec_Other;
527 case COP_ArrayIndex: return Prec_Postfix;
528 case COP_ArrayAdd: return Prec_Postfix;
530 case COP_UnaryOp: return Prec_Unary;
531 case COP_BinaryOp: return Prec_Binary;
532 case COP_Cast: return Prec_Unary;
534 case COP_SCFG: return Prec_Decl;
535 case COP_BasicBlock: return Prec_MAX;
536 case COP_Phi: return Prec_Atom;
537 case COP_Goto: return Prec_Atom;
538 case COP_Branch: return Prec_Atom;
540 case COP_Identifier: return Prec_Atom;
541 case COP_IfThenElse: return Prec_Other;
542 case COP_Let: return Prec_Decl;
547 void printBlockLabel(StreamType & SS, BasicBlock *BB, unsigned index) {
558 void printSExpr(SExpr *E, StreamType &SS, unsigned P) {
560 self()->printNull(SS);
563 if (self()->precedence(E) > P) {
564 // Wrap expr in () if necessary.
566 self()->printSExpr(E, SS, Prec_MAX);
571 switch (E->opcode()) {
572 #define TIL_OPCODE_DEF(X) \
574 self()->print##X(cast<X>(E), SS); \
576 #include "ThreadSafetyOps.def"
577 #undef TIL_OPCODE_DEF
581 void printNull(StreamType &SS) {
585 void printFuture(Future *E, StreamType &SS) {
586 self()->printSExpr(E->maybeGetResult(), SS, Prec_Atom);
589 void printUndefined(Undefined *E, StreamType &SS) {
593 void printWildcard(Wildcard *E, StreamType &SS) {
598 void printLiteralT(LiteralT<T> *E, StreamType &SS) {
602 void printLiteralT(LiteralT<uint8_t> *E, StreamType &SS) {
603 SS << "'" << E->value() << "'";
606 void printLiteral(Literal *E, StreamType &SS) {
607 if (E->clangExpr()) {
608 SS << getSourceLiteralString(E->clangExpr());
612 ValueType VT = E->valueType();
614 case ValueType::BT_Void: {
618 case ValueType::BT_Bool: {
619 if (E->as<bool>().value())
625 case ValueType::BT_Int: {
627 case ValueType::ST_8:
629 printLiteralT(&E->as<int8_t>(), SS);
631 printLiteralT(&E->as<uint8_t>(), SS);
633 case ValueType::ST_16:
635 printLiteralT(&E->as<int16_t>(), SS);
637 printLiteralT(&E->as<uint16_t>(), SS);
639 case ValueType::ST_32:
641 printLiteralT(&E->as<int32_t>(), SS);
643 printLiteralT(&E->as<uint32_t>(), SS);
645 case ValueType::ST_64:
647 printLiteralT(&E->as<int64_t>(), SS);
649 printLiteralT(&E->as<uint64_t>(), SS);
656 case ValueType::BT_Float: {
658 case ValueType::ST_32:
659 printLiteralT(&E->as<float>(), SS);
661 case ValueType::ST_64:
662 printLiteralT(&E->as<double>(), SS);
669 case ValueType::BT_String: {
671 printLiteralT(&E->as<StringRef>(), SS);
675 case ValueType::BT_Pointer: {
679 case ValueType::BT_ValueRef: {
688 void printLiteralPtr(LiteralPtr *E, StreamType &SS) {
689 SS << E->clangDecl()->getNameAsString();
692 void printVariable(Variable *V, StreamType &SS, bool IsVarDecl = false) {
693 if (!IsVarDecl && Cleanup) {
694 SExpr* E = getCanonicalVal(V);
696 printSExpr(E, SS, Prec_Atom);
700 if (V->kind() == Variable::VK_LetBB)
701 SS << V->name() << V->getBlockID() << "_" << V->getID();
703 SS << V->name() << V->getID();
706 void printFunction(Function *E, StreamType &SS, unsigned sugared = 0) {
709 SS << "\\("; // Lambda
712 SS << "("; // Slot declarations
715 SS << ", "; // Curried functions
718 self()->printVariable(E->variableDecl(), SS, true);
720 self()->printSExpr(E->variableDecl()->definition(), SS, Prec_MAX);
722 SExpr *B = E->body();
723 if (B && B->opcode() == COP_Function)
724 self()->printFunction(cast<Function>(B), SS, 2);
727 self()->printSExpr(B, SS, Prec_Decl);
731 void printSFunction(SFunction *E, StreamType &SS) {
733 self()->printVariable(E->variableDecl(), SS, true);
735 self()->printSExpr(E->body(), SS, Prec_Decl);
738 void printCode(Code *E, StreamType &SS) {
740 self()->printSExpr(E->returnType(), SS, Prec_Decl-1);
742 self()->printSExpr(E->body(), SS, Prec_Decl);
745 void printField(Field *E, StreamType &SS) {
747 self()->printSExpr(E->range(), SS, Prec_Decl-1);
749 self()->printSExpr(E->body(), SS, Prec_Decl);
752 void printApply(Apply *E, StreamType &SS, bool sugared = false) {
754 if (F->opcode() == COP_Apply) {
755 printApply(cast<Apply>(F), SS, true);
758 self()->printSExpr(F, SS, Prec_Postfix);
761 self()->printSExpr(E->arg(), SS, Prec_MAX);
766 void printSApply(SApply *E, StreamType &SS) {
767 self()->printSExpr(E->sfun(), SS, Prec_Postfix);
768 if (E->isDelegation()) {
770 self()->printSExpr(E->arg(), SS, Prec_MAX);
775 void printProject(Project *E, StreamType &SS) {
776 self()->printSExpr(E->record(), SS, Prec_Postfix);
781 void printCall(Call *E, StreamType &SS) {
782 SExpr *T = E->target();
783 if (T->opcode() == COP_Apply) {
784 self()->printApply(cast<Apply>(T), SS, true);
788 self()->printSExpr(T, SS, Prec_Postfix);
793 void printAlloc(Alloc *E, StreamType &SS) {
795 self()->printSExpr(E->dataType(), SS, Prec_Other-1);
798 void printLoad(Load *E, StreamType &SS) {
799 self()->printSExpr(E->pointer(), SS, Prec_Postfix);
803 void printStore(Store *E, StreamType &SS) {
804 self()->printSExpr(E->destination(), SS, Prec_Other-1);
806 self()->printSExpr(E->source(), SS, Prec_Other-1);
809 void printArrayIndex(ArrayIndex *E, StreamType &SS) {
810 self()->printSExpr(E->array(), SS, Prec_Postfix);
812 self()->printSExpr(E->index(), SS, Prec_MAX);
816 void printArrayAdd(ArrayAdd *E, StreamType &SS) {
817 self()->printSExpr(E->array(), SS, Prec_Postfix);
819 self()->printSExpr(E->index(), SS, Prec_Atom);
822 void printUnaryOp(UnaryOp *E, StreamType &SS) {
823 SS << getUnaryOpcodeString(E->unaryOpcode());
824 self()->printSExpr(E->expr(), SS, Prec_Unary);
827 void printBinaryOp(BinaryOp *E, StreamType &SS) {
828 self()->printSExpr(E->expr0(), SS, Prec_Binary-1);
829 SS << " " << getBinaryOpcodeString(E->binaryOpcode()) << " ";
830 self()->printSExpr(E->expr1(), SS, Prec_Binary-1);
833 void printCast(Cast *E, StreamType &SS) {
835 self()->printSExpr(E->expr(), SS, Prec_Unary);
838 void printSCFG(SCFG *E, StreamType &SS) {
840 for (auto BBI : *E) {
841 printBasicBlock(BBI, SS);
847 void printBasicBlock(BasicBlock *E, StreamType &SS) {
848 SS << "BB_" << E->blockID() << ":";
850 SS << " BB_" << E->parent()->blockID();
852 for (auto *A : E->arguments()) {
854 self()->printVariable(A, SS, true);
856 self()->printSExpr(A->definition(), SS, Prec_MAX);
860 for (auto *I : E->instructions()) {
861 if (I->definition()->opcode() != COP_Store) {
863 self()->printVariable(I, SS, true);
866 self()->printSExpr(I->definition(), SS, Prec_MAX);
870 SExpr *T = E->terminator();
872 self()->printSExpr(T, SS, Prec_MAX);
879 void printPhi(Phi *E, StreamType &SS) {
881 if (E->status() == Phi::PH_SingleVal)
882 self()->printSExpr(E->values()[0], SS, Prec_MAX);
885 for (auto V : E->values()) {
888 self()->printSExpr(V, SS, Prec_MAX);
894 void printGoto(Goto *E, StreamType &SS) {
896 printBlockLabel(SS, E->targetBlock(), E->index());
899 void printBranch(Branch *E, StreamType &SS) {
901 self()->printSExpr(E->condition(), SS, Prec_MAX);
903 printBlockLabel(SS, E->thenBlock(), E->thenIndex());
905 printBlockLabel(SS, E->elseBlock(), E->elseIndex());
908 void printIdentifier(Identifier *E, StreamType &SS) {
912 void printIfThenElse(IfThenElse *E, StreamType &SS) {
914 printSExpr(E->condition(), SS, Prec_MAX);
916 printSExpr(E->thenExpr(), SS, Prec_Other);
918 printSExpr(E->elseExpr(), SS, Prec_Other);
921 void printLet(Let *E, StreamType &SS) {
923 printVariable(E->variableDecl(), SS, true);
925 printSExpr(E->variableDecl()->definition(), SS, Prec_Decl-1);
927 printSExpr(E->body(), SS, Prec_Decl-1);
932 } // end namespace til
933 } // end namespace threadSafety
934 } // end namespace clang
936 #endif // LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H