clang: include/clang/Analysis/Analyses/ThreadSafetyTraverse.h Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H
17#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H
18
23#include "llvm/ADT/StringRef.h"
24#include "llvm/Support/Casting.h"
25#include
26#include
27
29namespace threadSafety {
30namespace til {
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57template <class Self, class R>
59public:
61
62
63
64
65
66
67 template
68 typename R::R_SExpr traverse(T* &E, typename R::R_Ctx Ctx) {
70 }
71
72
73
76 }
77
78
80 switch (E->opcode()) {
81#define TIL_OPCODE_DEF(X) \
82 case COP_##X: \
83 return self()->traverse##X(cast(E), Ctx);
84#include "ThreadSafetyOps.def"
85#undef TIL_OPCODE_DEF
86 }
87 return self()->reduceNull();
88 }
89
90
91
92#define TIL_OPCODE_DEF(X) \
93 typename R::R_SExpr traverse##X(X *e, typename R::R_Ctx Ctx) { \
94 return e->traverse(*self(), Ctx); \
95 }
96#include "ThreadSafetyOps.def"
97#undef TIL_OPCODE_DEF
98};
99
100
102public:
104
106
107
109
110
112
113
116
117
118
119
121
122
124
125
126
128
129
130
132
133
135};
136
137
139public:
140
141
144
145
146
148 public:
149
151
152
154
156 };
157
159
160protected:
162};
163
164
166public:
167
170
171
173 public:
175
177
179 };
180};
181
182
183
184template
187public:
189
190public:
194
196 template
199
201 return Nvd && E0;
202 }
203
205 return Nvd && E0;
206 }
207
209 return E0 && E1;
210 }
211
213 return E0 && E1;
214 }
215
217 return E0 && E1;
218 }
219
221 return E0 && E1;
222 }
223
229
231 return E0 && E1;
232 }
233
235 return E0 && E1;
236 }
237
239
241 return E0 && E1;
242 }
243
245
248 }
249
253 }
254
257 }
258
260 return true;
261 }
262
264 return C;
265 }
266
268 return E;
269 }
270
272 return true;
273 }
274
277 }
278
280 return Nvd && B;
281 }
282
289
292
293public:
296 return Success;
297 }
298
300 Self Visitor;
302 }
303
304private:
305 bool Success;
306};
307
308
309template
311protected:
313
314public:
316 switch (E1->opcode()) {
317#define TIL_OPCODE_DEF(X) \
318 case COP_##X: \
319 return cast(E1)->compare(cast(E2), *self());
320#include "ThreadSafetyOps.def"
321#undef TIL_OPCODE_DEF
322 }
323 return false;
324 }
325};
326
328public:
329
330
331
333
336
340
343 return false;
345 }
346
347
350
352 return V1 == V2;
353 }
354
357 return Eq.compare(E1, E2);
358 }
359};
360
362public:
363
364
365
367
370
374
376
377 if (E1->opcode() == COP_Wildcard || E2->opcode() == COP_Wildcard)
378 return true;
379
381 return false;
383 }
384
385
388
390 return V1 == V2;
391 }
392
395 return Matcher.compare(E1, E2);
396 }
397};
398
399
400
401
402
403
404template <typename Self, typename StreamType>
406private:
407
408 bool Verbose;
409
410
411 bool Cleanup;
412
413
414 bool CStyle;
415
416public:
418 : Verbose(V), Cleanup(C), CStyle(CS) {}
419
421 Self printer;
422 printer.printSExpr(E, SS, Prec_MAX);
423 }
424
425protected:
427
429 SS << "\n";
430 }
431
432
440
441
443 switch (E->opcode()) {
444 case COP_Future: return Prec_Atom;
445 case COP_Undefined: return Prec_Atom;
446 case COP_Wildcard: return Prec_Atom;
447
448 case COP_Literal: return Prec_Atom;
449 case COP_LiteralPtr: return Prec_Atom;
450 case COP_Variable: return Prec_Atom;
451 case COP_Function: return Prec_Decl;
452 case COP_SFunction: return Prec_Decl;
454 case COP_Field: return Prec_Decl;
455
459
466
470
472 case COP_BasicBlock: return Prec_MAX;
475 case COP_Branch: return Prec_Atom;
477
478 case COP_Identifier: return Prec_Atom;
479 case COP_IfThenElse: return Prec_Other;
481 }
483 }
484
486 if (!BB) {
487 SS << "BB_null";
488 return;
489 }
490 SS << "BB_";
492 if (index >= 0) {
493 SS << ":";
494 SS << index;
495 }
496 }
497
499 if () {
500 self()->printNull(SS);
501 return;
502 }
503 if (Sub && E->block() && E->opcode() != COP_Variable) {
504 SS << "_x" << E->id();
505 return;
506 }
508
509 SS << "(";
511 SS << ")";
512 return;
513 }
514
515 switch (E->opcode()) {
516#define TIL_OPCODE_DEF(X) \
517 case COP_##X: \
518 self()->print##X(cast(E), SS); \
519 return;
520#include "ThreadSafetyOps.def"
521#undef TIL_OPCODE_DEF
522 }
523 }
524
526 SS << "#null";
527 }
528
530 self()->printSExpr(E->maybeGetResult(), SS, Prec_Atom);
531 }
532
534 SS << "#undefined";
535 }
536
538 SS << "*";
539 }
540
541 template
543 SS << E->value();
544 }
545
547 SS << "'" << E->value() << "'";
548 }
549
551 if (E->clangExpr()) {
553 return;
554 }
555 else {
557 switch (VT.Base) {
559 SS << "void";
560 return;
562 if (E->as<bool>().value())
563 SS << "true";
564 else
565 SS << "false";
566 return;
568 switch (VT.Size) {
572 else
574 return;
578 else
580 return;
584 else
586 return;
590 else
592 return;
593 default:
594 break;
595 }
596 break;
598 switch (VT.Size) {
601 return;
604 return;
605 default:
606 break;
607 }
608 break;
610 SS << "\"";
612 SS << "\"";
613 return;
615 SS << "#ptr";
616 return;
618 SS << "#vref";
619 return;
620 }
621 }
622 SS << "#lit";
623 }
624
627 SS << D->getNameAsString();
628 else
629 SS << "";
630 }
631
634 SS << "this";
635 else
636 SS << V->name() << V->id();
637 }
638
640 switch (sugared) {
641 default:
642 SS << "\\(";
643 break;
644 case 1:
645 SS << "(";
646 break;
647 case 2:
648 SS << ", ";
649 break;
650 }
651 self()->printVariable(E->variableDecl(), SS, true);
652 SS << ": ";
653 self()->printSExpr(E->variableDecl()->definition(), SS, Prec_MAX);
654
655 const SExpr *B = E->body();
656 if (B && B->opcode() == COP_Function)
657 self()->printFunction(cast(B), SS, 2);
658 else {
659 SS << ")";
661 }
662 }
663
665 SS << "@";
666 self()->printVariable(E->variableDecl(), SS, true);
667 SS << " ";
669 }
670
672 SS << ": ";
673 self()->printSExpr(E->returnType(), SS, Prec_Decl-1);
674 SS << " -> ";
676 }
677
679 SS << ": ";
681 SS << " = ";
683 }
684
686 const SExpr *F = E->fun();
687 if (F->opcode() == COP_Apply) {
688 printApply(cast(F), SS, true);
689 SS << ", ";
690 } else {
692 SS << "(";
693 }
695 if (!sugared)
696 SS << ")$";
697 }
698
701 if (E->isDelegation()) {
702 SS << "@(";
704 SS << ")";
705 }
706 }
707
709 if (CStyle) {
710
711 if (const auto *SAP = dyn_cast(E->record())) {
712 if (const auto *V = dyn_cast(SAP->sfun())) {
714 SS << E->slotName();
715 return;
716 }
717 }
718 }
719 if (isa(E->record())) {
720
721 SS << "&";
722 SS << E->clangDecl()->getQualifiedNameAsString();
723 return;
724 }
725 }
727 if (CStyle && E->isArrow())
728 SS << "->";
729 else
730 SS << ".";
731 SS << E->slotName();
732 }
733
735 const SExpr *T = E->target();
736 if (T->opcode() == COP_Apply) {
737 self()->printApply(cast(T), SS, true);
738 SS << ")";
739 }
740 else {
742 SS << "()";
743 }
744 }
745
747 SS << "new ";
749 }
750
753 if (!CStyle)
754 SS << "^";
755 }
756
759 SS << " := ";
761 }
762
765 SS << "[";
767 SS << "]";
768 }
769
772 SS << " + ";
774 }
775
779 }
780
785 }
786
788 if (!CStyle) {
789 SS << "cast[";
790 switch (E->castOpcode()) {
792 SS << "none";
793 break;
795 SS << "extendNum";
796 break;
798 SS << "truncNum";
799 break;
801 SS << "toFloat";
802 break;
804 SS << "toInt";
805 break;
807 SS << "objToPtr";
808 break;
809 }
810 SS << "](";
812 SS << ")";
813 return;
814 }
816 }
817
819 SS << "CFG {\n";
820 for (const auto *BBI : *E)
822 SS << "}";
824 }
825
827 bool Sub = false;
828 if (E->opcode() == COP_Variable) {
830 SS << "let " << V->name() << V->id() << " = ";
832 Sub = true;
833 }
834 else if (E->opcode() != COP_Store) {
835 SS << "let _x" << E->id() << " = ";
836 }
838 SS << ";";
840 }
841
843 SS << "BB_" << E->blockID() << ":";
844 if (E->parent())
845 SS << " BB_" << E->parent()->blockID();
847
848 for (const auto *A : E->arguments())
850
851 for (const auto *I : E->instructions())
853
854 const SExpr *T = E->terminator();
855 if (T) {
857 SS << ";";
859 }
861 }
862
864 SS << "phi(";
866 self()->printSExpr(E->values()[0], SS, Prec_MAX);
867 else {
868 unsigned i = 0;
869 for (const auto *V : E->values()) {
870 if (i++ > 0)
871 SS << ", ";
873 }
874 }
875 SS << ")";
876 }
877
879 SS << "goto ";
881 }
882
884 SS << "branch (";
885 self()->printSExpr(E->condition(), SS, Prec_MAX);
886 SS << ") ";
888 SS << " ";
890 }
891
893 SS << "return ";
895 }
896
898 SS << E->name();
899 }
900
902 if (CStyle) {
904 SS << " ? ";
906 SS << " : ";
908 return;
909 }
910 SS << "if (";
912 SS << ") then ";
914 SS << " else ";
916 }
917
919 SS << "let ";
921 SS << " = ";
923 SS << "; ";
925 }
926};
927
929
930}
931}
932}
933
934#endif
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
__device__ __2f16 float __ockl_bool s
This represents a decl that may have a name.
Allocate memory for a new value on the heap or stack.
Apply an argument to a function.
Pointer arithmetic, restricted to arrays only.
If p is a reference to an array, then p[i] is a reference to the i'th element of the array.
A basic block is part of an SCFG.
int blockID() const
Returns the block ID. Every block has a unique ID in the CFG.
Simple arithmetic binary operations, e.g.
A conditional branch to two other blocks.
Call a function (after all arguments have been applied).
A block of code – e.g. the body of a function.
bool compareByCase(const SExpr *E1, const SExpr *E2)
Container(CopyReducerBase &S, unsigned N)
CopyReducerBase(MemRegionRef A)
bool compare(const SExpr *E1, const SExpr *E2)
bool comparePointers(const void *P, const void *Q)
bool compareStrings(StringRef s, StringRef r)
void enterScope(const Variable *V1, const Variable *V2)
bool compareVariableRefs(const Variable *V1, const Variable *V2)
static bool compareExprs(const SExpr *E1, const SExpr *E2)
bool compareIntegers(unsigned i, unsigned j)
A typed, writable location in memory.
Placeholder for an expression that has not yet been created.
Jump to another basic block.
An if-then-else expression.
A Literal pointer to an object allocated in memory.
Load a value from memory.
bool compareVariableRefs(const Variable *V1, const Variable *V2)
bool comparePointers(const void *P, const void *Q)
static bool compareExprs(const SExpr *E1, const SExpr *E2)
bool compare(const SExpr *E1, const SExpr *E2)
bool compareIntegers(unsigned i, unsigned j)
bool compareStrings(StringRef s, StringRef r)
void enterScope(const Variable *V1, const Variable *V2)
Phi Node, for code in SSA form.
static const unsigned Prec_MAX
void printFuture(const Future *E, StreamType &SS)
void printCall(const Call *E, StreamType &SS)
void printLiteralT(const LiteralT< uint8_t > *E, StreamType &SS)
void printApply(const Apply *E, StreamType &SS, bool sugared=false)
void printProject(const Project *E, StreamType &SS)
void printWildcard(const Wildcard *E, StreamType &SS)
void printBranch(const Branch *E, StreamType &SS)
void printLet(const Let *E, StreamType &SS)
void printLiteral(const Literal *E, StreamType &SS)
void printField(const Field *E, StreamType &SS)
void printUnaryOp(const UnaryOp *E, StreamType &SS)
void printUndefined(const Undefined *E, StreamType &SS)
void printIdentifier(const Identifier *E, StreamType &SS)
static void print(const SExpr *E, StreamType &SS)
void printReturn(const Return *E, StreamType &SS)
void printVariable(const Variable *V, StreamType &SS, bool IsVarDecl=false)
static const unsigned Prec_Unary
void printCode(const Code *E, StreamType &SS)
void printStore(const Store *E, StreamType &SS)
static const unsigned Prec_Binary
static const unsigned Prec_Atom
void printCast(const Cast *E, StreamType &SS)
void printIfThenElse(const IfThenElse *E, StreamType &SS)
void printBasicBlock(const BasicBlock *E, StreamType &SS)
void printLiteralPtr(const LiteralPtr *E, StreamType &SS)
void newline(StreamType &SS)
void printGoto(const Goto *E, StreamType &SS)
void printBBInstr(const SExpr *E, StreamType &SS)
void printAlloc(const Alloc *E, StreamType &SS)
void printNull(StreamType &SS)
void printPhi(const Phi *E, StreamType &SS)
void printSCFG(const SCFG *E, StreamType &SS)
static const unsigned Prec_Decl
unsigned precedence(const SExpr *E)
static const unsigned Prec_Postfix
void printFunction(const Function *E, StreamType &SS, unsigned sugared=0)
void printBinaryOp(const BinaryOp *E, StreamType &SS)
void printArrayAdd(const ArrayAdd *E, StreamType &SS)
static const unsigned Prec_Other
void printSFunction(const SFunction *E, StreamType &SS)
void printArrayIndex(const ArrayIndex *E, StreamType &SS)
void printSApply(const SApply *E, StreamType &SS)
void printLoad(const Load *E, StreamType &SS)
void printLiteralT(const LiteralT< T > *E, StreamType &SS)
PrettyPrinter(bool V=false, bool C=true, bool CS=true)
void printBlockLabel(StreamType &SS, const BasicBlock *BB, int index)
void printSExpr(const SExpr *E, StreamType &SS, unsigned P, bool Sub=true)
Project a named slot from a C++ struct or class.
Return from the enclosing function, passing the return value to the caller.
Apply a self-argument to a self-applicable function.
An SCFG is a control-flow graph.
Base class for AST nodes in the typed intermediate language.
TIL_Opcode opcode() const
A self-applicable function.
R_Ctx subExprCtx(R_Ctx Ctx)
R::R_SExpr traverse(T *&E, typename R::R_Ctx Ctx)
R::R_SExpr traverseSExpr(SExpr *E, typename R::R_Ctx Ctx)
R::R_SExpr traverseByCase(SExpr *E, typename R::R_Ctx Ctx)
Simple arithmetic unary operations, e.g.
Placeholder for expressions that cannot be represented in the TIL.
@ VK_SFun
SFunction (self) parameter.
Container(VisitReducerBase &S, unsigned N)
Variable * enterScope(Variable &Orig, R_SExpr E0)
R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1)
R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1)
R_SExpr reduceProject(Project &Orig, R_SExpr E0)
R_SExpr reduceLet(Let &Orig, Variable *Nvd, R_SExpr B)
R_SExpr reduceArrayAdd(Store &Orig, R_SExpr E0, R_SExpr E1)
R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0)
void exitScope(const Variable &Orig)
void exitBasicBlock(BasicBlock &BB)
R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0)
R_SExpr reduceIdentifier(Identifier &Orig)
R_SExpr reduceLiteral(Literal &Orig)
R_SExpr reduceSCFG(SCFG &Orig, Container< BasicBlock * > Bbs)
R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1)
R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container< R_SExpr > &As, Container< R_SExpr > &Is, R_SExpr T)
BasicBlock * reduceBasicBlockRef(BasicBlock *Obb)
R_SExpr reduceGoto(Goto &Orig, BasicBlock *B)
R_SExpr reduceUndefined(Undefined &Orig)
bool traverse(SExpr *E, TraversalKind K=TRV_Normal)
R_SExpr reduceWildcard(Wildcard &Orig)
R_SExpr reduceField(Field &Orig, R_SExpr E0, R_SExpr E1)
R_SExpr reducePhi(Phi &Orig, Container< R_SExpr > &As)
R_SExpr reduceLoad(Load &Orig, R_SExpr E0)
R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1)
R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0)
Variable * reduceVariableRef(Variable *Ovd)
R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1)
R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0)
R_SExpr reduceLiteralT(LiteralT< T > &Orig)
R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1)
void enterBasicBlock(BasicBlock &BB)
R_SExpr reduceReturn(Return &O, R_SExpr E)
R_SExpr reduceCast(Cast &Orig, R_SExpr E0)
R_SExpr reduceCall(Call &Orig, R_SExpr E0)
R_SExpr reduceArrayIndex(Store &Orig, R_SExpr E0, R_SExpr E1)
static bool visit(SExpr *E)
R_SExpr reduceLiteralPtr(Literal &Orig)
R_SExpr reduceIfThenElse(IfThenElse &Orig, R_SExpr C, R_SExpr T, R_SExpr E)
Placeholder for a wildcard that matches any other expression.
StringRef getBinaryOpcodeString(TIL_BinaryOpcode Op)
Return the name of a binary opcode.
StringRef getUnaryOpcodeString(TIL_UnaryOpcode Op)
Return the name of a unary opcode.
std::string getSourceLiteralString(const Expr *CE)
The JSON file list parser is used to communicate input to InstallAPI.
@ Self
'self' clause, allowed on Compute and Combined Constructs, plus 'update'.
const FunctionProtoType * T
ValueTypes are data types that can actually be held in registers.