47 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H 48 #define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H 53 #include "llvm/ADT/ArrayRef.h" 54 #include "llvm/ADT/None.h" 55 #include "llvm/ADT/Optional.h" 56 #include "llvm/ADT/StringRef.h" 57 #include "llvm/Support/Casting.h" 58 #include "llvm/Support/raw_ostream.h" 73 namespace threadSafety {
80 #define TIL_OPCODE_DEF(X) COP_##X, 81 #include "ThreadSafetyOps.def" 194 case 2:
return ST_16;
195 case 4:
return ST_32;
196 case 8:
return ST_64;
198 default:
return ST_0;
263 inline ValueType ValueType::getValueType<long double>() {
299 return ::operator
new(S, R);
303 void *
operator new(
size_t) =
delete;
308 void operator delete(
void *) =
delete;
312 unsigned id()
const {
return SExprID; }
326 unsigned char Reserved = 0;
327 unsigned short Flags = 0;
328 unsigned SExprID = 0;
333 namespace ThreadSafetyTIL {
336 unsigned Op = E->
opcode();
337 return Op == COP_Variable || Op == COP_Literal || Op == COP_LiteralPtr;
370 :
SExpr(COP_Variable), Name(s), Definition(D) {
375 :
SExpr(COP_Variable), Name(Cvd ? Cvd->
getName() :
"_x"),
376 Definition(D), Cvdecl(Cvd) {
381 :
SExpr(Vd), Name(Vd.Name), Definition(D), Cvdecl(Vd.Cvdecl) {
391 StringRef
name()
const {
return Name; }
408 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
410 return Vs.reduceVariableRef(
this);
415 return Cmp.compareVariableRefs(
this, E);
445 virtual ~
Future() =
delete;
468 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
469 assert(Result &&
"Cannot traverse Future that has not been forced.");
470 return Vs.traverse(Result, Ctx);
475 if (!Result || !E->Result)
476 return Cmp.comparePointers(
this, E);
477 return Cmp.compare(Result, E->Result);
484 SExpr *Result =
nullptr;
496 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
497 return Vs.reduceUndefined(*
this);
502 return Cmp.trueResult();
517 template <
class V>
typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
518 return Vs.reduceWildcard(*
this);
523 return Cmp.trueResult();
551 template <
class V>
typename V::R_SExpr traverse(V &Vs,
typename V::R_Ctx Ctx);
556 return Cmp.trueResult();
561 const Expr *Cexpr =
nullptr;
581 return Vs.reduceLiteral(*
this);
583 switch (ValType.Base) {
587 return Vs.reduceLiteralT(as<bool>());
589 switch (ValType.Size) {
592 return Vs.reduceLiteralT(as<int8_t>());
594 return Vs.reduceLiteralT(as<uint8_t>());
597 return Vs.reduceLiteralT(as<int16_t>());
599 return Vs.reduceLiteralT(as<uint16_t>());
602 return Vs.reduceLiteralT(as<int32_t>());
604 return Vs.reduceLiteralT(as<uint32_t>());
607 return Vs.reduceLiteralT(as<int64_t>());
609 return Vs.reduceLiteralT(as<uint64_t>());
615 switch (ValType.Size) {
617 return Vs.reduceLiteralT(as<float>());
619 return Vs.reduceLiteralT(as<double>());
625 return Vs.reduceLiteralT(as<StringRef>());
627 return Vs.reduceLiteralT(as<void*>());
631 return Vs.reduceLiteral(*
this);
647 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
648 return Vs.reduceLiteralPtr(*
this);
653 return Cmp.comparePointers(Cvdecl, E->Cvdecl);
684 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
689 auto E1 = Vs.
traverse(Body, Vs.declCtx(Ctx));
691 return Vs.reduceFunction(*
this, Nvd, E1);
696 typename C::CType Ct =
701 Ct = Cmp.compare(body(), E->
body());
718 assert(Vd->Definition ==
nullptr);
720 Vd->Definition =
this;
725 assert(Vd->Definition ==
nullptr);
727 Vd->Definition =
this;
739 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
744 auto E1 = Vs.
traverse(Body, Vs.declCtx(Ctx));
747 return Vs.reduceSFunction(*
this, Nvd, E1);
753 typename C::CType Ct = Cmp.compare(body(), E->
body());
768 :
SExpr(C), ReturnType(T), Body(B) {}
779 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
780 auto Nt = Vs.traverse(ReturnType, Vs.typeCtx(Ctx));
781 auto Nb = Vs.traverse(Body, Vs.lazyCtx(Ctx));
782 return Vs.reduceCode(*
this, Nt, Nb);
787 typename C::CType Ct = Cmp.compare(returnType(), E->
returnType());
790 return Cmp.compare(body(), E->
body());
803 :
SExpr(C), Range(R), Body(B) {}
814 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
815 auto Nr = Vs.traverse(Range, Vs.typeCtx(Ctx));
816 auto Nb = Vs.traverse(Body, Vs.lazyCtx(Ctx));
817 return Vs.reduceField(*
this, Nr, Nb);
822 typename C::CType Ct = Cmp.compare(range(), E->
range());
825 return Cmp.compare(body(), E->
body());
842 :
SExpr(A), Fun(F), Arg(Ar) {}
853 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
854 auto Nf = Vs.traverse(Fun, Vs.subExprCtx(Ctx));
855 auto Na = Vs.traverse(Arg, Vs.subExprCtx(Ctx));
856 return Vs.reduceApply(*
this, Nf, Na);
861 typename C::CType Ct = Cmp.compare(fun(), E->
fun());
864 return Cmp.compare(arg(), E->
arg());
877 :
SExpr(A), Sfun(Sf), Arg(Ar) {}
885 const SExpr *
arg()
const {
return Arg ? Arg : Sfun; }
890 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
891 auto Nf = Vs.traverse(Sfun, Vs.subExprCtx(Ctx));
892 typename V::R_SExpr Na = Arg ? Vs.traverse(Arg, Vs.subExprCtx(Ctx))
894 return Vs.reduceSApply(*
this, Nf, Na);
899 typename C::CType Ct = Cmp.compare(sfun(), E->
sfun());
900 if (Cmp.notTrue(Ct) || (!arg() && !E->
arg()))
902 return Cmp.compare(arg(), E->
arg());
914 :
SExpr(COP_Project), Rec(R), Cvdecl(Cvd) {
915 assert(Cvd &&
"ValueDecl must not be null");
925 bool isArrow()
const {
return (Flags & 0x01) != 0; }
928 if (b) Flags |= 0x01;
929 else Flags &= 0xFFFE;
933 if (Cvdecl->getDeclName().isIdentifier())
934 return Cvdecl->getName();
937 llvm::raw_string_ostream OS(*SlotName);
938 Cvdecl->printName(OS);
944 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
945 auto Nr = Vs.traverse(Rec, Vs.subExprCtx(Ctx));
946 return Vs.reduceProject(*
this, Nr);
951 typename C::CType Ct = Cmp.compare(record(), E->
record());
954 return Cmp.comparePointers(Cvdecl, E->Cvdecl);
978 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
979 auto Nt = Vs.traverse(
Target, Vs.subExprCtx(Ctx));
980 return Vs.reduceCall(*
this, Nt);
985 return Cmp.compare(target(), E->
target());
1012 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1013 auto Nd = Vs.traverse(Dtype, Vs.declCtx(Ctx));
1014 return Vs.reduceAlloc(*
this, Nd);
1019 typename C::CType Ct = Cmp.compareIntegers(
kind(), E->
kind());
1020 if (Cmp.notTrue(Ct))
1022 return Cmp.compare(dataType(), E->
dataType());
1041 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1042 auto Np = Vs.traverse(Ptr, Vs.subExprCtx(Ctx));
1043 return Vs.reduceLoad(*
this, Np);
1048 return Cmp.compare(pointer(), E->
pointer());
1071 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1072 auto Np = Vs.traverse(Dest, Vs.subExprCtx(Ctx));
1073 auto Nv = Vs.traverse(Source, Vs.subExprCtx(Ctx));
1074 return Vs.reduceStore(*
this, Np, Nv);
1079 typename C::CType Ct = Cmp.compare(destination(), E->
destination());
1080 if (Cmp.notTrue(Ct))
1082 return Cmp.compare(source(), E->
source());
1096 :
SExpr(E), Array(A), Index(N) {}
1107 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1108 auto Na = Vs.traverse(Array, Vs.subExprCtx(Ctx));
1109 auto Ni = Vs.traverse(Index, Vs.subExprCtx(Ctx));
1110 return Vs.reduceArrayIndex(*
this, Na, Ni);
1115 typename C::CType Ct = Cmp.compare(array(), E->
array());
1116 if (Cmp.notTrue(Ct))
1118 return Cmp.compare(index(), E->
index());
1133 :
SExpr(E), Array(A), Index(N) {}
1144 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1145 auto Na = Vs.traverse(Array, Vs.subExprCtx(Ctx));
1146 auto Ni = Vs.traverse(Index, Vs.subExprCtx(Ctx));
1147 return Vs.reduceArrayAdd(*
this, Na, Ni);
1152 typename C::CType Ct = Cmp.compare(array(), E->
array());
1153 if (Cmp.notTrue(Ct))
1155 return Cmp.compare(index(), E->
index());
1183 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1184 auto Ne = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
1185 return Vs.reduceUnaryOp(*
this, Ne);
1190 typename C::CType Ct =
1191 Cmp.compareIntegers(unaryOpcode(), E->
unaryOpcode());
1192 if (Cmp.notTrue(Ct))
1194 return Cmp.compare(
expr(), E->
expr());
1206 :
SExpr(COP_BinaryOp), Expr0(E0), Expr1(E1) {
1211 :
SExpr(B), Expr0(E0), Expr1(E1) {
1228 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1229 auto Ne0 = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
1230 auto Ne1 = Vs.traverse(Expr1, Vs.subExprCtx(Ctx));
1231 return Vs.reduceBinaryOp(*
this, Ne0, Ne1);
1236 typename C::CType Ct =
1237 Cmp.compareIntegers(binaryOpcode(), E->
binaryOpcode());
1238 if (Cmp.notTrue(Ct))
1240 Ct = Cmp.compare(expr0(), E->
expr0());
1241 if (Cmp.notTrue(Ct))
1243 return Cmp.compare(expr1(), E->
expr1());
1269 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1270 auto Ne = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
1271 return Vs.reduceCast(*
this, Ne);
1276 typename C::CType Ct =
1277 Cmp.compareIntegers(castOpcode(), E->
castOpcode());
1278 if (Cmp.notTrue(Ct))
1280 return Cmp.compare(
expr(), E->
expr());
1324 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1325 typename V::template Container<typename V::R_SExpr>
1326 Nvs(Vs, Values.size());
1328 for (
const auto *Val : Values)
1329 Nvs.push_back( Vs.traverse(Val, Vs.subExprCtx(Ctx)) );
1330 return Vs.reducePhi(*
this, Nvs);
1336 return Cmp.comparePointers(
this, E);
1352 return E->
opcode() >= COP_Goto && E->
opcode() <= COP_Return;
1359 return const_cast<Terminator*
>(
this)->successors();
1371 :
Terminator(COP_Goto), TargetBlock(B), Index(I) {}
1373 :
Terminator(COP_Goto), TargetBlock(B), Index(I) {}
1381 unsigned index()
const {
return Index; }
1387 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1388 BasicBlock *Ntb = Vs.reduceBasicBlockRef(TargetBlock);
1389 return Vs.reduceGoto(*
this, Ntb);
1395 return Cmp.comparePointers(
this, E);
1433 return llvm::makeArrayRef(Branches);
1437 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1438 auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx));
1439 BasicBlock *Ntb = Vs.reduceBasicBlockRef(Branches[0]);
1440 BasicBlock *Nte = Vs.reduceBasicBlockRef(Branches[1]);
1441 return Vs.reduceBranch(*
this, Nc, Ntb, Nte);
1447 return Cmp.comparePointers(
this, E);
1471 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1472 auto Ne = Vs.traverse(Retval, Vs.subExprCtx(Ctx));
1473 return Vs.reduceReturn(*
this, Ne);
1478 return Cmp.compare(Retval, E->Retval);
1487 case COP_Goto:
return cast<Goto>(
this)->successors();
1488 case COP_Branch:
return cast<Branch>(
this)->successors();
1489 case COP_Return:
return cast<Return>(
this)->successors();
1513 int SizeOfSubTree = 0;
1521 return OtherNode.
NodeID > NodeID &&
1522 OtherNode.
NodeID < NodeID + SizeOfSubTree;
1526 return OtherNode.
NodeID >= NodeID &&
1527 OtherNode.
NodeID < NodeID + SizeOfSubTree;
1532 :
SExpr(COP_BasicBlock), Arena(A), BlockID(0), Visited(
false) {}
1535 :
SExpr(COP_BasicBlock), Arena(A), BlockID(0), Visited(
false),
1536 Args(
std::move(As)), Instrs(
std::move(Is)), TermInstr(T) {}
1574 return DominatorNode.isParentOfOrEqual(Other.DominatorNode);
1578 return PostDominatorNode.isParentOfOrEqual(Other.PostDominatorNode);
1583 Args.reserveCheck(1, Arena);
1589 Instrs.reserveCheck(1, Arena);
1590 Instrs.push_back(V);
1604 void reservePredecessors(
unsigned NumPreds);
1608 auto I = std::find(Predecessors.cbegin(), Predecessors.cend(), BB);
1613 typename V::R_BasicBlock
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1614 typename V::template Container<SExpr*> Nas(Vs, Args.size());
1615 typename V::template Container<SExpr*> Nis(Vs, Instrs.size());
1618 Vs.enterBasicBlock(*
this);
1620 for (
const auto *E : Args) {
1621 auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
1624 for (
const auto *E : Instrs) {
1625 auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
1628 auto Nt = Vs.traverse(TermInstr, Ctx);
1631 Vs.exitBasicBlock(*
this);
1633 return Vs.reduceBasicBlock(*
this, Nas, Nis, Nt);
1639 return Cmp.comparePointers(
this, E);
1646 int renumberInstrs(
int id);
1650 void computeDominator();
1651 void computePostDominator();
1657 SCFG *CFGPtr =
nullptr;
1694 :
SExpr(COP_SCFG), Arena(A), Blocks(A, Nblocks) {
1697 auto *V =
new (A)
Phi();
1698 Exit->addArgument(V);
1699 Exit->setTerminator(
new (A)
Return(V));
1705 :
SExpr(COP_SCFG), Arena(Cfg.Arena), Blocks(
std::move(Ba)) {
1712 bool valid()
const {
return Entry && Exit && Blocks.size() > 0; }
1743 assert(BB->CFGPtr ==
nullptr);
1745 Blocks.reserveCheck(1, Arena);
1746 Blocks.push_back(BB);
1752 void computeNormalForm();
1755 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1757 typename V::template Container<BasicBlock *> Bbs(Vs, Blocks.size());
1759 for (
const auto *B : Blocks) {
1760 Bbs.push_back( B->traverse(Vs, Vs.subExprCtx(Ctx)) );
1763 return Vs.reduceSCFG(*
this, Bbs);
1769 return Cmp.comparePointers(
this, E);
1774 void renumberInstrs();
1780 unsigned NumInstructions = 0;
1781 bool Normal =
false;
1793 StringRef
name()
const {
return Name; }
1796 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1797 return Vs.reduceIdentifier(*
this);
1802 return Cmp.compareStrings(name(), E->
name());
1814 :
SExpr(COP_IfThenElse), Condition(C), ThenExpr(T), ElseExpr(E) {}
1816 :
SExpr(I), Condition(C), ThenExpr(T), ElseExpr(E) {}
1830 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1831 auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx));
1832 auto Nt = Vs.traverse(ThenExpr, Vs.subExprCtx(Ctx));
1833 auto Ne = Vs.traverse(ElseExpr, Vs.subExprCtx(Ctx));
1834 return Vs.reduceIfThenElse(*
this, Nc, Nt, Ne);
1839 typename C::CType Ct = Cmp.compare(condition(), E->
condition());
1840 if (Cmp.notTrue(Ct))
1842 Ct = Cmp.compare(thenExpr(), E->
thenExpr());
1843 if (Cmp.notTrue(Ct))
1845 return Cmp.compare(elseExpr(), E->
elseExpr());
1875 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1882 return Vs.reduceLet(*
this, Nvd, E1);
1887 typename C::CType Ct =
1889 if (Cmp.notTrue(Ct))
1892 Ct = Cmp.compare(body(), E->
body());
1911 #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)
__SIZE_TYPE__ size_t
The unsigned integer type of the result of the sizeof operator.
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...
std::string getName(ArrayRef< StringRef > Parts) const
Get the platform-specific name separator.
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
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 ...
Expr - 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 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)
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
bool isTrivial(const SExpr *E)
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)