clang API Documentation
00001 //===- ThreadSafetyTraverse.h ----------------------------------*- C++ --*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines a framework for doing generic traversals and rewriting 00011 // operations over the Thread Safety TIL. 00012 // 00013 // UNDER CONSTRUCTION. USE AT YOUR OWN RISK. 00014 // 00015 //===----------------------------------------------------------------------===// 00016 00017 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H 00018 #define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H 00019 00020 #include "ThreadSafetyTIL.h" 00021 00022 #include <ostream> 00023 00024 namespace clang { 00025 namespace threadSafety { 00026 namespace til { 00027 00028 // Defines an interface used to traverse SExprs. Traversals have been made as 00029 // generic as possible, and are intended to handle any kind of pass over the 00030 // AST, e.g. visiters, copying, non-destructive rewriting, destructive 00031 // (in-place) rewriting, hashing, typing, etc. 00032 // 00033 // Traversals implement the functional notion of a "fold" operation on SExprs. 00034 // Each SExpr class provides a traverse method, which does the following: 00035 // * e->traverse(v): 00036 // // compute a result r_i for each subexpression e_i 00037 // for (i = 1..n) r_i = v.traverse(e_i); 00038 // // combine results into a result for e, where X is the class of e 00039 // return v.reduceX(*e, r_1, .. r_n). 00040 // 00041 // A visitor can control the traversal by overriding the following methods: 00042 // * v.traverse(e): 00043 // return v.traverseByCase(e), which returns v.traverseX(e) 00044 // * v.traverseX(e): (X is the class of e) 00045 // return e->traverse(v). 00046 // * v.reduceX(*e, r_1, .. r_n): 00047 // compute a result for a node of type X 00048 // 00049 // The reduceX methods control the kind of traversal (visitor, copy, etc.). 00050 // They are defined in derived classes. 00051 // 00052 // Class R defines the basic interface types (R_SExpr). 00053 template <class Self, class R> 00054 class Traversal { 00055 public: 00056 Self *self() { return static_cast<Self *>(this); } 00057 00058 // Traverse an expression -- returning a result of type R_SExpr. 00059 // Override this method to do something for every expression, regardless 00060 // of which kind it is. 00061 // E is a reference, so this can be use for in-place updates. 00062 // The type T must be a subclass of SExpr. 00063 template <class T> 00064 typename R::R_SExpr traverse(T* &E, typename R::R_Ctx Ctx) { 00065 return traverseSExpr(E, Ctx); 00066 } 00067 00068 // Override this method to do something for every expression. 00069 // Does not allow in-place updates. 00070 typename R::R_SExpr traverseSExpr(SExpr *E, typename R::R_Ctx Ctx) { 00071 return traverseByCase(E, Ctx); 00072 } 00073 00074 // Helper method to call traverseX(e) on the appropriate type. 00075 typename R::R_SExpr traverseByCase(SExpr *E, typename R::R_Ctx Ctx) { 00076 switch (E->opcode()) { 00077 #define TIL_OPCODE_DEF(X) \ 00078 case COP_##X: \ 00079 return self()->traverse##X(cast<X>(E), Ctx); 00080 #include "ThreadSafetyOps.def" 00081 #undef TIL_OPCODE_DEF 00082 } 00083 return self()->reduceNull(); 00084 } 00085 00086 // Traverse e, by static dispatch on the type "X" of e. 00087 // Override these methods to do something for a particular kind of term. 00088 #define TIL_OPCODE_DEF(X) \ 00089 typename R::R_SExpr traverse##X(X *e, typename R::R_Ctx Ctx) { \ 00090 return e->traverse(*self(), Ctx); \ 00091 } 00092 #include "ThreadSafetyOps.def" 00093 #undef TIL_OPCODE_DEF 00094 }; 00095 00096 00097 // Base class for simple reducers that don't much care about the context. 00098 class SimpleReducerBase { 00099 public: 00100 enum TraversalKind { 00101 TRV_Normal, // ordinary subexpressions 00102 TRV_Decl, // declarations (e.g. function bodies) 00103 TRV_Lazy, // expressions that require lazy evaluation 00104 TRV_Type // type expressions 00105 }; 00106 00107 // R_Ctx defines a "context" for the traversal, which encodes information 00108 // about where a term appears. This can be used to encoding the 00109 // "current continuation" for CPS transforms, or other information. 00110 typedef TraversalKind R_Ctx; 00111 00112 // Create context for an ordinary subexpression. 00113 R_Ctx subExprCtx(R_Ctx Ctx) { return TRV_Normal; } 00114 00115 // Create context for a subexpression that occurs in a declaration position 00116 // (e.g. function body). 00117 R_Ctx declCtx(R_Ctx Ctx) { return TRV_Decl; } 00118 00119 // Create context for a subexpression that occurs in a position that 00120 // should be reduced lazily. (e.g. code body). 00121 R_Ctx lazyCtx(R_Ctx Ctx) { return TRV_Lazy; } 00122 00123 // Create context for a subexpression that occurs in a type position. 00124 R_Ctx typeCtx(R_Ctx Ctx) { return TRV_Type; } 00125 }; 00126 00127 00128 // Base class for traversals that rewrite an SExpr to another SExpr. 00129 class CopyReducerBase : public SimpleReducerBase { 00130 public: 00131 // R_SExpr is the result type for a traversal. 00132 // A copy or non-destructive rewrite returns a newly allocated term. 00133 typedef SExpr *R_SExpr; 00134 typedef BasicBlock *R_BasicBlock; 00135 00136 // Container is a minimal interface used to store results when traversing 00137 // SExprs of variable arity, such as Phi, Goto, and SCFG. 00138 template <class T> class Container { 00139 public: 00140 // Allocate a new container with a capacity for n elements. 00141 Container(CopyReducerBase &S, unsigned N) : Elems(S.Arena, N) {} 00142 00143 // Push a new element onto the container. 00144 void push_back(T E) { Elems.push_back(E); } 00145 00146 SimpleArray<T> Elems; 00147 }; 00148 00149 CopyReducerBase(MemRegionRef A) : Arena(A) {} 00150 00151 protected: 00152 MemRegionRef Arena; 00153 }; 00154 00155 00156 // Base class for visit traversals. 00157 class VisitReducerBase : public SimpleReducerBase { 00158 public: 00159 // A visitor returns a bool, representing success or failure. 00160 typedef bool R_SExpr; 00161 typedef bool R_BasicBlock; 00162 00163 // A visitor "container" is a single bool, which accumulates success. 00164 template <class T> class Container { 00165 public: 00166 Container(VisitReducerBase &S, unsigned N) : Success(true) {} 00167 void push_back(bool E) { Success = Success && E; } 00168 00169 bool Success; 00170 }; 00171 }; 00172 00173 00174 // Implements a traversal that visits each subexpression, and returns either 00175 // true or false. 00176 template <class Self> 00177 class VisitReducer : public Traversal<Self, VisitReducerBase>, 00178 public VisitReducerBase { 00179 public: 00180 VisitReducer() {} 00181 00182 public: 00183 R_SExpr reduceNull() { return true; } 00184 R_SExpr reduceUndefined(Undefined &Orig) { return true; } 00185 R_SExpr reduceWildcard(Wildcard &Orig) { return true; } 00186 00187 R_SExpr reduceLiteral(Literal &Orig) { return true; } 00188 template<class T> 00189 R_SExpr reduceLiteralT(LiteralT<T> &Orig) { return true; } 00190 R_SExpr reduceLiteralPtr(Literal &Orig) { return true; } 00191 00192 R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) { 00193 return Nvd && E0; 00194 } 00195 R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) { 00196 return Nvd && E0; 00197 } 00198 R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) { 00199 return E0 && E1; 00200 } 00201 R_SExpr reduceField(Field &Orig, R_SExpr E0, R_SExpr E1) { 00202 return E0 && E1; 00203 } 00204 R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) { 00205 return E0 && E1; 00206 } 00207 R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) { 00208 return E0 && E1; 00209 } 00210 R_SExpr reduceProject(Project &Orig, R_SExpr E0) { return E0; } 00211 R_SExpr reduceCall(Call &Orig, R_SExpr E0) { return E0; } 00212 R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) { return E0; } 00213 R_SExpr reduceLoad(Load &Orig, R_SExpr E0) { return E0; } 00214 R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) { return E0 && E1; } 00215 R_SExpr reduceArrayIndex(Store &Orig, R_SExpr E0, R_SExpr E1) { 00216 return E0 && E1; 00217 } 00218 R_SExpr reduceArrayAdd(Store &Orig, R_SExpr E0, R_SExpr E1) { 00219 return E0 && E1; 00220 } 00221 R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) { return E0; } 00222 R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) { 00223 return E0 && E1; 00224 } 00225 R_SExpr reduceCast(Cast &Orig, R_SExpr E0) { return E0; } 00226 00227 R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> Bbs) { 00228 return Bbs.Success; 00229 } 00230 R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container<R_SExpr> &As, 00231 Container<R_SExpr> &Is, R_SExpr T) { 00232 return (As.Success && Is.Success && T); 00233 } 00234 R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) { 00235 return As.Success; 00236 } 00237 R_SExpr reduceGoto(Goto &Orig, BasicBlock *B) { 00238 return true; 00239 } 00240 R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) { 00241 return C; 00242 } 00243 R_SExpr reduceReturn(Return &O, R_SExpr E) { 00244 return E; 00245 } 00246 00247 R_SExpr reduceIdentifier(Identifier &Orig) { 00248 return true; 00249 } 00250 R_SExpr reduceIfThenElse(IfThenElse &Orig, R_SExpr C, R_SExpr T, R_SExpr E) { 00251 return C && T && E; 00252 } 00253 R_SExpr reduceLet(Let &Orig, Variable *Nvd, R_SExpr B) { 00254 return Nvd && B; 00255 } 00256 00257 Variable *enterScope(Variable &Orig, R_SExpr E0) { return &Orig; } 00258 void exitScope(const Variable &Orig) {} 00259 void enterCFG(SCFG &Cfg) {} 00260 void exitCFG(SCFG &Cfg) {} 00261 void enterBasicBlock(BasicBlock &BB) {} 00262 void exitBasicBlock(BasicBlock &BB) {} 00263 00264 Variable *reduceVariableRef (Variable *Ovd) { return Ovd; } 00265 BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; } 00266 00267 public: 00268 bool traverse(SExpr *E, TraversalKind K = TRV_Normal) { 00269 Success = Success && this->traverseByCase(E); 00270 return Success; 00271 } 00272 00273 static bool visit(SExpr *E) { 00274 Self Visitor; 00275 return Visitor.traverse(E, TRV_Normal); 00276 } 00277 00278 private: 00279 bool Success; 00280 }; 00281 00282 00283 // Basic class for comparison operations over expressions. 00284 template <typename Self> 00285 class Comparator { 00286 protected: 00287 Self *self() { return reinterpret_cast<Self *>(this); } 00288 00289 public: 00290 bool compareByCase(const SExpr *E1, const SExpr* E2) { 00291 switch (E1->opcode()) { 00292 #define TIL_OPCODE_DEF(X) \ 00293 case COP_##X: \ 00294 return cast<X>(E1)->compare(cast<X>(E2), *self()); 00295 #include "ThreadSafetyOps.def" 00296 #undef TIL_OPCODE_DEF 00297 } 00298 return false; 00299 } 00300 }; 00301 00302 00303 class EqualsComparator : public Comparator<EqualsComparator> { 00304 public: 00305 // Result type for the comparison, e.g. bool for simple equality, 00306 // or int for lexigraphic comparison (-1, 0, 1). Must have one value which 00307 // denotes "true". 00308 typedef bool CType; 00309 00310 CType trueResult() { return true; } 00311 bool notTrue(CType ct) { return !ct; } 00312 00313 bool compareIntegers(unsigned i, unsigned j) { return i == j; } 00314 bool compareStrings (StringRef s, StringRef r) { return s == r; } 00315 bool comparePointers(const void* P, const void* Q) { return P == Q; } 00316 00317 bool compare(const SExpr *E1, const SExpr* E2) { 00318 if (E1->opcode() != E2->opcode()) 00319 return false; 00320 return compareByCase(E1, E2); 00321 } 00322 00323 // TODO -- handle alpha-renaming of variables 00324 void enterScope(const Variable* V1, const Variable* V2) { } 00325 void leaveScope() { } 00326 00327 bool compareVariableRefs(const Variable* V1, const Variable* V2) { 00328 return V1 == V2; 00329 } 00330 00331 static bool compareExprs(const SExpr *E1, const SExpr* E2) { 00332 EqualsComparator Eq; 00333 return Eq.compare(E1, E2); 00334 } 00335 }; 00336 00337 00338 00339 class MatchComparator : public Comparator<MatchComparator> { 00340 public: 00341 // Result type for the comparison, e.g. bool for simple equality, 00342 // or int for lexigraphic comparison (-1, 0, 1). Must have one value which 00343 // denotes "true". 00344 typedef bool CType; 00345 00346 CType trueResult() { return true; } 00347 bool notTrue(CType ct) { return !ct; } 00348 00349 bool compareIntegers(unsigned i, unsigned j) { return i == j; } 00350 bool compareStrings (StringRef s, StringRef r) { return s == r; } 00351 bool comparePointers(const void* P, const void* Q) { return P == Q; } 00352 00353 bool compare(const SExpr *E1, const SExpr* E2) { 00354 // Wildcards match anything. 00355 if (E1->opcode() == COP_Wildcard || E2->opcode() == COP_Wildcard) 00356 return true; 00357 // otherwise normal equality. 00358 if (E1->opcode() != E2->opcode()) 00359 return false; 00360 return compareByCase(E1, E2); 00361 } 00362 00363 // TODO -- handle alpha-renaming of variables 00364 void enterScope(const Variable* V1, const Variable* V2) { } 00365 void leaveScope() { } 00366 00367 bool compareVariableRefs(const Variable* V1, const Variable* V2) { 00368 return V1 == V2; 00369 } 00370 00371 static bool compareExprs(const SExpr *E1, const SExpr* E2) { 00372 MatchComparator Matcher; 00373 return Matcher.compare(E1, E2); 00374 } 00375 }; 00376 00377 00378 00379 // inline std::ostream& operator<<(std::ostream& SS, StringRef R) { 00380 // return SS.write(R.data(), R.size()); 00381 // } 00382 00383 // Pretty printer for TIL expressions 00384 template <typename Self, typename StreamType> 00385 class PrettyPrinter { 00386 private: 00387 bool Verbose; // Print out additional information 00388 bool Cleanup; // Omit redundant decls. 00389 bool CStyle; // Print exprs in C-like syntax. 00390 00391 public: 00392 PrettyPrinter(bool V = false, bool C = true, bool CS = true) 00393 : Verbose(V), Cleanup(C), CStyle(CS) 00394 {} 00395 00396 static void print(const SExpr *E, StreamType &SS) { 00397 Self printer; 00398 printer.printSExpr(E, SS, Prec_MAX); 00399 } 00400 00401 protected: 00402 Self *self() { return reinterpret_cast<Self *>(this); } 00403 00404 void newline(StreamType &SS) { 00405 SS << "\n"; 00406 } 00407 00408 // TODO: further distinguish between binary operations. 00409 static const unsigned Prec_Atom = 0; 00410 static const unsigned Prec_Postfix = 1; 00411 static const unsigned Prec_Unary = 2; 00412 static const unsigned Prec_Binary = 3; 00413 static const unsigned Prec_Other = 4; 00414 static const unsigned Prec_Decl = 5; 00415 static const unsigned Prec_MAX = 6; 00416 00417 // Return the precedence of a given node, for use in pretty printing. 00418 unsigned precedence(const SExpr *E) { 00419 switch (E->opcode()) { 00420 case COP_Future: return Prec_Atom; 00421 case COP_Undefined: return Prec_Atom; 00422 case COP_Wildcard: return Prec_Atom; 00423 00424 case COP_Literal: return Prec_Atom; 00425 case COP_LiteralPtr: return Prec_Atom; 00426 case COP_Variable: return Prec_Atom; 00427 case COP_Function: return Prec_Decl; 00428 case COP_SFunction: return Prec_Decl; 00429 case COP_Code: return Prec_Decl; 00430 case COP_Field: return Prec_Decl; 00431 00432 case COP_Apply: return Prec_Postfix; 00433 case COP_SApply: return Prec_Postfix; 00434 case COP_Project: return Prec_Postfix; 00435 00436 case COP_Call: return Prec_Postfix; 00437 case COP_Alloc: return Prec_Other; 00438 case COP_Load: return Prec_Postfix; 00439 case COP_Store: return Prec_Other; 00440 case COP_ArrayIndex: return Prec_Postfix; 00441 case COP_ArrayAdd: return Prec_Postfix; 00442 00443 case COP_UnaryOp: return Prec_Unary; 00444 case COP_BinaryOp: return Prec_Binary; 00445 case COP_Cast: return Prec_Atom; 00446 00447 case COP_SCFG: return Prec_Decl; 00448 case COP_BasicBlock: return Prec_MAX; 00449 case COP_Phi: return Prec_Atom; 00450 case COP_Goto: return Prec_Atom; 00451 case COP_Branch: return Prec_Atom; 00452 case COP_Return: return Prec_Other; 00453 00454 case COP_Identifier: return Prec_Atom; 00455 case COP_IfThenElse: return Prec_Other; 00456 case COP_Let: return Prec_Decl; 00457 } 00458 return Prec_MAX; 00459 } 00460 00461 void printBlockLabel(StreamType & SS, const BasicBlock *BB, int index) { 00462 if (!BB) { 00463 SS << "BB_null"; 00464 return; 00465 } 00466 SS << "BB_"; 00467 SS << BB->blockID(); 00468 if (index >= 0) { 00469 SS << ":"; 00470 SS << index; 00471 } 00472 } 00473 00474 00475 void printSExpr(const SExpr *E, StreamType &SS, unsigned P, bool Sub=true) { 00476 if (!E) { 00477 self()->printNull(SS); 00478 return; 00479 } 00480 if (Sub && E->block() && E->opcode() != COP_Variable) { 00481 SS << "_x" << E->id(); 00482 return; 00483 } 00484 if (self()->precedence(E) > P) { 00485 // Wrap expr in () if necessary. 00486 SS << "("; 00487 self()->printSExpr(E, SS, Prec_MAX); 00488 SS << ")"; 00489 return; 00490 } 00491 00492 switch (E->opcode()) { 00493 #define TIL_OPCODE_DEF(X) \ 00494 case COP_##X: \ 00495 self()->print##X(cast<X>(E), SS); \ 00496 return; 00497 #include "ThreadSafetyOps.def" 00498 #undef TIL_OPCODE_DEF 00499 } 00500 } 00501 00502 void printNull(StreamType &SS) { 00503 SS << "#null"; 00504 } 00505 00506 void printFuture(const Future *E, StreamType &SS) { 00507 self()->printSExpr(E->maybeGetResult(), SS, Prec_Atom); 00508 } 00509 00510 void printUndefined(const Undefined *E, StreamType &SS) { 00511 SS << "#undefined"; 00512 } 00513 00514 void printWildcard(const Wildcard *E, StreamType &SS) { 00515 SS << "*"; 00516 } 00517 00518 template<class T> 00519 void printLiteralT(const LiteralT<T> *E, StreamType &SS) { 00520 SS << E->value(); 00521 } 00522 00523 void printLiteralT(const LiteralT<uint8_t> *E, StreamType &SS) { 00524 SS << "'" << E->value() << "'"; 00525 } 00526 00527 void printLiteral(const Literal *E, StreamType &SS) { 00528 if (E->clangExpr()) { 00529 SS << getSourceLiteralString(E->clangExpr()); 00530 return; 00531 } 00532 else { 00533 ValueType VT = E->valueType(); 00534 switch (VT.Base) { 00535 case ValueType::BT_Void: { 00536 SS << "void"; 00537 return; 00538 } 00539 case ValueType::BT_Bool: { 00540 if (E->as<bool>().value()) 00541 SS << "true"; 00542 else 00543 SS << "false"; 00544 return; 00545 } 00546 case ValueType::BT_Int: { 00547 switch (VT.Size) { 00548 case ValueType::ST_8: 00549 if (VT.Signed) 00550 printLiteralT(&E->as<int8_t>(), SS); 00551 else 00552 printLiteralT(&E->as<uint8_t>(), SS); 00553 return; 00554 case ValueType::ST_16: 00555 if (VT.Signed) 00556 printLiteralT(&E->as<int16_t>(), SS); 00557 else 00558 printLiteralT(&E->as<uint16_t>(), SS); 00559 return; 00560 case ValueType::ST_32: 00561 if (VT.Signed) 00562 printLiteralT(&E->as<int32_t>(), SS); 00563 else 00564 printLiteralT(&E->as<uint32_t>(), SS); 00565 return; 00566 case ValueType::ST_64: 00567 if (VT.Signed) 00568 printLiteralT(&E->as<int64_t>(), SS); 00569 else 00570 printLiteralT(&E->as<uint64_t>(), SS); 00571 return; 00572 default: 00573 break; 00574 } 00575 break; 00576 } 00577 case ValueType::BT_Float: { 00578 switch (VT.Size) { 00579 case ValueType::ST_32: 00580 printLiteralT(&E->as<float>(), SS); 00581 return; 00582 case ValueType::ST_64: 00583 printLiteralT(&E->as<double>(), SS); 00584 return; 00585 default: 00586 break; 00587 } 00588 break; 00589 } 00590 case ValueType::BT_String: { 00591 SS << "\""; 00592 printLiteralT(&E->as<StringRef>(), SS); 00593 SS << "\""; 00594 return; 00595 } 00596 case ValueType::BT_Pointer: { 00597 SS << "#ptr"; 00598 return; 00599 } 00600 case ValueType::BT_ValueRef: { 00601 SS << "#vref"; 00602 return; 00603 } 00604 } 00605 } 00606 SS << "#lit"; 00607 } 00608 00609 void printLiteralPtr(const LiteralPtr *E, StreamType &SS) { 00610 SS << E->clangDecl()->getNameAsString(); 00611 } 00612 00613 void printVariable(const Variable *V, StreamType &SS, bool IsVarDecl=false) { 00614 if (CStyle && V->kind() == Variable::VK_SFun) 00615 SS << "this"; 00616 else 00617 SS << V->name() << V->id(); 00618 } 00619 00620 void printFunction(const Function *E, StreamType &SS, unsigned sugared = 0) { 00621 switch (sugared) { 00622 default: 00623 SS << "\\("; // Lambda 00624 break; 00625 case 1: 00626 SS << "("; // Slot declarations 00627 break; 00628 case 2: 00629 SS << ", "; // Curried functions 00630 break; 00631 } 00632 self()->printVariable(E->variableDecl(), SS, true); 00633 SS << ": "; 00634 self()->printSExpr(E->variableDecl()->definition(), SS, Prec_MAX); 00635 00636 const SExpr *B = E->body(); 00637 if (B && B->opcode() == COP_Function) 00638 self()->printFunction(cast<Function>(B), SS, 2); 00639 else { 00640 SS << ")"; 00641 self()->printSExpr(B, SS, Prec_Decl); 00642 } 00643 } 00644 00645 void printSFunction(const SFunction *E, StreamType &SS) { 00646 SS << "@"; 00647 self()->printVariable(E->variableDecl(), SS, true); 00648 SS << " "; 00649 self()->printSExpr(E->body(), SS, Prec_Decl); 00650 } 00651 00652 void printCode(const Code *E, StreamType &SS) { 00653 SS << ": "; 00654 self()->printSExpr(E->returnType(), SS, Prec_Decl-1); 00655 SS << " -> "; 00656 self()->printSExpr(E->body(), SS, Prec_Decl); 00657 } 00658 00659 void printField(const Field *E, StreamType &SS) { 00660 SS << ": "; 00661 self()->printSExpr(E->range(), SS, Prec_Decl-1); 00662 SS << " = "; 00663 self()->printSExpr(E->body(), SS, Prec_Decl); 00664 } 00665 00666 void printApply(const Apply *E, StreamType &SS, bool sugared = false) { 00667 const SExpr *F = E->fun(); 00668 if (F->opcode() == COP_Apply) { 00669 printApply(cast<Apply>(F), SS, true); 00670 SS << ", "; 00671 } else { 00672 self()->printSExpr(F, SS, Prec_Postfix); 00673 SS << "("; 00674 } 00675 self()->printSExpr(E->arg(), SS, Prec_MAX); 00676 if (!sugared) 00677 SS << ")$"; 00678 } 00679 00680 void printSApply(const SApply *E, StreamType &SS) { 00681 self()->printSExpr(E->sfun(), SS, Prec_Postfix); 00682 if (E->isDelegation()) { 00683 SS << "@("; 00684 self()->printSExpr(E->arg(), SS, Prec_MAX); 00685 SS << ")"; 00686 } 00687 } 00688 00689 void printProject(const Project *E, StreamType &SS) { 00690 if (CStyle) { 00691 // Omit the this-> 00692 if (const SApply *SAP = dyn_cast<SApply>(E->record())) { 00693 if (const Variable *V = dyn_cast<Variable>(SAP->sfun())) { 00694 if (!SAP->isDelegation() && V->kind() == Variable::VK_SFun) { 00695 SS << E->slotName(); 00696 return; 00697 } 00698 } 00699 } 00700 if (isa<Wildcard>(E->record())) { 00701 // handle existentials 00702 SS << "&"; 00703 SS << E->clangDecl()->getQualifiedNameAsString(); 00704 return; 00705 } 00706 } 00707 self()->printSExpr(E->record(), SS, Prec_Postfix); 00708 if (CStyle && E->isArrow()) { 00709 SS << "->"; 00710 } 00711 else { 00712 SS << "."; 00713 } 00714 SS << E->slotName(); 00715 } 00716 00717 void printCall(const Call *E, StreamType &SS) { 00718 const SExpr *T = E->target(); 00719 if (T->opcode() == COP_Apply) { 00720 self()->printApply(cast<Apply>(T), SS, true); 00721 SS << ")"; 00722 } 00723 else { 00724 self()->printSExpr(T, SS, Prec_Postfix); 00725 SS << "()"; 00726 } 00727 } 00728 00729 void printAlloc(const Alloc *E, StreamType &SS) { 00730 SS << "new "; 00731 self()->printSExpr(E->dataType(), SS, Prec_Other-1); 00732 } 00733 00734 void printLoad(const Load *E, StreamType &SS) { 00735 self()->printSExpr(E->pointer(), SS, Prec_Postfix); 00736 if (!CStyle) 00737 SS << "^"; 00738 } 00739 00740 void printStore(const Store *E, StreamType &SS) { 00741 self()->printSExpr(E->destination(), SS, Prec_Other-1); 00742 SS << " := "; 00743 self()->printSExpr(E->source(), SS, Prec_Other-1); 00744 } 00745 00746 void printArrayIndex(const ArrayIndex *E, StreamType &SS) { 00747 self()->printSExpr(E->array(), SS, Prec_Postfix); 00748 SS << "["; 00749 self()->printSExpr(E->index(), SS, Prec_MAX); 00750 SS << "]"; 00751 } 00752 00753 void printArrayAdd(const ArrayAdd *E, StreamType &SS) { 00754 self()->printSExpr(E->array(), SS, Prec_Postfix); 00755 SS << " + "; 00756 self()->printSExpr(E->index(), SS, Prec_Atom); 00757 } 00758 00759 void printUnaryOp(const UnaryOp *E, StreamType &SS) { 00760 SS << getUnaryOpcodeString(E->unaryOpcode()); 00761 self()->printSExpr(E->expr(), SS, Prec_Unary); 00762 } 00763 00764 void printBinaryOp(const BinaryOp *E, StreamType &SS) { 00765 self()->printSExpr(E->expr0(), SS, Prec_Binary-1); 00766 SS << " " << getBinaryOpcodeString(E->binaryOpcode()) << " "; 00767 self()->printSExpr(E->expr1(), SS, Prec_Binary-1); 00768 } 00769 00770 void printCast(const Cast *E, StreamType &SS) { 00771 if (!CStyle) { 00772 SS << "cast["; 00773 SS << E->castOpcode(); 00774 SS << "]("; 00775 self()->printSExpr(E->expr(), SS, Prec_Unary); 00776 SS << ")"; 00777 return; 00778 } 00779 self()->printSExpr(E->expr(), SS, Prec_Unary); 00780 } 00781 00782 void printSCFG(const SCFG *E, StreamType &SS) { 00783 SS << "CFG {\n"; 00784 for (auto BBI : *E) { 00785 printBasicBlock(BBI, SS); 00786 } 00787 SS << "}"; 00788 newline(SS); 00789 } 00790 00791 00792 void printBBInstr(const SExpr *E, StreamType &SS) { 00793 bool Sub = false; 00794 if (E->opcode() == COP_Variable) { 00795 auto *V = cast<Variable>(E); 00796 SS << "let " << V->name() << V->id() << " = "; 00797 E = V->definition(); 00798 Sub = true; 00799 } 00800 else if (E->opcode() != COP_Store) { 00801 SS << "let _x" << E->id() << " = "; 00802 } 00803 self()->printSExpr(E, SS, Prec_MAX, Sub); 00804 SS << ";"; 00805 newline(SS); 00806 } 00807 00808 void printBasicBlock(const BasicBlock *E, StreamType &SS) { 00809 SS << "BB_" << E->blockID() << ":"; 00810 if (E->parent()) 00811 SS << " BB_" << E->parent()->blockID(); 00812 newline(SS); 00813 00814 for (auto *A : E->arguments()) 00815 printBBInstr(A, SS); 00816 00817 for (auto *I : E->instructions()) 00818 printBBInstr(I, SS); 00819 00820 const SExpr *T = E->terminator(); 00821 if (T) { 00822 self()->printSExpr(T, SS, Prec_MAX, false); 00823 SS << ";"; 00824 newline(SS); 00825 } 00826 newline(SS); 00827 } 00828 00829 void printPhi(const Phi *E, StreamType &SS) { 00830 SS << "phi("; 00831 if (E->status() == Phi::PH_SingleVal) 00832 self()->printSExpr(E->values()[0], SS, Prec_MAX); 00833 else { 00834 unsigned i = 0; 00835 for (auto V : E->values()) { 00836 if (i++ > 0) 00837 SS << ", "; 00838 self()->printSExpr(V, SS, Prec_MAX); 00839 } 00840 } 00841 SS << ")"; 00842 } 00843 00844 void printGoto(const Goto *E, StreamType &SS) { 00845 SS << "goto "; 00846 printBlockLabel(SS, E->targetBlock(), E->index()); 00847 } 00848 00849 void printBranch(const Branch *E, StreamType &SS) { 00850 SS << "branch ("; 00851 self()->printSExpr(E->condition(), SS, Prec_MAX); 00852 SS << ") "; 00853 printBlockLabel(SS, E->thenBlock(), -1); 00854 SS << " "; 00855 printBlockLabel(SS, E->elseBlock(), -1); 00856 } 00857 00858 void printReturn(const Return *E, StreamType &SS) { 00859 SS << "return "; 00860 self()->printSExpr(E->returnValue(), SS, Prec_Other); 00861 } 00862 00863 void printIdentifier(const Identifier *E, StreamType &SS) { 00864 SS << E->name(); 00865 } 00866 00867 void printIfThenElse(const IfThenElse *E, StreamType &SS) { 00868 if (CStyle) { 00869 printSExpr(E->condition(), SS, Prec_Unary); 00870 SS << " ? "; 00871 printSExpr(E->thenExpr(), SS, Prec_Unary); 00872 SS << " : "; 00873 printSExpr(E->elseExpr(), SS, Prec_Unary); 00874 return; 00875 } 00876 SS << "if ("; 00877 printSExpr(E->condition(), SS, Prec_MAX); 00878 SS << ") then "; 00879 printSExpr(E->thenExpr(), SS, Prec_Other); 00880 SS << " else "; 00881 printSExpr(E->elseExpr(), SS, Prec_Other); 00882 } 00883 00884 void printLet(const Let *E, StreamType &SS) { 00885 SS << "let "; 00886 printVariable(E->variableDecl(), SS, true); 00887 SS << " = "; 00888 printSExpr(E->variableDecl()->definition(), SS, Prec_Decl-1); 00889 SS << "; "; 00890 printSExpr(E->body(), SS, Prec_Decl-1); 00891 } 00892 }; 00893 00894 00895 class StdPrinter : public PrettyPrinter<StdPrinter, std::ostream> { }; 00896 00897 00898 00899 } // end namespace til 00900 } // end namespace threadSafety 00901 } // end namespace clang 00902 00903 #endif // LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H