1 //===- ThreadSafetyTraverse.h ----------------------------------*- C++ --*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines a framework for doing generic traversals and rewriting 11 // operations over the Thread Safety TIL. 12 // 13 // UNDER CONSTRUCTION. USE AT YOUR OWN RISK. 14 // 15 //===----------------------------------------------------------------------===// 16 17 #ifndef LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H 18 #define LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H 19 20 #include "ThreadSafetyTIL.h" 21 22 namespace clang { 23 namespace threadSafety { 24 namespace til { 25 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. 30 // 31 // Traversals implement the functional notion of a "fold" operation on SExprs. 32 // Each SExpr class provides a traverse method, which does the following: 33 // * e->traverse(v): 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). 38 // 39 // A visitor can control the traversal by overriding the following methods: 40 // * v.traverse(e): 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 46 // 47 // The reduceX methods control the kind of traversal (visitor, copy, etc.). 48 // They are defined in derived classes. 49 // 50 // Class R defines the basic interface types (R_SExpr). 51 template <class Self, class R> 52 class Traversal { 53 public: 54 Self *self() { return static_cast<Self *>(this); } 55 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); 61 } 62 63 typename R::R_SExpr traverse(SExpr *E, typename R::R_Ctx Ctx) { 64 return traverseByCase(E, Ctx); 65 } 66 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) \ 71 case COP_##X: \ 72 return self()->traverse##X(cast<X>(E), Ctx); 73 #include "ThreadSafetyOps.def" 74 #undef TIL_OPCODE_DEF 75 } 76 } 77 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); \ 83 } 84 #include "ThreadSafetyOps.def" 85 #undef TIL_OPCODE_DEF 86 }; 87 88 89 // Base class for simple reducers that don't much care about the context. 90 class SimpleReducerBase { 91 public: 92 enum TraversalKind { 93 TRV_Normal, 94 TRV_Decl, 95 TRV_Lazy, 96 TRV_Type 97 }; 98 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; 103 104 // Create context for an ordinary subexpression. 105 R_Ctx subExprCtx(R_Ctx Ctx) { return TRV_Normal; } 106 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; } 110 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; } 114 115 // Create context for a subexpression that occurs in a type position. 116 R_Ctx typeCtx(R_Ctx Ctx) { return TRV_Type; } 117 }; 118 119 120 // Base class for traversals that rewrite an SExpr to another SExpr. 121 class CopyReducerBase : public SimpleReducerBase { 122 public: 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; 127 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 { 131 public: 132 // Allocate a new container with a capacity for n elements. 133 Container(CopyReducerBase &S, unsigned N) : Elems(S.Arena, N) {} 134 135 // Push a new element onto the container. 136 void push_back(T E) { Elems.push_back(E); } 137 138 SimpleArray<T> Elems; 139 }; 140 141 CopyReducerBase(MemRegionRef A) : Arena(A) {} 142 143 protected: 144 MemRegionRef Arena; 145 }; 146 147 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 151 // passes. 152 template<class Self> 153 class CopyReducer : public Traversal<Self, CopyReducerBase>, 154 public CopyReducerBase { 155 public: 156 CopyReducer(MemRegionRef A) : CopyReducerBase(A) {} 157 158 public: 159 R_SExpr reduceNull() { 160 return nullptr; 161 } 162 // R_SExpr reduceFuture(...) is never used. 163 164 R_SExpr reduceUndefined(Undefined &Orig) { 165 return new (Arena) Undefined(Orig); 166 } 167 R_SExpr reduceWildcard(Wildcard &Orig) { 168 return new (Arena) Wildcard(Orig); 169 } 170 171 R_SExpr reduceLiteral(Literal &Orig) { 172 return new (Arena) Literal(Orig); 173 } 174 template<class T> 175 R_SExpr reduceLiteralT(LiteralT<T> &Orig) { 176 return new (Arena) LiteralT<T>(Orig); 177 } 178 R_SExpr reduceLiteralPtr(LiteralPtr &Orig) { 179 return new (Arena) LiteralPtr(Orig); 180 } 181 182 R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) { 183 return new (Arena) Function(Orig, Nvd, E0); 184 } 185 R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) { 186 return new (Arena) SFunction(Orig, Nvd, E0); 187 } 188 R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) { 189 return new (Arena) Code(Orig, E0, E1); 190 } 191 R_SExpr reduceField(Field &Orig, R_SExpr E0, R_SExpr E1) { 192 return new (Arena) Field(Orig, E0, E1); 193 } 194 195 R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) { 196 return new (Arena) Apply(Orig, E0, E1); 197 } 198 R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) { 199 return new (Arena) SApply(Orig, E0, E1); 200 } 201 R_SExpr reduceProject(Project &Orig, R_SExpr E0) { 202 return new (Arena) Project(Orig, E0); 203 } 204 R_SExpr reduceCall(Call &Orig, R_SExpr E0) { 205 return new (Arena) Call(Orig, E0); 206 } 207 208 R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) { 209 return new (Arena) Alloc(Orig, E0); 210 } 211 R_SExpr reduceLoad(Load &Orig, R_SExpr E0) { 212 return new (Arena) Load(Orig, E0); 213 } 214 R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) { 215 return new (Arena) Store(Orig, E0, E1); 216 } 217 R_SExpr reduceArrayIndex(ArrayIndex &Orig, R_SExpr E0, R_SExpr E1) { 218 return new (Arena) ArrayIndex(Orig, E0, E1); 219 } 220 R_SExpr reduceArrayAdd(ArrayAdd &Orig, R_SExpr E0, R_SExpr E1) { 221 return new (Arena) ArrayAdd(Orig, E0, E1); 222 } 223 R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) { 224 return new (Arena) UnaryOp(Orig, E0); 225 } 226 R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) { 227 return new (Arena) BinaryOp(Orig, E0, E1); 228 } 229 R_SExpr reduceCast(Cast &Orig, R_SExpr E0) { 230 return new (Arena) Cast(Orig, E0); 231 } 232 233 R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> &Bbs) { 234 return nullptr; // FIXME: implement CFG rewriting 235 } 236 R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container<Variable *> &As, 237 Container<Variable *> &Is, R_SExpr T) { 238 return nullptr; // FIXME: implement CFG rewriting 239 } 240 R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) { 241 return new (Arena) Phi(Orig, std::move(As.Elems)); 242 } 243 R_SExpr reduceGoto(Goto &Orig, BasicBlock *B) { 244 return new (Arena) Goto(Orig, B, 0); // FIXME: set index 245 } 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 248 } 249 250 R_SExpr reduceIdentifier(Identifier &Orig) { 251 return new (Arena) Identifier(Orig); 252 } 253 R_SExpr reduceIfThenElse(IfThenElse &Orig, R_SExpr C, R_SExpr T, R_SExpr E) { 254 return new (Arena) IfThenElse(Orig, C, T, E); 255 } 256 R_SExpr reduceLet(Let &Orig, Variable *Nvd, R_SExpr B) { 257 return new (Arena) Let(Orig, Nvd, B); 258 } 259 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); 263 } 264 // Exit the lexical scope of orig. 265 void exitScope(const Variable &Orig) {} 266 267 void enterCFG(SCFG &Cfg) {} 268 void exitCFG(SCFG &Cfg) {} 269 void enterBasicBlock(BasicBlock &BB) {} 270 void exitBasicBlock(BasicBlock &BB) {} 271 272 // Map Variable references to their rewritten definitions. 273 Variable *reduceVariableRef(Variable *Ovd) { return Ovd; } 274 275 // Map BasicBlock references to their rewritten definitions. 276 BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; } 277 }; 278 279 280 class SExprCopier : public CopyReducer<SExprCopier> { 281 public: 282 typedef SExpr *R_SExpr; 283 284 SExprCopier(MemRegionRef A) : CopyReducer(A) { } 285 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); 290 } 291 }; 292 293 294 295 // Base class for visit traversals. 296 class VisitReducerBase : public SimpleReducerBase { 297 public: 298 // A visitor returns a bool, representing success or failure. 299 typedef bool R_SExpr; 300 typedef bool R_BasicBlock; 301 302 // A visitor "container" is a single bool, which accumulates success. 303 template <class T> class Container { 304 public: 305 Container(VisitReducerBase &S, unsigned N) : Success(true) {} 306 void push_back(bool E) { Success = Success && E; } 307 308 bool Success; 309 }; 310 }; 311 312 313 // Implements a traversal that visits each subexpression, and returns either 314 // true or false. 315 template <class Self> 316 class VisitReducer : public Traversal<Self, VisitReducerBase>, 317 public VisitReducerBase { 318 public: 319 VisitReducer() {} 320 321 public: 322 R_SExpr reduceNull() { return true; } 323 R_SExpr reduceUndefined(Undefined &Orig) { return true; } 324 R_SExpr reduceWildcard(Wildcard &Orig) { return true; } 325 326 R_SExpr reduceLiteral(Literal &Orig) { return true; } 327 template<class T> 328 R_SExpr reduceLiteralT(LiteralT<T> &Orig) { return true; } 329 R_SExpr reduceLiteralPtr(Literal &Orig) { return true; } 330 331 R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) { 332 return Nvd && E0; 333 } 334 R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) { 335 return Nvd && E0; 336 } 337 R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) { 338 return E0 && E1; 339 } 340 R_SExpr reduceField(Field &Orig, R_SExpr E0, R_SExpr E1) { 341 return E0 && E1; 342 } 343 R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) { 344 return E0 && E1; 345 } 346 R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) { 347 return E0 && E1; 348 } 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) { 355 return E0 && E1; 356 } 357 R_SExpr reduceArrayAdd(Store &Orig, R_SExpr E0, R_SExpr E1) { 358 return E0 && E1; 359 } 360 R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) { return E0; } 361 R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) { 362 return E0 && E1; 363 } 364 R_SExpr reduceCast(Cast &Orig, R_SExpr E0) { return E0; } 365 366 R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> Bbs) { 367 return Bbs.Success; 368 } 369 R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container<Variable *> &As, 370 Container<Variable *> &Is, R_SExpr T) { 371 return (As.Success && Is.Success && T); 372 } 373 R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) { 374 return As.Success; 375 } 376 R_SExpr reduceGoto(Goto &Orig, BasicBlock *B) { 377 return true; 378 } 379 R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) { 380 return C; 381 } 382 383 R_SExpr reduceIdentifier(Identifier &Orig) { 384 return true; 385 } 386 R_SExpr reduceIfThenElse(IfThenElse &Orig, R_SExpr C, R_SExpr T, R_SExpr E) { 387 return C && T && E; 388 } 389 R_SExpr reduceLet(Let &Orig, Variable *Nvd, R_SExpr B) { 390 return Nvd && B; 391 } 392 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) {} 399 400 Variable *reduceVariableRef (Variable *Ovd) { return Ovd; } 401 BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; } 402 403 public: 404 bool traverse(SExpr *E, TraversalKind K = TRV_Normal) { 405 Success = Success && this->traverseByCase(E); 406 return Success; 407 } 408 409 static bool visit(SExpr *E) { 410 Self Visitor; 411 return Visitor.traverse(E, TRV_Normal); 412 } 413 414 private: 415 bool Success; 416 }; 417 418 419 // Basic class for comparison operations over expressions. 420 template <typename Self> 421 class Comparator { 422 protected: 423 Self *self() { return reinterpret_cast<Self *>(this); } 424 425 public: 426 bool compareByCase(SExpr *E1, SExpr* E2) { 427 switch (E1->opcode()) { 428 #define TIL_OPCODE_DEF(X) \ 429 case COP_##X: \ 430 return cast<X>(E1)->compare(cast<X>(E2), *self()); 431 #include "ThreadSafetyOps.def" 432 #undef TIL_OPCODE_DEF 433 } 434 } 435 }; 436 437 438 class EqualsComparator : public Comparator<EqualsComparator> { 439 public: 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 442 // denotes "true". 443 typedef bool CType; 444 445 CType trueResult() { return true; } 446 bool notTrue(CType ct) { return !ct; } 447 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; } 451 452 bool compare(SExpr *E1, SExpr* E2) { 453 if (E1->opcode() != E2->opcode()) 454 return false; 455 return compareByCase(E1, E2); 456 } 457 458 // TODO -- handle alpha-renaming of variables 459 void enterScope(Variable* V1, Variable* V2) { } 460 void leaveScope() { } 461 462 bool compareVariableRefs(Variable* V1, Variable* V2) { 463 return V1 == V2; 464 } 465 466 static bool compareExprs(SExpr *E1, SExpr* E2) { 467 EqualsComparator Eq; 468 return Eq.compare(E1, E2); 469 } 470 }; 471 472 473 // Pretty printer for TIL expressions 474 template <typename Self, typename StreamType> 475 class PrettyPrinter { 476 private: 477 bool Verbose; // Print out additional information 478 bool Cleanup; // Omit redundant decls. 479 480 public: 481 PrettyPrinter(bool V = false, bool C = true) : Verbose(V), Cleanup(C) { } 482 483 static void print(SExpr *E, StreamType &SS) { 484 Self printer; 485 printer.printSExpr(E, SS, Prec_MAX); 486 } 487 488 protected: 489 Self *self() { return reinterpret_cast<Self *>(this); } 490 491 void newline(StreamType &SS) { 492 SS << "\n"; 493 } 494 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; 503 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; 510 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; 518 519 case COP_Apply: return Prec_Postfix; 520 case COP_SApply: return Prec_Postfix; 521 case COP_Project: return Prec_Postfix; 522 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; 529 530 case COP_UnaryOp: return Prec_Unary; 531 case COP_BinaryOp: return Prec_Binary; 532 case COP_Cast: return Prec_Unary; 533 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; 539 540 case COP_Identifier: return Prec_Atom; 541 case COP_IfThenElse: return Prec_Other; 542 case COP_Let: return Prec_Decl; 543 } 544 return Prec_MAX; 545 } 546 547 void printBlockLabel(StreamType & SS, BasicBlock *BB, unsigned index) { 548 if (!BB) { 549 SS << "BB_null"; 550 return; 551 } 552 SS << "BB_"; 553 SS << BB->blockID(); 554 SS << ":"; 555 SS << index; 556 } 557 558 void printSExpr(SExpr *E, StreamType &SS, unsigned P) { 559 if (!E) { 560 self()->printNull(SS); 561 return; 562 } 563 if (self()->precedence(E) > P) { 564 // Wrap expr in () if necessary. 565 SS << "("; 566 self()->printSExpr(E, SS, Prec_MAX); 567 SS << ")"; 568 return; 569 } 570 571 switch (E->opcode()) { 572 #define TIL_OPCODE_DEF(X) \ 573 case COP_##X: \ 574 self()->print##X(cast<X>(E), SS); \ 575 return; 576 #include "ThreadSafetyOps.def" 577 #undef TIL_OPCODE_DEF 578 } 579 } 580 581 void printNull(StreamType &SS) { 582 SS << "#null"; 583 } 584 585 void printFuture(Future *E, StreamType &SS) { 586 self()->printSExpr(E->maybeGetResult(), SS, Prec_Atom); 587 } 588 589 void printUndefined(Undefined *E, StreamType &SS) { 590 SS << "#undefined"; 591 } 592 593 void printWildcard(Wildcard *E, StreamType &SS) { 594 SS << "_"; 595 } 596 597 template<class T> 598 void printLiteralT(LiteralT<T> *E, StreamType &SS) { 599 SS << E->value(); 600 } 601 602 void printLiteralT(LiteralT<uint8_t> *E, StreamType &SS) { 603 SS << "'" << E->value() << "'"; 604 } 605 606 void printLiteral(Literal *E, StreamType &SS) { 607 if (E->clangExpr()) { 608 SS << getSourceLiteralString(E->clangExpr()); 609 return; 610 } 611 else { 612 ValueType VT = E->valueType(); 613 switch (VT.Base) { 614 case ValueType::BT_Void: { 615 SS << "void"; 616 return; 617 } 618 case ValueType::BT_Bool: { 619 if (E->as<bool>().value()) 620 SS << "true"; 621 else 622 SS << "false"; 623 return; 624 } 625 case ValueType::BT_Int: { 626 switch (VT.Size) { 627 case ValueType::ST_8: 628 if (VT.Signed) 629 printLiteralT(&E->as<int8_t>(), SS); 630 else 631 printLiteralT(&E->as<uint8_t>(), SS); 632 return; 633 case ValueType::ST_16: 634 if (VT.Signed) 635 printLiteralT(&E->as<int16_t>(), SS); 636 else 637 printLiteralT(&E->as<uint16_t>(), SS); 638 return; 639 case ValueType::ST_32: 640 if (VT.Signed) 641 printLiteralT(&E->as<int32_t>(), SS); 642 else 643 printLiteralT(&E->as<uint32_t>(), SS); 644 return; 645 case ValueType::ST_64: 646 if (VT.Signed) 647 printLiteralT(&E->as<int64_t>(), SS); 648 else 649 printLiteralT(&E->as<uint64_t>(), SS); 650 return; 651 default: 652 break; 653 } 654 break; 655 } 656 case ValueType::BT_Float: { 657 switch (VT.Size) { 658 case ValueType::ST_32: 659 printLiteralT(&E->as<float>(), SS); 660 return; 661 case ValueType::ST_64: 662 printLiteralT(&E->as<double>(), SS); 663 return; 664 default: 665 break; 666 } 667 break; 668 } 669 case ValueType::BT_String: { 670 SS << "\""; 671 printLiteralT(&E->as<StringRef>(), SS); 672 SS << "\""; 673 return; 674 } 675 case ValueType::BT_Pointer: { 676 SS << "#ptr"; 677 return; 678 } 679 case ValueType::BT_ValueRef: { 680 SS << "#vref"; 681 return; 682 } 683 } 684 } 685 SS << "#lit"; 686 } 687 688 void printLiteralPtr(LiteralPtr *E, StreamType &SS) { 689 SS << E->clangDecl()->getNameAsString(); 690 } 691 692 void printVariable(Variable *V, StreamType &SS, bool IsVarDecl = false) { 693 if (!IsVarDecl && Cleanup) { 694 SExpr* E = getCanonicalVal(V); 695 if (E != V) { 696 printSExpr(E, SS, Prec_Atom); 697 return; 698 } 699 } 700 if (V->kind() == Variable::VK_LetBB) 701 SS << V->name() << V->getBlockID() << "_" << V->getID(); 702 else 703 SS << V->name() << V->getID(); 704 } 705 706 void printFunction(Function *E, StreamType &SS, unsigned sugared = 0) { 707 switch (sugared) { 708 default: 709 SS << "\\("; // Lambda 710 break; 711 case 1: 712 SS << "("; // Slot declarations 713 break; 714 case 2: 715 SS << ", "; // Curried functions 716 break; 717 } 718 self()->printVariable(E->variableDecl(), SS, true); 719 SS << ": "; 720 self()->printSExpr(E->variableDecl()->definition(), SS, Prec_MAX); 721 722 SExpr *B = E->body(); 723 if (B && B->opcode() == COP_Function) 724 self()->printFunction(cast<Function>(B), SS, 2); 725 else { 726 SS << ")"; 727 self()->printSExpr(B, SS, Prec_Decl); 728 } 729 } 730 731 void printSFunction(SFunction *E, StreamType &SS) { 732 SS << "@"; 733 self()->printVariable(E->variableDecl(), SS, true); 734 SS << " "; 735 self()->printSExpr(E->body(), SS, Prec_Decl); 736 } 737 738 void printCode(Code *E, StreamType &SS) { 739 SS << ": "; 740 self()->printSExpr(E->returnType(), SS, Prec_Decl-1); 741 SS << " -> "; 742 self()->printSExpr(E->body(), SS, Prec_Decl); 743 } 744 745 void printField(Field *E, StreamType &SS) { 746 SS << ": "; 747 self()->printSExpr(E->range(), SS, Prec_Decl-1); 748 SS << " = "; 749 self()->printSExpr(E->body(), SS, Prec_Decl); 750 } 751 752 void printApply(Apply *E, StreamType &SS, bool sugared = false) { 753 SExpr *F = E->fun(); 754 if (F->opcode() == COP_Apply) { 755 printApply(cast<Apply>(F), SS, true); 756 SS << ", "; 757 } else { 758 self()->printSExpr(F, SS, Prec_Postfix); 759 SS << "("; 760 } 761 self()->printSExpr(E->arg(), SS, Prec_MAX); 762 if (!sugared) 763 SS << ")$"; 764 } 765 766 void printSApply(SApply *E, StreamType &SS) { 767 self()->printSExpr(E->sfun(), SS, Prec_Postfix); 768 if (E->isDelegation()) { 769 SS << "@("; 770 self()->printSExpr(E->arg(), SS, Prec_MAX); 771 SS << ")"; 772 } 773 } 774 775 void printProject(Project *E, StreamType &SS) { 776 self()->printSExpr(E->record(), SS, Prec_Postfix); 777 SS << "."; 778 SS << E->slotName(); 779 } 780 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); 785 SS << ")"; 786 } 787 else { 788 self()->printSExpr(T, SS, Prec_Postfix); 789 SS << "()"; 790 } 791 } 792 793 void printAlloc(Alloc *E, StreamType &SS) { 794 SS << "new "; 795 self()->printSExpr(E->dataType(), SS, Prec_Other-1); 796 } 797 798 void printLoad(Load *E, StreamType &SS) { 799 self()->printSExpr(E->pointer(), SS, Prec_Postfix); 800 SS << "^"; 801 } 802 803 void printStore(Store *E, StreamType &SS) { 804 self()->printSExpr(E->destination(), SS, Prec_Other-1); 805 SS << " := "; 806 self()->printSExpr(E->source(), SS, Prec_Other-1); 807 } 808 809 void printArrayIndex(ArrayIndex *E, StreamType &SS) { 810 self()->printSExpr(E->array(), SS, Prec_Postfix); 811 SS << "["; 812 self()->printSExpr(E->index(), SS, Prec_MAX); 813 SS << "]"; 814 } 815 816 void printArrayAdd(ArrayAdd *E, StreamType &SS) { 817 self()->printSExpr(E->array(), SS, Prec_Postfix); 818 SS << " + "; 819 self()->printSExpr(E->index(), SS, Prec_Atom); 820 } 821 822 void printUnaryOp(UnaryOp *E, StreamType &SS) { 823 SS << getUnaryOpcodeString(E->unaryOpcode()); 824 self()->printSExpr(E->expr(), SS, Prec_Unary); 825 } 826 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); 831 } 832 833 void printCast(Cast *E, StreamType &SS) { 834 SS << "%"; 835 self()->printSExpr(E->expr(), SS, Prec_Unary); 836 } 837 838 void printSCFG(SCFG *E, StreamType &SS) { 839 SS << "CFG {\n"; 840 for (auto BBI : *E) { 841 printBasicBlock(BBI, SS); 842 } 843 SS << "}"; 844 newline(SS); 845 } 846 847 void printBasicBlock(BasicBlock *E, StreamType &SS) { 848 SS << "BB_" << E->blockID() << ":"; 849 if (E->parent()) 850 SS << " BB_" << E->parent()->blockID(); 851 newline(SS); 852 for (auto *A : E->arguments()) { 853 SS << "let "; 854 self()->printVariable(A, SS, true); 855 SS << " = "; 856 self()->printSExpr(A->definition(), SS, Prec_MAX); 857 SS << ";"; 858 newline(SS); 859 } 860 for (auto *I : E->instructions()) { 861 if (I->definition()->opcode() != COP_Store) { 862 SS << "let "; 863 self()->printVariable(I, SS, true); 864 SS << " = "; 865 } 866 self()->printSExpr(I->definition(), SS, Prec_MAX); 867 SS << ";"; 868 newline(SS); 869 } 870 SExpr *T = E->terminator(); 871 if (T) { 872 self()->printSExpr(T, SS, Prec_MAX); 873 SS << ";"; 874 newline(SS); 875 } 876 newline(SS); 877 } 878 879 void printPhi(Phi *E, StreamType &SS) { 880 SS << "phi("; 881 if (E->status() == Phi::PH_SingleVal) 882 self()->printSExpr(E->values()[0], SS, Prec_MAX); 883 else { 884 unsigned i = 0; 885 for (auto V : E->values()) { 886 if (i++ > 0) 887 SS << ", "; 888 self()->printSExpr(V, SS, Prec_MAX); 889 } 890 } 891 SS << ")"; 892 } 893 894 void printGoto(Goto *E, StreamType &SS) { 895 SS << "goto "; 896 printBlockLabel(SS, E->targetBlock(), E->index()); 897 } 898 899 void printBranch(Branch *E, StreamType &SS) { 900 SS << "branch ("; 901 self()->printSExpr(E->condition(), SS, Prec_MAX); 902 SS << ") "; 903 printBlockLabel(SS, E->thenBlock(), E->thenIndex()); 904 SS << " "; 905 printBlockLabel(SS, E->elseBlock(), E->elseIndex()); 906 } 907 908 void printIdentifier(Identifier *E, StreamType &SS) { 909 SS << E->name(); 910 } 911 912 void printIfThenElse(IfThenElse *E, StreamType &SS) { 913 SS << "if ("; 914 printSExpr(E->condition(), SS, Prec_MAX); 915 SS << ") then "; 916 printSExpr(E->thenExpr(), SS, Prec_Other); 917 SS << " else "; 918 printSExpr(E->elseExpr(), SS, Prec_Other); 919 } 920 921 void printLet(Let *E, StreamType &SS) { 922 SS << "let "; 923 printVariable(E->variableDecl(), SS, true); 924 SS << " = "; 925 printSExpr(E->variableDecl()->definition(), SS, Prec_Decl-1); 926 SS << "; "; 927 printSExpr(E->body(), SS, Prec_Decl-1); 928 } 929 }; 930 931 932 } // end namespace til 933 } // end namespace threadSafety 934 } // end namespace clang 935 936 #endif // LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H 937