17 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H 18 #define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H 24 namespace threadSafety {
52 template <
class Self,
class R>
55 Self *
self() {
return static_cast<Self *
>(
this); }
63 typename R::R_SExpr
traverse(
T* &E,
typename R::R_Ctx Ctx) {
76 #define TIL_OPCODE_DEF(X) \ 78 return self()->traverse##X(cast<X>(E), Ctx); 79 #include "ThreadSafetyOps.def" 82 return self()->reduceNull();
87 #define TIL_OPCODE_DEF(X) \ 88 typename R::R_SExpr traverse##X(X *e, typename R::R_Ctx Ctx) { \ 89 return e->traverse(*self(), Ctx); \ 91 #include "ThreadSafetyOps.def" 175 template <
class Self>
274 return Visitor.traverse(E, TRV_Normal);
283 template <
typename Self>
286 Self *
self() {
return reinterpret_cast<Self *
>(
this); }
291 #define TIL_OPCODE_DEF(X) \ 293 return cast<X>(E1)->compare(cast<X>(E2), *self()); 294 #include "ThreadSafetyOps.def" 295 #undef TIL_OPCODE_DEF 319 return compareByCase(E1, E2);
354 if (E1->
opcode() == COP_Wildcard || E2->
opcode() == COP_Wildcard)
359 return compareByCase(E1, E2);
372 return Matcher.
compare(E1, E2);
383 template <
typename Self,
typename StreamType>
392 : Verbose(V), Cleanup(C), CStyle(CS)
397 printer.printSExpr(E, SS, Prec_MAX);
401 Self *
self() {
return reinterpret_cast<Self *
>(
this); }
408 static const unsigned Prec_Atom = 0;
409 static const unsigned Prec_Postfix = 1;
410 static const unsigned Prec_Unary = 2;
411 static const unsigned Prec_Binary = 3;
412 static const unsigned Prec_Other = 4;
413 static const unsigned Prec_Decl = 5;
414 static const unsigned Prec_MAX = 6;
419 case COP_Future:
return Prec_Atom;
420 case COP_Undefined:
return Prec_Atom;
421 case COP_Wildcard:
return Prec_Atom;
423 case COP_Literal:
return Prec_Atom;
424 case COP_LiteralPtr:
return Prec_Atom;
425 case COP_Variable:
return Prec_Atom;
426 case COP_Function:
return Prec_Decl;
427 case COP_SFunction:
return Prec_Decl;
428 case COP_Code:
return Prec_Decl;
429 case COP_Field:
return Prec_Decl;
431 case COP_Apply:
return Prec_Postfix;
432 case COP_SApply:
return Prec_Postfix;
433 case COP_Project:
return Prec_Postfix;
435 case COP_Call:
return Prec_Postfix;
436 case COP_Alloc:
return Prec_Other;
437 case COP_Load:
return Prec_Postfix;
438 case COP_Store:
return Prec_Other;
439 case COP_ArrayIndex:
return Prec_Postfix;
440 case COP_ArrayAdd:
return Prec_Postfix;
442 case COP_UnaryOp:
return Prec_Unary;
443 case COP_BinaryOp:
return Prec_Binary;
444 case COP_Cast:
return Prec_Atom;
446 case COP_SCFG:
return Prec_Decl;
447 case COP_BasicBlock:
return Prec_MAX;
448 case COP_Phi:
return Prec_Atom;
449 case COP_Goto:
return Prec_Atom;
450 case COP_Branch:
return Prec_Atom;
451 case COP_Return:
return Prec_Other;
453 case COP_Identifier:
return Prec_Atom;
454 case COP_IfThenElse:
return Prec_Other;
455 case COP_Let:
return Prec_Decl;
476 self()->printNull(SS);
479 if (Sub && E->
block() && E->
opcode() != COP_Variable) {
480 SS <<
"_x" << E->
id();
483 if (
self()->precedence(E) > P) {
486 self()->printSExpr(E, SS, Prec_MAX);
492 #define TIL_OPCODE_DEF(X) \ 494 self()->print##X(cast<X>(E), SS); \ 496 #include "ThreadSafetyOps.def" 497 #undef TIL_OPCODE_DEF 523 SS <<
"'" << E->
value() <<
"'";
539 if (E->
as<
bool>().value())
549 printLiteralT(&E->
as<int8_t>(), SS);
551 printLiteralT(&E->
as<uint8_t>(), SS);
555 printLiteralT(&E->
as<int16_t>(), SS);
557 printLiteralT(&E->
as<uint16_t>(), SS);
561 printLiteralT(&E->
as<int32_t>(), SS);
563 printLiteralT(&E->
as<uint32_t>(), SS);
567 printLiteralT(&E->
as<int64_t>(), SS);
569 printLiteralT(&E->
as<uint64_t>(), SS);
579 printLiteralT(&E->
as<
float>(), SS);
582 printLiteralT(&E->
as<
double>(), SS);
591 printLiteralT(&E->
as<StringRef>(), SS);
616 SS << V->
name() << V->
id();
636 if (B && B->
opcode() == COP_Function)
637 self()->printFunction(cast<Function>(B), SS, 2);
640 self()->printSExpr(B, SS, Prec_Decl);
648 self()->printSExpr(E->
body(), SS, Prec_Decl);
653 self()->printSExpr(E->
returnType(), SS, Prec_Decl-1);
655 self()->printSExpr(E->
body(), SS, Prec_Decl);
660 self()->printSExpr(E->
range(), SS, Prec_Decl-1);
662 self()->printSExpr(E->
body(), SS, Prec_Decl);
667 if (F->
opcode() == COP_Apply) {
668 printApply(cast<Apply>(F), SS,
true);
671 self()->printSExpr(F, SS, Prec_Postfix);
674 self()->printSExpr(E->
arg(), SS, Prec_MAX);
680 self()->printSExpr(E->
sfun(), SS, Prec_Postfix);
683 self()->printSExpr(E->
arg(), SS, Prec_MAX);
691 if (
const SApply *SAP = dyn_cast<SApply>(E->
record())) {
692 if (
const Variable *V = dyn_cast<Variable>(SAP->sfun())) {
699 if (isa<Wildcard>(E->
record())) {
706 self()->printSExpr(E->
record(), SS, Prec_Postfix);
718 if (T->
opcode() == COP_Apply) {
719 self()->printApply(cast<Apply>(T), SS,
true);
723 self()->printSExpr(T, SS, Prec_Postfix);
730 self()->printSExpr(E->
dataType(), SS, Prec_Other-1);
734 self()->printSExpr(E->
pointer(), SS, Prec_Postfix);
740 self()->printSExpr(E->
destination(), SS, Prec_Other-1);
742 self()->printSExpr(E->
source(), SS, Prec_Other-1);
746 self()->printSExpr(E->
array(), SS, Prec_Postfix);
748 self()->printSExpr(E->
index(), SS, Prec_MAX);
753 self()->printSExpr(E->
array(), SS, Prec_Postfix);
755 self()->printSExpr(E->
index(), SS, Prec_Atom);
760 self()->printSExpr(E->
expr(), SS, Prec_Unary);
764 self()->printSExpr(E->
expr0(), SS, Prec_Binary-1);
766 self()->printSExpr(E->
expr1(), SS, Prec_Binary-1);
774 self()->printSExpr(E->
expr(), SS, Prec_Unary);
778 self()->printSExpr(E->
expr(), SS, Prec_Unary);
783 for (
auto BBI : *E) {
784 printBasicBlock(BBI, SS);
793 if (E->
opcode() == COP_Variable) {
794 auto *V = cast<Variable>(E);
795 SS <<
"let " << V->name() << V->id() <<
" = ";
799 else if (E->
opcode() != COP_Store) {
800 SS <<
"let _x" << E->
id() <<
" = ";
802 self()->printSExpr(E, SS, Prec_MAX, Sub);
808 SS <<
"BB_" << E->
blockID() <<
":";
821 self()->printSExpr(T, SS, Prec_MAX,
false);
831 self()->printSExpr(E->
values()[0], SS, Prec_MAX);
834 for (
auto V : E->
values()) {
837 self()->printSExpr(V, SS, Prec_MAX);
850 self()->printSExpr(E->
condition(), SS, Prec_MAX);
859 self()->printSExpr(E->
returnValue(), SS, Prec_Other);
868 printSExpr(E->
condition(), SS, Prec_Unary);
870 printSExpr(E->
thenExpr(), SS, Prec_Unary);
872 printSExpr(E->
elseExpr(), SS, Prec_Unary);
876 printSExpr(E->
condition(), SS, Prec_MAX);
878 printSExpr(E->
thenExpr(), SS, Prec_Other);
880 printSExpr(E->
elseExpr(), SS, Prec_Other);
889 printSExpr(E->
body(), SS, Prec_Decl-1);
902 #endif // LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H VariableKind kind() const
Return the kind of variable (let, function param, or self)
R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1)
Simple arithmetic unary operations, e.g.
Apply a self-argument to a self-applicable function.
unsigned index() const
Returns the index into the.
Pointer arithmetic, restricted to arrays only.
TIL_BinaryOpcode binaryOpcode() const
const Terminator * terminator() const
StringRef getBinaryOpcodeString(TIL_BinaryOpcode Op)
Return the name of a binary opcode.
R_SExpr reduceCall(Call &Orig, R_SExpr E0)
R_SExpr reduceArrayAdd(Store &Orig, R_SExpr E0, R_SExpr E1)
void printSExpr(const SExpr *E, StreamType &SS, unsigned P, bool Sub=true)
void printVariable(const Variable *V, StreamType &SS, bool IsVarDecl=false)
R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0)
A typed, writable location in memory.
A conditional branch to two other blocks.
bool compareVariableRefs(const Variable *V1, const Variable *V2)
ValueTypes are data types that can actually be held in registers.
CopyReducerBase(MemRegionRef A)
void printStore(const Store *E, StreamType &SS)
R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1)
BasicBlock * R_BasicBlock
void printCall(const Call *E, StreamType &SS)
R::R_SExpr traverse(T *&E, typename R::R_Ctx Ctx)
bool isDelegation() const
R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1)
bool compareIntegers(unsigned i, unsigned j)
SExpr * maybeGetResult() const
BasicBlock * reduceBasicBlockRef(BasicBlock *Obb)
R_SExpr reduceIfThenElse(IfThenElse &Orig, R_SExpr C, R_SExpr T, R_SExpr E)
StringRef name() const
Return the name of the variable, if any.
void printWildcard(const Wildcard *E, StreamType &SS)
Variable * variableDecl()
R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1)
If p is a reference to an array, then p[i] is a reference to the i'th element of the array...
R_SExpr reduceUndefined(Undefined &Orig)
unsigned id() const
Returns the instruction ID for this expression.
InstrArray & instructions()
Project a named slot from a C++ struct or class.
R::R_SExpr traverseSExpr(SExpr *E, typename R::R_Ctx Ctx)
void printUndefined(const Undefined *E, StreamType &SS)
Container(VisitReducerBase &S, unsigned N)
R_Ctx subExprCtx(R_Ctx Ctx)
R_SExpr reduceProject(Project &Orig, R_SExpr E0)
R_SExpr reducePhi(Phi &Orig, Container< R_SExpr > &As)
R::R_SExpr traverseByCase(SExpr *E, typename R::R_Ctx Ctx)
R_SExpr reduceSCFG(SCFG &Orig, Container< BasicBlock *> Bbs)
void printReturn(const Return *E, StreamType &SS)
void printLiteralT(const LiteralT< uint8_t > *E, StreamType &SS)
StringRef slotName() const
const LiteralT< T > & as() const
void printBinaryOp(const BinaryOp *E, StreamType &SS)
Variable * reduceVariableRef(Variable *Ovd)
R_SExpr reduceReturn(Return &O, R_SExpr E)
void printSFunction(const SFunction *E, StreamType &SS)
TIL_Opcode opcode() const
const SExpr * condition() const
static void print(const SExpr *E, StreamType &SS)
void printFunction(const Function *E, StreamType &SS, unsigned sugared=0)
bool compareVariableRefs(const Variable *V1, const Variable *V2)
R_SExpr reduceLet(Let &Orig, Variable *Nvd, R_SExpr B)
const clang::ValueDecl * clangDecl() const
A basic block is part of an SCFG.
void printArrayAdd(const ArrayAdd *E, StreamType &SS)
void printArrayIndex(const ArrayIndex *E, StreamType &SS)
Placeholder for expressions that cannot be represented in the TIL.
bool traverse(SExpr *E, TraversalKind K=TRV_Normal)
R_SExpr reduceCast(Cast &Orig, R_SExpr E0)
A self-applicable function.
unsigned precedence(const SExpr *E)
An SCFG is a control-flow graph.
R_SExpr reduceLoad(Load &Orig, R_SExpr E0)
void printNull(StreamType &SS)
R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1)
void printLiteral(const Literal *E, StreamType &SS)
PrettyPrinter(bool V=false, bool C=true, bool CS=true)
void enterBasicBlock(BasicBlock &BB)
Container(CopyReducerBase &S, unsigned N)
void printField(const Field *E, StreamType &SS)
Apply an argument to a function.
void printBranch(const Branch *E, StreamType &SS)
ValueType valueType() const
StringRef getUnaryOpcodeString(TIL_UnaryOpcode Op)
Return the name of a unary opcode.
const FunctionProtoType * T
TIL_UnaryOpcode unaryOpcode() const
void enterScope(const Variable *V1, const Variable *V2)
bool compare(const SExpr *E1, const SExpr *E2)
const clang::ValueDecl * clangDecl() const
bool compareByCase(const SExpr *E1, const SExpr *E2)
R_SExpr reduceLiteralT(LiteralT< T > &Orig)
Jump to another basic block.
R_SExpr reduceIdentifier(Identifier &Orig)
void printCast(const Cast *E, StreamType &SS)
Return from the enclosing function, passing the return value to the caller.
R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0)
static bool compareExprs(const SExpr *E1, const SExpr *E2)
bool compareIntegers(unsigned i, unsigned j)
void enterScope(const Variable *V1, const Variable *V2)
void printGoto(const Goto *E, StreamType &SS)
void printBasicBlock(const BasicBlock *E, StreamType &SS)
R_SExpr reduceField(Field &Orig, R_SExpr E0, R_SExpr E1)
void printFuture(const Future *E, StreamType &SS)
void printLet(const Let *E, StreamType &SS)
void exitBasicBlock(BasicBlock &BB)
bool compareStrings(StringRef s, StringRef r)
const BasicBlock * parent() const
std::string getNameAsString() const
getNameAsString - Get a human-readable name for the declaration, even if it is one of the special kin...
const ValArray & values() const
void printBBInstr(const SExpr *E, StreamType &SS)
void newline(StreamType &SS)
bool comparePointers(const void *P, const void *Q)
R_SExpr reduceWildcard(Wildcard &Orig)
R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0)
std::string getSourceLiteralString(const clang::Expr *CE)
Placeholder for a wildcard that matches any other expression.
void printApply(const Apply *E, StreamType &SS, bool sugared=false)
const InstrArray & arguments() const
const BasicBlock * thenBlock() const
const BasicBlock * targetBlock() const
Load a value from memory.
Dataflow Directional Tag Classes.
Allocate memory for a new value on the heap or stack.
void printSApply(const SApply *E, StreamType &SS)
void printSCFG(const SCFG *E, StreamType &SS)
void printUnaryOp(const UnaryOp *E, StreamType &SS)
An if-then-else expression.
R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0)
Variable * variableDecl()
BasicBlock * block() const
Returns the block, if this is an instruction in a basic block, otherwise returns null.
R_SExpr reduceLiteralPtr(Literal &Orig)
Variable * enterScope(Variable &Orig, R_SExpr E0)
const BasicBlock * elseBlock() const
R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container< R_SExpr > &As, Container< R_SExpr > &Is, R_SExpr T)
R_SExpr reduceLiteral(Literal &Orig)
Phi Node, for code in SSA form.
R_SExpr reduceGoto(Goto &Orig, BasicBlock *B)
Simple arithmetic binary operations, e.g.
A block of code – e.g. the body of a function.
void printBlockLabel(StreamType &SS, const BasicBlock *BB, int index)
R_SExpr reduceArrayIndex(Store &Orig, R_SExpr E0, R_SExpr E1)
void printLiteralPtr(const LiteralPtr *E, StreamType &SS)
void printLiteralT(const LiteralT< T > *E, StreamType &SS)
void printIdentifier(const Identifier *E, StreamType &SS)
TIL_CastOpcode castOpcode() const
R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1)
SExpr * definition()
Return the definition of the variable.
void printProject(const Project *E, StreamType &SS)
int blockID() const
Returns the block ID. Every block has a unique ID in the CFG.
void printAlloc(const Alloc *E, StreamType &SS)
bool compare(const SExpr *E1, const SExpr *E2)
void printIfThenElse(const IfThenElse *E, StreamType &SS)
std::string getQualifiedNameAsString() const
const clang::Expr * clangExpr() const
Placeholder for an expression that has not yet been created.
Base class for AST nodes in the typed intermediate language.
A Literal pointer to an object allocated in memory.
void printPhi(const Phi *E, StreamType &SS)
static bool compareExprs(const SExpr *E1, const SExpr *E2)
static bool visit(SExpr *E)
Call a function (after all arguments have been applied).
Variable * variableDecl()
void printLoad(const Load *E, StreamType &SS)
SFunction (self) parameter.
void exitScope(const Variable &Orig)
bool compareStrings(StringRef s, StringRef r)
bool comparePointers(const void *P, const void *Q)
void printCode(const Code *E, StreamType &SS)