47 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H 48 #define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H 61 namespace threadSafety {
67 #define TIL_OPCODE_DEF(X) COP_##X, 68 #include "ThreadSafetyOps.def" 172 case 2:
return ST_16;
173 case 4:
return ST_32;
174 case 8:
return ST_64;
176 default:
return ST_0;
242 inline ValueType ValueType::getValueType<long double>() {
280 return ::operator
new(S, R);
286 void operator delete(
void *) =
delete;
290 unsigned id()
const {
return SExprID; }
301 : Opcode(Op), Reserved(0), Flags(0), SExprID(0), Block(nullptr) {}
303 : Opcode(E.Opcode), Reserved(0), Flags(E.Flags), SExprID(0),
316 void *
operator new(
size_t) =
delete;
321 namespace ThreadSafetyTIL {
323 unsigned Op = E->
opcode();
324 return Op == COP_Variable || Op == COP_Literal || Op == COP_LiteralPtr;
357 :
SExpr(COP_Variable), Name(s), Definition(D), Cvdecl(nullptr) {
361 :
SExpr(COP_Variable), Name(Cvd ? Cvd->getName() :
"_x"),
362 Definition(D), Cvdecl(Cvd) {
366 :
SExpr(Vd), Name(Vd.Name), Definition(D), Cvdecl(Vd.Cvdecl) {
374 StringRef
name()
const {
return Name; }
391 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
393 return Vs.reduceVariableRef(
this);
398 return Cmp.compareVariableRefs(
this, E);
425 Future() :
SExpr(COP_Future), Status(FS_pending), Result(nullptr) {}
428 virtual ~
Future() =
delete;
452 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
453 assert(Result &&
"Cannot traverse Future that has not been forced.");
454 return Vs.traverse(Result, Ctx);
459 if (!Result || !E->Result)
460 return Cmp.comparePointers(
this, E);
461 return Cmp.compare(Result, E->Result);
481 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
482 return Vs.reduceUndefined(*
this);
487 return Cmp.trueResult();
503 template <
class V>
typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
504 return Vs.reduceWildcard(*
this);
509 return Cmp.trueResult();
539 template <
class V>
typename V::R_SExpr traverse(V &Vs,
typename V::R_Ctx Ctx);
544 return Cmp.trueResult();
572 return Vs.reduceLiteral(*
this);
574 switch (ValType.Base) {
578 return Vs.reduceLiteralT(as<bool>());
580 switch (ValType.Size) {
583 return Vs.reduceLiteralT(as<int8_t>());
585 return Vs.reduceLiteralT(as<uint8_t>());
588 return Vs.reduceLiteralT(as<int16_t>());
590 return Vs.reduceLiteralT(as<uint16_t>());
593 return Vs.reduceLiteralT(as<int32_t>());
595 return Vs.reduceLiteralT(as<uint32_t>());
598 return Vs.reduceLiteralT(as<int64_t>());
600 return Vs.reduceLiteralT(as<uint64_t>());
606 switch (ValType.Size) {
608 return Vs.reduceLiteralT(as<float>());
610 return Vs.reduceLiteralT(as<double>());
616 return Vs.reduceLiteralT(as<StringRef>());
618 return Vs.reduceLiteralT(as<void*>());
622 return Vs.reduceLiteral(*
this);
639 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
640 return Vs.reduceLiteralPtr(*
this);
645 return Cmp.comparePointers(Cvdecl, E->Cvdecl);
676 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
681 auto E1 = Vs.
traverse(Body, Vs.declCtx(Ctx));
683 return Vs.reduceFunction(*
this, Nvd, E1);
688 typename C::CType Ct =
693 Ct = Cmp.compare(body(), E->
body());
713 assert(Vd->Definition ==
nullptr);
715 Vd->Definition =
this;
719 assert(Vd->Definition ==
nullptr);
721 Vd->Definition =
this;
731 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
736 auto E1 = Vs.
traverse(Body, Vs.declCtx(Ctx));
739 return Vs.reduceSFunction(*
this, Nvd, E1);
745 typename C::CType Ct = Cmp.compare(body(), E->
body());
763 :
SExpr(C), ReturnType(T), Body(B) {}
772 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
773 auto Nt = Vs.traverse(ReturnType, Vs.typeCtx(Ctx));
774 auto Nb = Vs.traverse(Body, Vs.lazyCtx(Ctx));
775 return Vs.reduceCode(*
this, Nt, Nb);
780 typename C::CType Ct = Cmp.compare(returnType(), E->
returnType());
783 return Cmp.compare(body(), E->
body());
799 :
SExpr(C), Range(R), Body(B) {}
808 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
809 auto Nr = Vs.traverse(Range, Vs.typeCtx(Ctx));
810 auto Nb = Vs.traverse(Body, Vs.lazyCtx(Ctx));
811 return Vs.reduceField(*
this, Nr, Nb);
816 typename C::CType Ct = Cmp.compare(range(), E->
range());
819 return Cmp.compare(body(), E->
body());
839 :
SExpr(A), Fun(F), Arg(Ar)
849 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
850 auto Nf = Vs.traverse(Fun, Vs.subExprCtx(Ctx));
851 auto Na = Vs.traverse(Arg, Vs.subExprCtx(Ctx));
852 return Vs.reduceApply(*
this, Nf, Na);
857 typename C::CType Ct = Cmp.compare(fun(), E->
fun());
860 return Cmp.compare(arg(), E->
arg());
876 :
SExpr(A), Sfun(Sf), Arg(Ar) {}
882 const SExpr *
arg()
const {
return Arg ? Arg : Sfun; }
887 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
888 auto Nf = Vs.traverse(Sfun, Vs.subExprCtx(Ctx));
889 typename V::R_SExpr Na = Arg ? Vs.traverse(Arg, Vs.subExprCtx(Ctx))
891 return Vs.reduceSApply(*
this, Nf, Na);
896 typename C::CType Ct = Cmp.compare(sfun(), E->
sfun());
897 if (Cmp.notTrue(Ct) || (!arg() && !E->
arg()))
899 return Cmp.compare(arg(), E->
arg());
914 :
SExpr(COP_Project), Rec(R), Cvdecl(Cvd) {
915 assert(Cvd &&
"ValueDecl must not be null");
923 bool isArrow()
const {
return (Flags & 0x01) != 0; }
925 if (b) Flags |= 0x01;
926 else Flags &= 0xFFFE;
930 if (Cvdecl->getDeclName().isIdentifier())
931 return Cvdecl->getName();
934 llvm::raw_string_ostream OS(*SlotName);
935 Cvdecl->printName(OS);
941 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
942 auto Nr = Vs.traverse(Rec, Vs.subExprCtx(Ctx));
943 return Vs.reduceProject(*
this, Nr);
948 typename C::CType Ct = Cmp.compare(record(), E->
record());
951 return Cmp.comparePointers(Cvdecl, E->Cvdecl);
967 :
SExpr(COP_Call), Target(T), Cexpr(Ce) {}
976 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
977 auto Nt = Vs.traverse(Target, Vs.subExprCtx(Ctx));
978 return Vs.reduceCall(*
this, Nt);
983 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());
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());
1072 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1073 auto Np = Vs.traverse(Dest, Vs.subExprCtx(Ctx));
1074 auto Nv = Vs.traverse(Source, Vs.subExprCtx(Ctx));
1075 return Vs.reduceStore(*
this, Np, Nv);
1080 typename C::CType Ct = Cmp.compare(destination(), E->
destination());
1081 if (Cmp.notTrue(Ct))
1083 return Cmp.compare(source(), E->
source());
1100 :
SExpr(E), Array(A), Index(N) {}
1109 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1110 auto Na = Vs.traverse(Array, Vs.subExprCtx(Ctx));
1111 auto Ni = Vs.traverse(Index, Vs.subExprCtx(Ctx));
1112 return Vs.reduceArrayIndex(*
this, Na, Ni);
1117 typename C::CType Ct = Cmp.compare(array(), E->
array());
1118 if (Cmp.notTrue(Ct))
1120 return Cmp.compare(index(), E->
index());
1138 :
SExpr(E), Array(A), Index(N) {}
1147 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1148 auto Na = Vs.traverse(Array, Vs.subExprCtx(Ctx));
1149 auto Ni = Vs.traverse(Index, Vs.subExprCtx(Ctx));
1150 return Vs.reduceArrayAdd(*
this, Na, Ni);
1155 typename C::CType Ct = Cmp.compare(array(), E->
array());
1156 if (Cmp.notTrue(Ct))
1158 return Cmp.compare(index(), E->
index());
1186 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1187 auto Ne = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
1188 return Vs.reduceUnaryOp(*
this, Ne);
1193 typename C::CType Ct =
1194 Cmp.compareIntegers(unaryOpcode(), E->
unaryOpcode());
1195 if (Cmp.notTrue(Ct))
1197 return Cmp.compare(
expr(), E->
expr());
1212 :
SExpr(COP_BinaryOp), Expr0(E0), Expr1(E1) {
1216 :
SExpr(B), Expr0(E0), Expr1(E1) {
1231 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1232 auto Ne0 = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
1233 auto Ne1 = Vs.traverse(Expr1, Vs.subExprCtx(Ctx));
1234 return Vs.reduceBinaryOp(*
this, Ne0, Ne1);
1239 typename C::CType Ct =
1240 Cmp.compareIntegers(binaryOpcode(), E->
binaryOpcode());
1241 if (Cmp.notTrue(Ct))
1243 Ct = Cmp.compare(expr0(), E->
expr0());
1244 if (Cmp.notTrue(Ct))
1246 return Cmp.compare(expr1(), E->
expr1());
1273 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1274 auto Ne = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
1275 return Vs.reduceCast(*
this, Ne);
1280 typename C::CType Ct =
1281 Cmp.compareIntegers(castOpcode(), E->
castOpcode());
1282 if (Cmp.notTrue(Ct))
1284 return Cmp.compare(
expr(), E->
expr());
1314 :
SExpr(COP_Phi), Cvdecl(nullptr) {}
1316 :
SExpr(COP_Phi), Values(A, Nvals), Cvdecl(nullptr) {}
1318 :
SExpr(P), Values(
std::move(Vs)), Cvdecl(nullptr) {}
1320 const ValArray &
values()
const {
return Values; }
1333 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1334 typename V::template Container<typename V::R_SExpr>
1335 Nvs(Vs, Values.size());
1337 for (
auto *Val : Values) {
1338 Nvs.push_back( Vs.traverse(Val, Vs.subExprCtx(Ctx)) );
1340 return Vs.reducePhi(*
this, Nvs);
1346 return Cmp.comparePointers(
this, E);
1359 return E->
opcode() >= COP_Goto && E->
opcode() <= COP_Return;
1371 return const_cast<Terminator*
>(
this)->successors();
1386 :
Terminator(COP_Goto), TargetBlock(B), Index(I) {}
1388 :
Terminator(COP_Goto), TargetBlock(B), Index(I) {}
1394 unsigned index()
const {
return Index; }
1402 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1403 BasicBlock *Ntb = Vs.reduceBasicBlockRef(TargetBlock);
1404 return Vs.reduceGoto(*
this, Ntb);
1410 return Cmp.comparePointers(
this, E);
1448 return llvm::makeArrayRef(Branches);
1452 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1453 auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx));
1454 BasicBlock *Ntb = Vs.reduceBasicBlockRef(Branches[0]);
1455 BasicBlock *Nte = Vs.reduceBasicBlockRef(Branches[1]);
1456 return Vs.reduceBranch(*
this, Nc, Ntb, Nte);
1462 return Cmp.comparePointers(
this, E);
1489 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1490 auto Ne = Vs.traverse(Retval, Vs.subExprCtx(Ctx));
1491 return Vs.reduceReturn(*
this, Ne);
1496 return Cmp.compare(Retval, E->Retval);
1506 case COP_Goto:
return cast<Goto>(
this)->successors();
1507 case COP_Branch:
return cast<Branch>(
this)->successors();
1508 case COP_Return:
return cast<Return>(
this)->successors();
1533 return OtherNode.
NodeID > NodeID &&
1534 OtherNode.
NodeID < NodeID + SizeOfSubTree;
1538 return OtherNode.
NodeID >= NodeID &&
1539 OtherNode.
NodeID < NodeID + SizeOfSubTree;
1550 :
SExpr(COP_BasicBlock), Arena(A), CFGPtr(nullptr), BlockID(0),
1551 Visited(0), TermInstr(nullptr) {}
1554 :
SExpr(COP_BasicBlock), Arena(A), CFGPtr(nullptr), BlockID(0),Visited(0),
1555 Args(
std::move(As)), Instrs(
std::move(Is)), TermInstr(T) {}
1591 return DominatorNode.isParentOfOrEqual(Other.DominatorNode);
1595 return PostDominatorNode.isParentOfOrEqual(Other.PostDominatorNode);
1600 Args.reserveCheck(1, Arena);
1605 Instrs.reserveCheck(1, Arena);
1606 Instrs.push_back(V);
1619 void reservePredecessors(
unsigned NumPreds);
1623 auto I = std::find(Predecessors.cbegin(), Predecessors.cend(), BB);
1628 typename V::R_BasicBlock
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1629 typename V::template Container<SExpr*> Nas(Vs, Args.size());
1630 typename V::template Container<SExpr*> Nis(Vs, Instrs.size());
1633 Vs.enterBasicBlock(*
this);
1635 for (
auto *E : Args) {
1636 auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
1639 for (
auto *E : Instrs) {
1640 auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
1643 auto Nt = Vs.traverse(TermInstr, Ctx);
1646 Vs.exitBasicBlock(*
this);
1648 return Vs.reduceBasicBlock(*
this, Nas, Nis, Nt);
1654 return Cmp.comparePointers(
this, E);
1660 int renumberInstrs(
int id);
1663 void computeDominator();
1664 void computePostDominator();
1673 BlockArray Predecessors;
1695 :
SExpr(COP_SCFG), Arena(A), Blocks(A, Nblocks),
1696 Entry(nullptr), Exit(nullptr), NumInstructions(0), Normal(
false) {
1699 auto *V =
new (A)
Phi();
1700 Exit->addArgument(V);
1701 Exit->setTerminator(
new (A)
Return(V));
1706 :
SExpr(COP_SCFG), Arena(Cfg.Arena), Blocks(
std::move(Ba)),
1707 Entry(nullptr), Exit(nullptr), NumInstructions(0), Normal(
false) {
1712 bool valid()
const {
return Entry && Exit && Blocks.size() > 0; }
1719 iterator
begin() {
return Blocks.begin(); }
1720 iterator
end() {
return Blocks.end(); }
1722 const_iterator
begin()
const {
return cbegin(); }
1723 const_iterator
end()
const {
return cend(); }
1725 const_iterator
cbegin()
const {
return Blocks.cbegin(); }
1726 const_iterator
cend()
const {
return Blocks.cend(); }
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 (
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);
1773 void renumberInstrs();
1780 unsigned NumInstructions;
1795 StringRef
name()
const {
return Name; }
1798 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1799 return Vs.reduceIdentifier(*
this);
1804 return Cmp.compareStrings(name(), E->
name());
1819 :
SExpr(COP_IfThenElse), Condition(C), ThenExpr(T), ElseExpr(E)
1822 :
SExpr(I), Condition(C), ThenExpr(T), ElseExpr(E)
1835 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1836 auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx));
1837 auto Nt = Vs.traverse(ThenExpr, Vs.subExprCtx(Ctx));
1838 auto Ne = Vs.traverse(ElseExpr, Vs.subExprCtx(Ctx));
1839 return Vs.reduceIfThenElse(*
this, Nc, Nt, Ne);
1844 typename C::CType Ct = Cmp.compare(condition(), E->
condition());
1845 if (Cmp.notTrue(Ct))
1847 Ct = Cmp.compare(thenExpr(), E->
thenExpr());
1848 if (Cmp.notTrue(Ct))
1850 return Cmp.compare(elseExpr(), E->
elseExpr());
1880 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
1887 return Vs.reduceLet(*
this, Nvd, E1);
1892 typename C::CType Ct =
1894 if (Cmp.notTrue(Ct))
1897 Ct = Cmp.compare(body(), E->
body());
VariableKind kind() const
Return the kind of variable (let, function param, or self)
const Variable * variableDecl() const
BlockArray::const_iterator const_iterator
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
ArrayRef< BasicBlock * > successors() const
static bool classof(const SExpr *E)
const Terminator * terminator() const
StringRef getBinaryOpcodeString(TIL_BinaryOpcode Op)
Return the name of a binary opcode.
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
SimpleArray< SExpr * > InstrArray
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)
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
VarDecl - An instance of this class is created to represent 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.
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)
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.
SimpleArray< SExpr * > ValArray
ValueType(BaseType B, SizeType Sz, bool S, unsigned char VS)
C::CType compare(const Wildcard *E, C &Cmp) const
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
ArrayRef< BasicBlock * > successors()
Return an empty list.
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
SimpleArray< BasicBlock * > BlockArray
void reserveInstructions(unsigned Nins)
const SExpr * sfun() const
Base class for basic block terminators: Branch, Goto, and Return.
Wildcard(const Wildcard &W)
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.
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
const clang::ValueDecl * clangDecl() 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)
Placeholder for expressions that cannot be represented in the TIL.
const clang::CallExpr * clangCallExpr() const
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.
LiteralPtr(const LiteralPtr &R)
const clang::ValueDecl * clangDecl() const
Return the clang declaration for this variable, if any.
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
ValueDecl - Represent the declaration of a variable (in which case it is an lvalue) a function (in wh...
Expr - This represents one expression.
void setTerminator(Terminator *E)
const FunctionProtoType * T
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)
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.
const clang::ValueDecl * clangDecl() const
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)
SimpleArray< BasicBlock * > BlockArray
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
Undefined(const clang::Stmt *S=nullptr)
const SExpr * array() 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)
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)
Literal(const Literal &L)
C::CType compare(const IfThenElse *E, C &Cmp) const
const TIL_BinaryOpcode BOP_Max
const SExpr * index() const
const BasicBlock * parent() const
ArrayRef< BasicBlock * > successors()
Return the list of basic blocks that this terminator can branch to.
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)
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
Project(SExpr *R, const clang::ValueDecl *Cvd)
LiteralPtr(const clang::ValueDecl *D)
const BasicBlock * thenBlock() const
const BasicBlock * targetBlock() const
Variable(SExpr *D, const clang::ValueDecl *Cvd=nullptr)
Identifier(const Identifier &I)
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)
Literal(const clang::Expr *C)
void setClangDecl(const clang::ValueDecl *Cvd)
Set the clang variable associated with this Phi node.
An if-then-else expression.
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
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)
C::CType compare(const Goto *E, C &Cmp) const
C::CType compare(const Let *E, C &Cmp) const
void setClangDecl(const clang::ValueDecl *VD)
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)
const clang::Expr * clangExpr() const
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
Call(SExpr *T, const clang::CallExpr *Ce=nullptr)
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).
const clang::ValueDecl * clangDecl() const
Return the clang declaration of the variable for this Phi node, if any.
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
BlockArray::iterator iterator
static bool classof(const SExpr *E)
const TIL_CastOpcode CAST_Min
Apply(const Apply &A, SExpr *F, SExpr *Ar)
Branch(const Branch &Br, SExpr *C, BasicBlock *T, BasicBlock *E)