46 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H 47 #define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H 52 #include "llvm/ADT/ArrayRef.h" 53 #include "llvm/ADT/None.h" 54 #include "llvm/ADT/Optional.h" 55 #include "llvm/ADT/StringRef.h" 56 #include "llvm/Support/Casting.h" 57 #include "llvm/Support/raw_ostream.h" 72 namespace threadSafety {
79 #define TIL_OPCODE_DEF(X) COP_##X, 80 #include "ThreadSafetyOps.def" 193 case 2:
return ST_16;
194 case 4:
return ST_32;
195 case 8:
return ST_64;
197 default:
return ST_0;
262 inline ValueType ValueType::getValueType<long double>() {
298 return ::operator
new(S, R);
302 void *
operator new(
size_t) =
delete;
307 void operator delete(
void *) =
delete;
311 unsigned id()
const {
return SExprID; }
325 unsigned char Reserved = 0;
326 unsigned short Flags = 0;
327 unsigned SExprID = 0;
332 namespace ThreadSafetyTIL {
335 unsigned Op = E->
opcode();
336 return Op == COP_Variable || Op == COP_Literal || Op == COP_LiteralPtr;
369 :
SExpr(COP_Variable), Name(s), Definition(D) {
374 :
SExpr(COP_Variable), Name(Cvd ? Cvd->
getName() :
"_x"),
375 Definition(D), Cvdecl(Cvd) {
380 :
SExpr(Vd), Name(Vd.Name), Definition(D), Cvdecl(Vd.Cvdecl) {
390 StringRef
name()
const {
return Name; }
407 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
409 return Vs.reduceVariableRef(
this);
414 return Cmp.compareVariableRefs(
this, E);
444 virtual ~
Future() =
delete;
467 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
468 assert(Result &&
"Cannot traverse Future that has not been forced.");
469 return Vs.traverse(Result, Ctx);
474 if (!Result || !E->Result)
475 return Cmp.comparePointers(
this, E);
476 return Cmp.compare(Result, E->Result);
483 SExpr *Result =
nullptr;
495 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
496 return Vs.reduceUndefined(*
this);
501 return Cmp.trueResult();
516 template <
class V>
typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
517 return Vs.reduceWildcard(*
this);
522 return Cmp.trueResult();
550 template <
class V>
typename V::R_SExpr traverse(
V &Vs,
typename V::R_Ctx Ctx);
555 return Cmp.trueResult();
560 const Expr *Cexpr =
nullptr;
580 return Vs.reduceLiteral(*
this);
582 switch (ValType.Base) {
586 return Vs.reduceLiteralT(as<bool>());
588 switch (ValType.Size) {
591 return Vs.reduceLiteralT(as<int8_t>());
593 return Vs.reduceLiteralT(as<uint8_t>());
596 return Vs.reduceLiteralT(as<int16_t>());
598 return Vs.reduceLiteralT(as<uint16_t>());
601 return Vs.reduceLiteralT(as<int32_t>());
603 return Vs.reduceLiteralT(as<uint32_t>());
606 return Vs.reduceLiteralT(as<int64_t>());
608 return Vs.reduceLiteralT(as<uint64_t>());
614 switch (ValType.Size) {
616 return Vs.reduceLiteralT(as<float>());
618 return Vs.reduceLiteralT(as<double>());
624 return Vs.reduceLiteralT(as<StringRef>());
626 return Vs.reduceLiteralT(as<void*>());
630 return Vs.reduceLiteral(*
this);
646 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
647 return Vs.reduceLiteralPtr(*
this);
652 return Cmp.comparePointers(Cvdecl, E->Cvdecl);
683 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
688 auto E1 = Vs.
traverse(Body, Vs.declCtx(Ctx));
690 return Vs.reduceFunction(*
this, Nvd, E1);
695 typename C::CType Ct =
700 Ct = Cmp.compare(body(), E->
body());
717 assert(Vd->Definition ==
nullptr);
719 Vd->Definition =
this;
724 assert(Vd->Definition ==
nullptr);
726 Vd->Definition =
this;
738 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
743 auto E1 = Vs.
traverse(Body, Vs.declCtx(Ctx));
746 return Vs.reduceSFunction(*
this, Nvd, E1);
752 typename C::CType Ct = Cmp.compare(body(), E->
body());
767 :
SExpr(C), ReturnType(T), Body(B) {}
778 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
779 auto Nt = Vs.traverse(ReturnType, Vs.typeCtx(Ctx));
780 auto Nb = Vs.traverse(Body, Vs.lazyCtx(Ctx));
781 return Vs.reduceCode(*
this, Nt, Nb);
786 typename C::CType Ct = Cmp.compare(returnType(), E->
returnType());
789 return Cmp.compare(body(), E->
body());
802 :
SExpr(C), Range(R), Body(B) {}
813 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
814 auto Nr = Vs.traverse(Range, Vs.typeCtx(Ctx));
815 auto Nb = Vs.traverse(Body, Vs.lazyCtx(Ctx));
816 return Vs.reduceField(*
this, Nr, Nb);
821 typename C::CType Ct = Cmp.compare(
range(), E->
range());
824 return Cmp.compare(body(), E->
body());
841 :
SExpr(A), Fun(F), Arg(Ar) {}
852 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
853 auto Nf = Vs.traverse(Fun, Vs.subExprCtx(Ctx));
854 auto Na = Vs.traverse(Arg, Vs.subExprCtx(Ctx));
855 return Vs.reduceApply(*
this, Nf, Na);
860 typename C::CType Ct = Cmp.compare(fun(), E->
fun());
863 return Cmp.compare(arg(), E->
arg());
876 :
SExpr(A), Sfun(Sf), Arg(Ar) {}
884 const SExpr *
arg()
const {
return Arg ? Arg : Sfun; }
889 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
890 auto Nf = Vs.traverse(Sfun, Vs.subExprCtx(Ctx));
891 typename V::R_SExpr Na = Arg ? Vs.traverse(Arg, Vs.subExprCtx(Ctx))
893 return Vs.reduceSApply(*
this, Nf, Na);
898 typename C::CType Ct = Cmp.compare(sfun(), E->
sfun());
899 if (Cmp.notTrue(Ct) || (!arg() && !E->
arg()))
901 return Cmp.compare(arg(), E->
arg());
913 :
SExpr(COP_Project), Rec(R), Cvdecl(Cvd) {
914 assert(Cvd &&
"ValueDecl must not be null");
924 bool isArrow()
const {
return (Flags & 0x01) != 0; }
927 if (b) Flags |= 0x01;
928 else Flags &= 0xFFFE;
932 if (Cvdecl->getDeclName().isIdentifier())
933 return Cvdecl->getName();
936 llvm::raw_string_ostream OS(*SlotName);
937 Cvdecl->printName(OS);
943 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
944 auto Nr = Vs.traverse(Rec, Vs.subExprCtx(Ctx));
945 return Vs.reduceProject(*
this, Nr);
950 typename C::CType Ct = Cmp.compare(record(), E->
record());
953 return Cmp.comparePointers(Cvdecl, E->Cvdecl);
977 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
978 auto Nt = Vs.traverse(
Target, Vs.subExprCtx(Ctx));
979 return Vs.reduceCall(*
this, Nt);
984 return Cmp.compare(target(), E->
target());
1011 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1012 auto Nd = Vs.traverse(Dtype, Vs.declCtx(Ctx));
1013 return Vs.reduceAlloc(*
this, Nd);
1018 typename C::CType Ct = Cmp.compareIntegers(
kind(), E->
kind());
1019 if (Cmp.notTrue(Ct))
1021 return Cmp.compare(dataType(), E->
dataType());
1040 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1041 auto Np = Vs.traverse(Ptr, Vs.subExprCtx(Ctx));
1042 return Vs.reduceLoad(*
this, Np);
1047 return Cmp.compare(pointer(), E->
pointer());
1070 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1071 auto Np = Vs.traverse(Dest, Vs.subExprCtx(Ctx));
1072 auto Nv = Vs.traverse(Source, Vs.subExprCtx(Ctx));
1073 return Vs.reduceStore(*
this, Np, Nv);
1078 typename C::CType Ct = Cmp.compare(destination(), E->
destination());
1079 if (Cmp.notTrue(Ct))
1081 return Cmp.compare(source(), E->
source());
1095 :
SExpr(E), Array(A), Index(N) {}
1106 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1107 auto Na = Vs.traverse(Array, Vs.subExprCtx(Ctx));
1108 auto Ni = Vs.traverse(Index, Vs.subExprCtx(Ctx));
1109 return Vs.reduceArrayIndex(*
this, Na, Ni);
1114 typename C::CType Ct = Cmp.compare(array(), E->
array());
1115 if (Cmp.notTrue(Ct))
1117 return Cmp.compare(index(), E->
index());
1132 :
SExpr(E), Array(A), Index(N) {}
1143 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1144 auto Na = Vs.traverse(Array, Vs.subExprCtx(Ctx));
1145 auto Ni = Vs.traverse(Index, Vs.subExprCtx(Ctx));
1146 return Vs.reduceArrayAdd(*
this, Na, Ni);
1151 typename C::CType Ct = Cmp.compare(array(), E->
array());
1152 if (Cmp.notTrue(Ct))
1154 return Cmp.compare(index(), E->
index());
1182 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1183 auto Ne = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
1184 return Vs.reduceUnaryOp(*
this, Ne);
1189 typename C::CType Ct =
1190 Cmp.compareIntegers(unaryOpcode(), E->
unaryOpcode());
1191 if (Cmp.notTrue(Ct))
1193 return Cmp.compare(
expr(), E->
expr());
1205 :
SExpr(COP_BinaryOp), Expr0(E0), Expr1(E1) {
1210 :
SExpr(B), Expr0(E0), Expr1(E1) {
1227 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1228 auto Ne0 = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
1229 auto Ne1 = Vs.traverse(Expr1, Vs.subExprCtx(Ctx));
1230 return Vs.reduceBinaryOp(*
this, Ne0, Ne1);
1235 typename C::CType Ct =
1236 Cmp.compareIntegers(binaryOpcode(), E->
binaryOpcode());
1237 if (Cmp.notTrue(Ct))
1239 Ct = Cmp.compare(expr0(), E->
expr0());
1240 if (Cmp.notTrue(Ct))
1242 return Cmp.compare(expr1(), E->
expr1());
1268 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1269 auto Ne = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
1270 return Vs.reduceCast(*
this, Ne);
1275 typename C::CType Ct =
1276 Cmp.compareIntegers(castOpcode(), E->
castOpcode());
1277 if (Cmp.notTrue(Ct))
1279 return Cmp.compare(
expr(), E->
expr());
1323 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1324 typename V::template Container<typename V::R_SExpr>
1325 Nvs(Vs, Values.size());
1327 for (
const auto *Val : Values)
1328 Nvs.push_back( Vs.traverse(Val, Vs.subExprCtx(Ctx)) );
1329 return Vs.reducePhi(*
this, Nvs);
1335 return Cmp.comparePointers(
this, E);
1351 return E->
opcode() >= COP_Goto && E->
opcode() <= COP_Return;
1358 return const_cast<Terminator*
>(
this)->successors();
1370 :
Terminator(COP_Goto), TargetBlock(B), Index(I) {}
1372 :
Terminator(COP_Goto), TargetBlock(B), Index(I) {}
1380 unsigned index()
const {
return Index; }
1386 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1387 BasicBlock *Ntb = Vs.reduceBasicBlockRef(TargetBlock);
1388 return Vs.reduceGoto(*
this, Ntb);
1394 return Cmp.comparePointers(
this, E);
1432 return llvm::makeArrayRef(Branches);
1436 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1437 auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx));
1438 BasicBlock *Ntb = Vs.reduceBasicBlockRef(Branches[0]);
1439 BasicBlock *Nte = Vs.reduceBasicBlockRef(Branches[1]);
1440 return Vs.reduceBranch(*
this, Nc, Ntb, Nte);
1446 return Cmp.comparePointers(
this, E);
1470 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1471 auto Ne = Vs.traverse(Retval, Vs.subExprCtx(Ctx));
1472 return Vs.reduceReturn(*
this, Ne);
1477 return Cmp.compare(Retval, E->Retval);
1486 case COP_Goto:
return cast<Goto>(
this)->successors();
1487 case COP_Branch:
return cast<Branch>(
this)->successors();
1488 case COP_Return:
return cast<Return>(
this)->successors();
1512 int SizeOfSubTree = 0;
1520 return OtherNode.
NodeID > NodeID &&
1521 OtherNode.
NodeID < NodeID + SizeOfSubTree;
1525 return OtherNode.
NodeID >= NodeID &&
1526 OtherNode.
NodeID < NodeID + SizeOfSubTree;
1531 :
SExpr(COP_BasicBlock), Arena(A), BlockID(0), Visited(
false) {}
1534 :
SExpr(COP_BasicBlock), Arena(A), BlockID(0), Visited(
false),
1535 Args(
std::move(As)), Instrs(
std::move(Is)), TermInstr(T) {}
1573 return DominatorNode.isParentOfOrEqual(Other.DominatorNode);
1577 return PostDominatorNode.isParentOfOrEqual(Other.PostDominatorNode);
1582 Args.reserveCheck(1, Arena);
1588 Instrs.reserveCheck(1, Arena);
1589 Instrs.push_back(V);
1603 void reservePredecessors(
unsigned NumPreds);
1607 auto I = llvm::find(Predecessors, BB);
1612 typename V::R_BasicBlock
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1613 typename V::template Container<SExpr*> Nas(Vs, Args.size());
1614 typename V::template Container<SExpr*> Nis(Vs, Instrs.size());
1617 Vs.enterBasicBlock(*
this);
1619 for (
const auto *E : Args) {
1620 auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
1623 for (
const auto *E : Instrs) {
1624 auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
1627 auto Nt = Vs.traverse(TermInstr, Ctx);
1630 Vs.exitBasicBlock(*
this);
1632 return Vs.reduceBasicBlock(*
this, Nas, Nis, Nt);
1638 return Cmp.comparePointers(
this, E);
1645 unsigned renumberInstrs(
unsigned id);
1649 void computeDominator();
1650 void computePostDominator();
1656 SCFG *CFGPtr =
nullptr;
1659 unsigned BlockID : 31;
1693 :
SExpr(COP_SCFG), Arena(A), Blocks(A, Nblocks) {
1696 auto *
V =
new (A)
Phi();
1697 Exit->addArgument(
V);
1698 Exit->setTerminator(
new (A)
Return(
V));
1704 :
SExpr(COP_SCFG), Arena(Cfg.Arena), Blocks(
std::move(Ba)) {
1711 bool valid()
const {
return Entry && Exit && Blocks.size() > 0; }
1742 assert(BB->CFGPtr ==
nullptr);
1744 Blocks.reserveCheck(1, Arena);
1745 Blocks.push_back(BB);
1751 void computeNormalForm();
1754 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1756 typename V::template Container<BasicBlock *> Bbs(Vs, Blocks.size());
1758 for (
const auto *B : Blocks) {
1759 Bbs.push_back( B->traverse(Vs, Vs.subExprCtx(Ctx)) );
1762 return Vs.reduceSCFG(*
this, Bbs);
1768 return Cmp.comparePointers(
this, E);
1773 void renumberInstrs();
1779 unsigned NumInstructions = 0;
1780 bool Normal =
false;
1792 StringRef
name()
const {
return Name; }
1795 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1796 return Vs.reduceIdentifier(*
this);
1801 return Cmp.compareStrings(
name(), E->
name());
1813 :
SExpr(COP_IfThenElse), Condition(C), ThenExpr(T), ElseExpr(E) {}
1815 :
SExpr(I), Condition(C), ThenExpr(T), ElseExpr(E) {}
1829 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1830 auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx));
1831 auto Nt = Vs.traverse(ThenExpr, Vs.subExprCtx(Ctx));
1832 auto Ne = Vs.traverse(ElseExpr, Vs.subExprCtx(Ctx));
1833 return Vs.reduceIfThenElse(*
this, Nc, Nt, Ne);
1838 typename C::CType Ct = Cmp.compare(condition(), E->
condition());
1839 if (Cmp.notTrue(Ct))
1841 Ct = Cmp.compare(thenExpr(), E->
thenExpr());
1842 if (Cmp.notTrue(Ct))
1844 return Cmp.compare(elseExpr(), E->
elseExpr());
1874 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1881 return Vs.reduceLet(*
this, Nvd, E1);
1886 typename C::CType Ct =
1888 if (Cmp.notTrue(Ct))
1891 Ct = Cmp.compare(body(), E->
body());
1910 #endif // LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H
VariableKind kind() const
Return the kind of variable (let, function param, or self)
const Variable * variableDecl() const
V::R_BasicBlock traverse(V &Vs, typename V::R_Ctx Ctx)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
Simple arithmetic unary operations, e.g.
UnaryOp(const UnaryOp &U, SExpr *E)
const BlockArray & predecessors() const
Apply a self-argument to a self-applicable function.
unsigned index() const
Returns the index into the.
ArrayRef< BasicBlock * > successors()
Pointer arithmetic, restricted to arrays only.
TIL_BinaryOpcode binaryOpcode() const
C::CType compare(const Load *E, C &Cmp) const
static bool classof(const SExpr *E)
const Terminator * terminator() const
StringRef getBinaryOpcodeString(TIL_BinaryOpcode Op)
Return the name of a binary opcode.
Variable(SExpr *D, const ValueDecl *Cvd=nullptr)
A typed, writable location in memory.
A conditional branch to two other blocks.
C::CType compare(const BasicBlock *E, C &Cmp) const
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
ValueTypes are data types that can actually be held in registers.
C::CType compare(const Identifier *E, C &Cmp) const
C::CType compare(const ArrayIndex *E, C &Cmp) const
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
C::CType compare(const SApply *E, C &Cmp) const
Stmt - This represents one statement.
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
BlockArray & predecessors()
Returns a list of predecessors.
ArrayAdd(SExpr *A, SExpr *N)
C::CType compare(const Variable *E, C &Cmp) const
void setID(BasicBlock *B, unsigned id)
Set the basic block and instruction ID for this expression.
static bool classof(const SExpr *E)
BlockArray::iterator iterator
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
UnaryOp(TIL_UnaryOpcode Op, SExpr *E)
static bool classof(const SExpr *E)
const TIL_BinaryOpcode BOP_Min
bool isParentOf(const TopologyNode &OtherNode)
static bool classof(const SExpr *E)
SFunction(const SFunction &F, Variable *Vd, SExpr *B)
Cast(const Cast &C, SExpr *E)
const BasicBlock * entry() const
static bool classof(const SExpr *E)
bool isDelegation() const
const SExpr * body() const
Function(Variable *Vd, SExpr *Bd)
Undefined(const Undefined &U)
float __ovld __cnfn distance(float p0, float p1)
Returns the distance between p0 and p1.
const SExpr * definition() const
BasicBlock(BasicBlock &B, MemRegionRef A, InstrArray &&As, InstrArray &&Is, Terminator *T)
SExpr * simplifyToCanonicalVal(SExpr *E)
ArrayAdd(const ArrayAdd &E, SExpr *A, SExpr *N)
const SExpr * target() const
Represents a variable declaration or definition.
Variable(StringRef s, SExpr *D=nullptr)
SExpr * maybeGetResult() const
const TIL_UnaryOpcode UOP_Max
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
StringRef name() const
Return the name of the variable, if any.
void setClangDecl(const ValueDecl *VD)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
ArrayIndex(const ArrayIndex &E, SExpr *A, SExpr *N)
Variable * variableDecl()
const SExpr * body() const
const_iterator end() const
size_t numPredecessors() const
Returns the number of predecessors.
If p is a reference to an array, then p[i] is a reference to the i'th element of the array...
unsigned numInstructions()
Return the total number of instructions in the CFG.
Field(SExpr *R, SExpr *B)
SCFG(MemRegionRef A, unsigned Nblocks)
const SExpr * thenExpr() const
const SExpr * returnType() const
static bool classof(const SExpr *E)
BlockArray::const_iterator const_iterator
const InstrArray & instructions() const
Phi(const Phi &P, ValArray &&Vs)
unsigned id() const
Returns the instruction ID for this expression.
InstrArray & instructions()
Project a named slot from a C++ struct or class.
ValueType(BaseType B, SizeType Sz, bool S, unsigned char VS)
C::CType compare(const Wildcard *E, C &Cmp) const
const ValueDecl * clangDecl() const
Return the clang declaration of the variable for this Phi node, if any.
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
const_iterator cend() const
static bool classof(const SExpr *E)
SApply(SApply &A, SExpr *Sf, SExpr *Ar=nullptr)
size_t numSuccessors() const
const SExpr * pointer() const
C::CType compare(const UnaryOp *E, C &Cmp) const
C::CType compare(const Cast *E, C &Cmp) const
C::CType compare(const Apply *E, C &Cmp) const
StringRef slotName() const
__SIZE_TYPE__ size_t
The unsigned integer type of the result of the sizeof operator.
This declaration is definitely a definition.
Cast(TIL_CastOpcode Op, SExpr *E)
static bool classof(const SExpr *E)
const LiteralT< T > & as() const
void reserveInstructions(unsigned Nins)
const SExpr * sfun() const
Base class for basic block terminators: Branch, Goto, and Return.
Let(Variable *Vd, SExpr *Bd)
BinaryOp(TIL_BinaryOpcode Op, SExpr *E0, SExpr *E1)
unsigned findPredecessorIndex(const BasicBlock *BB) const
Return the index of BB, or Predecessors.size if BB is not a predecessor.
const SExpr * expr1() const
static bool classof(const SExpr *E)
static bool classof(const SExpr *E)
static bool classof(const SExpr *E)
ArrayRef< BasicBlock * > successors()
Return the list of basic blocks that this terminator can branch to.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified...
virtual SExpr * compute()
TIL_Opcode opcode() const
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
Terminator(const SExpr &E)
const SExpr * condition() const
Branch(SExpr *C, BasicBlock *T, BasicBlock *E)
ArrayIndex(SExpr *A, SExpr *N)
static bool classof(const SExpr *E)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
Return(const Return &R, SExpr *Rval)
C::CType compare(const Return *E, C &Cmp) const
A basic block is part of an SCFG.
const_iterator begin() const
const SExpr * body() const
void setDefinition(SExpr *E)
void setEntry(BasicBlock *BB)
void setClangDecl(const ValueDecl *Cvd)
Set the clang variable associated with this Phi node.
const ValueDecl * clangDecl() const
Placeholder for expressions that cannot be represented in the TIL.
ArrayRef< BasicBlock * > successors()
Return an empty list.
A self-applicable function.
void addInstruction(SExpr *V)
Add a new instruction.
static bool classof(const SExpr *E)
const SExpr * fun() const
An SCFG is a control-flow graph.
TIL_Opcode
Enum for the different distinct classes of SExpr.
Goto(const Goto &G, BasicBlock *B, unsigned I)
C::CType compare(const Call *E, C &Cmp) const
Field(const Field &C, SExpr *R, SExpr *B)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
bool isParentOfOrEqual(const TopologyNode &OtherNode)
void addArgument(Phi *V)
Add a new argument.
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
Apply an argument to a function.
C::CType compare(const Project *E, C &Cmp) const
ValueType valueType() const
StringRef getUnaryOpcodeString(TIL_UnaryOpcode Op)
Return the name of a unary opcode.
const SExpr * array() const
const SExpr * condition() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
This represents one expression.
void setTerminator(Terminator *E)
Apply(SExpr *F, SExpr *A)
TIL_UnaryOpcode unaryOpcode() const
const SExpr * arg() const
const unsigned char Opcode
static bool classof(const SExpr *E)
C::CType compare(const Branch *E, C &Cmp) const
C::CType compare(const Alloc *E, C &Cmp) const
const Variable * variableDecl() const
static bool classof(const SExpr *E)
Call(SExpr *T, const CallExpr *Ce=nullptr)
internal::Matcher< T > id(StringRef ID, const internal::BindableMatcher< T > &InnerMatcher)
If the provided matcher matches a node, binds the node to ID.
const SExpr * expr() const
const SExpr * expr() const
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
static bool classof(const SExpr *E)
void reserveArguments(unsigned Nargs)
static bool classof(const SExpr *E)
ArrayRef< BasicBlock * > successors()
Return the list of basic blocks that this terminator can branch to.
Jump to another basic block.
const SExpr * body() const
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
Return from the enclosing function, passing the return value to the caller.
IfThenElse(const IfThenElse &I, SExpr *C, SExpr *T, SExpr *E)
bool normal() const
Return true if this CFG has been normalized.
static bool classof(const SExpr *E)
C::CType compare(const Store *E, C &Cmp) const
const_iterator cbegin() const
const SExpr * expr0() const
const SExpr * array() const
const Expr * clangExpr() const
const SExpr * arg() const
const SExpr * destination() const
Let(const Let &L, Variable *Vd, SExpr *Bd)
const SExpr * elseExpr() const
bool PostDominates(const BasicBlock &Other)
Undefined(const Stmt *S=nullptr)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
bool Dominates(const BasicBlock &Other)
C::CType compare(const ArrayAdd *E, C &Cmp) const
TIL_BinaryOpcode
Opcode for binary arithmetic operations.
const SExpr * source() const
Call(const Call &C, SExpr *T)
static bool classof(const SExpr *E)
static SizeType getSizeType(unsigned nbytes)
C::CType compare(const IfThenElse *E, C &Cmp) const
const TIL_BinaryOpcode BOP_Max
const SExpr * index() const
const BasicBlock * parent() const
Project(SExpr *R, const ValueDecl *Cvd)
static bool classof(const SExpr *E)
const ValArray & values() const
TIL_UnaryOpcode
Opcode for unary arithmetic operations.
BasicBlock(MemRegionRef A)
const SExpr * getCanonicalVal(const SExpr *E)
const TIL_UnaryOpcode UOP_Min
C::CType compare(const Field *E, C &Cmp) const
const SExpr * record() const
void setKind(VariableKind K)
const TIL_CastOpcode CAST_Max
const Variable * variableDecl() const
Function(const Function &F, Variable *Vd, SExpr *Bd)
Store(SExpr *P, SExpr *V)
Terminator * terminator()
static bool classof(const SExpr *E)
const ValueDecl * clangDecl() const
Return the clang declaration for this variable, if any.
Phi(MemRegionRef A, unsigned Nvals)
C::CType compare(const Phi *E, C &Cmp) const
Placeholder for a wildcard that matches any other expression.
TIL_CastOpcode
Opcode for cast operations.
static bool classof(const SExpr *E)
C::CType compare(const LiteralPtr *E, C &Cmp) const
ArrayRef< BasicBlock * > successors() const
LiteralT(const LiteralT< T > &L)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
Variable(const Variable &Vd, SExpr *D)
SFunction(Variable *Vd, SExpr *B)
const InstrArray & arguments() const
const BasicBlock * thenBlock() const
const BasicBlock * targetBlock() const
Load a value from memory.
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
Dataflow Directional Tag Classes.
Allocate memory for a new value on the heap or stack.
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
static std::string getName(const CallEvent &Call)
static bool classof(const SExpr *E)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
static bool classof(const SExpr *E)
ArrayRef< BasicBlock * > successors() const
An if-then-else expression.
const CallExpr * clangCallExpr() const
const BasicBlock * exit() const
Variable * variableDecl()
C::CType compare(const SCFG *E, C &Cmp) const
SApply(SExpr *Sf, SExpr *A=nullptr)
BasicBlock * block() const
Returns the block, if this is an instruction in a basic block, otherwise returns null.
Goto(BasicBlock *B, unsigned I)
const SExpr * dataType() const
ArrayRef< BasicBlock * > successors()
Return the list of basic blocks that this terminator can branch to.
static bool classof(const SExpr *E)
const BasicBlock * elseBlock() const
C::CType compare(const Literal *E, C &Cmp) const
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
IfThenElse(SExpr *C, SExpr *T, SExpr *E)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
static bool classof(const SExpr *E)
Phi Node, for code in SSA form.
bool valid() const
Return true if this CFG is valid.
Simple arithmetic binary operations, e.g.
static bool classof(const SExpr *E)
BinaryOp(const BinaryOp &B, SExpr *E0, SExpr *E1)
A block of code – e.g. the body of a function.
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
void setName(StringRef S)
const ValueDecl * clangDecl() const
C::CType compare(const Goto *E, C &Cmp) const
C::CType compare(const Let *E, C &Cmp) const
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
TIL_CastOpcode castOpcode() const
SExpr * definition()
Return the definition of the variable.
Alloc(const Alloc &A, SExpr *Dt)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
size_t numBlocks() const
Return the number of blocks in the CFG.
const SExpr * index() const
SCFG(const SCFG &Cfg, BlockArray &&Ba)
static bool isTrivial(ASTContext &Ctx, const Expr *E)
Checks if the expression is constant or does not have non-trivial function calls. ...
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
const SExpr * range() const
static bool classof(const SExpr *E)
const SExpr * body() const
static bool classof(const SExpr *E)
Terminator(TIL_Opcode Op)
void simplifyIncompleteArg(til::Phi *Ph)
int blockID() const
Returns the block ID. Every block has a unique ID in the CFG.
BasicBlock * targetBlock()
C::CType compare(const BinaryOp *E, C &Cmp) const
unsigned kind
All of the diagnostics that can be emitted by the frontend.
C::CType compare(const SFunction *E, C &Cmp) const
Code(const Code &C, SExpr *T, SExpr *B)
C::CType compare(const Future *E, C &Cmp) const
void setExit(BasicBlock *BB)
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
static bool classof(const SExpr *E)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
Store(const Store &S, SExpr *P, SExpr *V)
Placeholder for an expression that has not yet been created.
C::CType compare(const Function *E, C &Cmp) const
C::CType compare(const Undefined *E, C &Cmp) const
Load(const Load &L, SExpr *P)
static bool classof(const SExpr *E)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
Base class for AST nodes in the typed intermediate language.
static ValueType getValueType()
A Literal pointer to an object allocated in memory.
C::CType compare(const Code *E, C &Cmp) const
Call a function (after all arguments have been applied).
Variable * variableDecl()
Alloc(SExpr *D, AllocKind K)
SFunction (self) parameter.
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
const SExpr * returnValue() const
static bool classof(const SExpr *E)
const TIL_CastOpcode CAST_Min
LiteralPtr(const ValueDecl *D)
Apply(const Apply &A, SExpr *F, SExpr *Ar)
Branch(const Branch &Br, SExpr *C, BasicBlock *T, BasicBlock *E)