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"
171 case 2:
return ST_16;
172 case 4:
return ST_32;
173 case 8:
return ST_64;
175 default:
return ST_0;
182 return ValueType(BT_Void, ST_0,
false, 0);
187 return ValueType(BT_Bool, ST_1,
false, 0);
197 return ValueType(BT_Int, ST_8,
false, 0);
202 return ValueType(BT_Int, ST_16,
true, 0);
207 return ValueType(BT_Int, ST_16,
false, 0);
212 return ValueType(BT_Int, ST_32,
true, 0);
217 return ValueType(BT_Int, ST_32,
false, 0);
222 return ValueType(BT_Int, ST_64,
true, 0);
227 return ValueType(BT_Int, ST_64,
false, 0);
232 return ValueType(BT_Float, ST_32,
true, 0);
237 return ValueType(BT_Float, ST_64,
true, 0);
241 inline ValueType ValueType::getValueType<long double>() {
242 return ValueType(BT_Float, ST_128,
true, 0);
247 return ValueType(BT_String, getSizeType(
sizeof(StringRef)),
false, 0);
252 return ValueType(BT_Pointer, getSizeType(
sizeof(
void*)),
false, 0);
279 return ::operator
new(
S, R);
285 void operator delete(
void *) =
delete;
315 void *
operator new(
size_t) =
delete;
320 namespace ThreadSafetyTIL {
322 unsigned Op = E->
opcode();
323 return Op == COP_Variable || Op == COP_Literal || Op == COP_LiteralPtr;
356 :
SExpr(COP_Variable), Name(s), Definition(D), Cvdecl(nullptr) {
360 :
SExpr(COP_Variable), Name(Cvd ? Cvd->getName() :
"_x"),
361 Definition(D), Cvdecl(Cvd) {
365 :
SExpr(Vd), Name(Vd.Name), Definition(D), Cvdecl(Vd.Cvdecl) {
373 StringRef
name()
const {
return Name; }
390 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
392 return Vs.reduceVariableRef(
this);
397 return Cmp.compareVariableRefs(
this, E);
427 virtual ~
Future() =
delete;
451 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
452 assert(Result &&
"Cannot traverse Future that has not been forced.");
453 return Vs.traverse(Result, Ctx);
458 if (!Result || !E->Result)
459 return Cmp.comparePointers(
this, E);
460 return Cmp.compare(Result, E->Result);
480 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
481 return Vs.reduceUndefined(*
this);
486 return Cmp.trueResult();
490 const clang::Stmt *Cstmt;
502 template <
class V>
typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
503 return Vs.reduceWildcard(*
this);
508 return Cmp.trueResult();
521 :
SExpr(COP_Literal), ValType(
ValueType::getValueType<void>()), Cexpr(C)
538 template <
class V>
typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx);
543 return Cmp.trueResult();
554 class LiteralT :
public Literal {
571 return Vs.reduceLiteral(*
this);
573 switch (ValType.
Base) {
577 return Vs.reduceLiteralT(as<bool>());
579 switch (ValType.
Size) {
582 return Vs.reduceLiteralT(as<int8_t>());
584 return Vs.reduceLiteralT(as<uint8_t>());
587 return Vs.reduceLiteralT(as<int16_t>());
589 return Vs.reduceLiteralT(as<uint16_t>());
592 return Vs.reduceLiteralT(as<int32_t>());
594 return Vs.reduceLiteralT(as<uint32_t>());
597 return Vs.reduceLiteralT(as<int64_t>());
599 return Vs.reduceLiteralT(as<uint64_t>());
605 switch (ValType.
Size) {
607 return Vs.reduceLiteralT(as<float>());
609 return Vs.reduceLiteralT(as<double>());
615 return Vs.reduceLiteralT(as<StringRef>());
617 return Vs.reduceLiteralT(as<void*>());
621 return Vs.reduceLiteral(*
this);
638 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
639 return Vs.reduceLiteralPtr(*
this);
644 return Cmp.comparePointers(Cvdecl, E->Cvdecl);
675 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
680 auto E1 = Vs.
traverse(Body, Vs.declCtx(Ctx));
682 return Vs.reduceFunction(*
this, Nvd, E1);
687 typename C::CType Ct =
692 Ct = Cmp.compare(
body(), E->
body());
712 assert(Vd->Definition ==
nullptr);
714 Vd->Definition =
this;
718 assert(Vd->Definition ==
nullptr);
720 Vd->Definition =
this;
730 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
735 auto E1 = Vs.
traverse(Body, Vs.declCtx(Ctx));
738 return Vs.reduceSFunction(*
this, Nvd, E1);
744 typename C::CType Ct = Cmp.compare(
body(), E->
body());
762 :
SExpr(C), ReturnType(T), Body(B) {}
771 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
772 auto Nt = Vs.traverse(ReturnType, Vs.typeCtx(Ctx));
773 auto Nb = Vs.traverse(Body, Vs.lazyCtx(Ctx));
774 return Vs.reduceCode(*
this, Nt, Nb);
782 return Cmp.compare(
body(), E->
body());
798 :
SExpr(C), Range(R), Body(B) {}
807 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
808 auto Nr = Vs.traverse(Range, Vs.typeCtx(Ctx));
809 auto Nb = Vs.traverse(Body, Vs.lazyCtx(Ctx));
810 return Vs.reduceField(*
this, Nr, Nb);
815 typename C::CType Ct = Cmp.compare(
range(), E->
range());
818 return Cmp.compare(
body(), E->
body());
838 :
SExpr(A), Fun(F), Arg(Ar)
848 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
849 auto Nf = Vs.traverse(Fun, Vs.subExprCtx(Ctx));
850 auto Na = Vs.traverse(Arg, Vs.subExprCtx(Ctx));
851 return Vs.reduceApply(*
this, Nf, Na);
856 typename C::CType Ct = Cmp.compare(
fun(), E->
fun());
859 return Cmp.compare(
arg(), E->
arg());
875 :
SExpr(A), Sfun(Sf), Arg(Ar) {}
881 const SExpr *
arg()
const {
return Arg ? Arg : Sfun; }
886 typename V::R_SExpr
traverse(V &Vs,
typename V::R_Ctx Ctx) {
887 auto Nf = Vs.traverse(Sfun, Vs.subExprCtx(Ctx));
888 typename V::R_SExpr Na = Arg ? Vs.traverse(Arg, Vs.subExprCtx(Ctx))
890 return Vs.reduceSApply(*
this, Nf, Na);
895 typename C::CType Ct = Cmp.compare(
sfun(), E->
sfun());
896 if (Cmp.notTrue(Ct) || (!
arg() && !E->
arg()))
898 return Cmp.compare(
arg(), E->
arg());
913 :
SExpr(COP_Project), Rec(R), SlotName(SName), Cvdecl(nullptr)
916 :
SExpr(COP_Project), Rec(R), SlotName(Cvd->getName()), Cvdecl(Cvd)
919 :
SExpr(P), Rec(R), SlotName(P.SlotName), Cvdecl(P.Cvdecl)
929 if (b)
Flags |= 0x01;
930 else Flags &= 0xFFFE;
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);
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))
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);
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);
1081 if (Cmp.notTrue(Ct))
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))
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))
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 =
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 =
1241 if (Cmp.notTrue(Ct))
1244 if (Cmp.notTrue(Ct))
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 =
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) {}
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;
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();
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) {}
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();
1695 :
SExpr(COP_SCFG), Arena(A), Blocks(A, Nblocks),
1696 Entry(nullptr), Exit(nullptr), NumInstructions(0), Normal(
false) {
1699 auto *V =
new (A)
Phi();
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; }
1743 assert(BB->CFGPtr ==
nullptr);
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);
1845 if (Cmp.notTrue(Ct))
1848 if (Cmp.notTrue(Ct))
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());
Project(const Project &P, SExpr *R)
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)
C::CType compare(const Return *E, C &Cmp) const
Apply a self-argument to a self-applicable function.
const clang::CallExpr * clangCallExpr() const
StringRef getName() const
getName - Get the name of identifier for this declaration as a StringRef.
ArrayRef< BasicBlock * > successors()
Pointer arithmetic, restricted to arrays only.
static bool classof(const SExpr *E)
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.
size_t numSuccessors() 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.
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
C::CType compare(const SCFG *E, C &Cmp) const
SimpleArray< SExpr * > InstrArray
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
BlockArray & predecessors()
Returns a list of predecessors.
ArrayAdd(SExpr *A, SExpr *N)
const SExpr * sfun() const
const SExpr * target() const
void setID(BasicBlock *B, unsigned id)
Set the basic block and instruction ID for this expression.
static bool classof(const SExpr *E)
C::CType compare(const BinaryOp *E, C &Cmp) const
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)
const ValArray & values() const
const SExpr * arg() const
static bool classof(const SExpr *E)
C::CType compare(const IfThenElse *E, C &Cmp) const
const TIL_BinaryOpcode BOP_Min
bool isParentOf(const TopologyNode &OtherNode)
static bool classof(const SExpr *E)
const BasicBlock * parent() const
C::CType compare(const Phi *E, C &Cmp) const
const Variable * variableDecl() const
SFunction(const SFunction &F, Variable *Vd, SExpr *B)
size_t numBlocks() const
Return the number of blocks in the CFG.
Cast(const Cast &C, SExpr *E)
static bool classof(const SExpr *E)
const_iterator cend() const
Function(Variable *Vd, SExpr *Bd)
C::CType compare(const ArrayIndex *E, C &Cmp) const
Undefined(const Undefined &U)
float __ovld __cnfn distance(float p0, float p1)
Returns the distance between p0 and p1.
const_iterator cbegin() const
BasicBlock(BasicBlock &B, MemRegionRef A, InstrArray &&As, InstrArray &&Is, Terminator *T)
C::CType compare(const Store *E, C &Cmp) const
SExpr * simplifyToCanonicalVal(SExpr *E)
ArrayAdd(const ArrayAdd &E, SExpr *A, SExpr *N)
VarDecl - An instance of this class is created to represent a variable declaration or definition...
Variable(StringRef s, SExpr *D=nullptr)
const Variable * variableDecl() const
const TIL_UnaryOpcode UOP_Max
bool normal() const
Return true if this CFG has been normalized.
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
ArrayIndex(const ArrayIndex &E, SExpr *A, SExpr *N)
Variable * variableDecl()
unsigned addPredecessor(BasicBlock *Pred)
If p is a reference to an array, then p[i] is a reference to the i'th element of the array...
const SExpr * elseExpr() const
unsigned numInstructions()
Return the total number of instructions in the CFG.
Field(SExpr *R, SExpr *B)
const SExpr * index() const
const SExpr * returnValue() const
SCFG(MemRegionRef A, unsigned Nblocks)
static bool classof(const SExpr *E)
Phi(const Phi &P, ValArray &&Vs)
InstrArray & instructions()
class LLVM_ALIGNAS(8) DependentTemplateSpecializationType const IdentifierInfo * Name
Represents a template specialization type whose template cannot be resolved, e.g. ...
Project a named slot from a C++ struct or class.
void push_back(const T &Elem)
SimpleArray< SExpr * > ValArray
ValueType(BaseType B, SizeType Sz, bool S, unsigned char VS)
const SExpr * condition() const
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
static bool classof(const SExpr *E)
SApply(SApply &A, SExpr *Sf, SExpr *Ar=nullptr)
const BlockArray & predecessors() const
const SExpr * body() const
C::CType compare(const UnaryOp *E, C &Cmp) const
ArrayRef< BasicBlock * > successors()
Return an empty list.
This declaration is definitely a definition.
Cast(TIL_CastOpcode Op, SExpr *E)
static bool classof(const SExpr *E)
SimpleArray< BasicBlock * > BlockArray
void reserveInstructions(unsigned Nins)
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)
const SExpr * pointer() const
const SExpr * expr() const
static bool classof(const SExpr *E)
static bool classof(const SExpr *E)
C::CType compare(const Branch *E, C &Cmp) const
static bool classof(const SExpr *E)
const BasicBlock * entry() const
ArrayRef< BasicBlock * > successors()
Return the list of basic blocks that this terminator can branch to.
virtual SExpr * compute()
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
Terminator(const SExpr &E)
C::CType compare(const Wildcard *E, C &Cmp) const
Branch(SExpr *C, BasicBlock *T, BasicBlock *E)
C::CType compare(const LiteralPtr *E, C &Cmp) const
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)
const SExpr * array() const
A basic block is part of an SCFG.
C::CType compare(const Let *E, C &Cmp) const
void setDefinition(SExpr *E)
void setEntry(BasicBlock *BB)
unsigned findPredecessorIndex(const BasicBlock *BB) const
Return the index of BB, or Predecessors.size if BB is not a predecessor.
const BasicBlock * exit() const
detail::InMemoryDirectory::const_iterator I
Placeholder for expressions that cannot be represented in the TIL.
const InstrArray & instructions() const
A self-applicable function.
void addInstruction(SExpr *V)
Add a new instruction.
static bool classof(const SExpr *E)
An SCFG is a control-flow graph.
TIL_Opcode
Enum for the different distinct classes of SExpr.
TIL_Opcode opcode() const
LiteralPtr(const LiteralPtr &R)
Goto(const Goto &G, BasicBlock *B, unsigned I)
const SExpr * body() const
const SExpr * body() 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.
const Variable * variableDecl() const
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
Apply an argument to a function.
StringRef getUnaryOpcodeString(TIL_UnaryOpcode Op)
Return the name of a unary opcode.
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)
unsigned id() const
Returns the instruction ID for this expression.
C::CType compare(const BasicBlock *E, C &Cmp) const
const InstrArray & arguments() const
C::CType compare(const Project *E, C &Cmp) const
const clang::Expr * clangExpr() const
Apply(SExpr *F, SExpr *A)
const unsigned char Opcode
C::CType compare(const Call *E, C &Cmp) const
static bool classof(const SExpr *E)
C::CType compare(const Field *E, C &Cmp) const
C::CType compare(const Undefined *E, C &Cmp) const
static bool classof(const SExpr *E)
C::CType compare(const Variable *E, C &Cmp) const
ValueType valueType() 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.
ArrayRef< BasicBlock * > successors() const
C::CType compare(const Cast *E, C &Cmp) 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)
StringRef name() const
Return the name of the variable, if any.
SimpleArray< BasicBlock * > BlockArray
static bool classof(const SExpr *E)
Undefined(const clang::Stmt *S=nullptr)
const SExpr * expr1() const
Let(const Let &L, Variable *Vd, SExpr *Bd)
bool PostDominates(const BasicBlock &Other)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
const SExpr * body() const
const SExpr * returnType() const
bool Dominates(const BasicBlock &Other)
BasicBlock * block() const
Returns the block, if this is an instruction in a basic block, otherwise returns null.
TIL_BinaryOpcode
Opcode for binary arithmetic operations.
const SExpr * index() const
Call(const Call &C, SExpr *T)
const Terminator * terminator() const
static bool classof(const SExpr *E)
void reservePredecessors(unsigned NumPreds)
static SizeType getSizeType(unsigned nbytes)
Literal(const Literal &L)
TIL_BinaryOpcode binaryOpcode() const
const TIL_BinaryOpcode BOP_Max
ArrayRef< BasicBlock * > successors()
Return the list of basic blocks that this terminator can branch to.
const SExpr * arg() const
static bool classof(const SExpr *E)
const clang::ValueDecl * clangDecl() const
const SExpr * definition() const
TIL_UnaryOpcode
Opcode for unary arithmetic operations.
BasicBlock(MemRegionRef A)
const SExpr * dataType() const
const SExpr * getCanonicalVal(const SExpr *E)
const TIL_UnaryOpcode UOP_Min
bool isDelegation() const
void setKind(VariableKind K)
const TIL_CastOpcode CAST_Max
Function(const Function &F, Variable *Vd, SExpr *Bd)
Store(SExpr *P, SExpr *V)
const LiteralT< T > & as() const
Terminator * terminator()
static bool classof(const SExpr *E)
Phi(MemRegionRef A, unsigned Nvals)
const SExpr * body() const
size_t numPredecessors() const
Returns the number of predecessors.
const clang::ValueDecl * clangDecl() const
Placeholder for a wildcard that matches any other expression.
TIL_CastOpcode
Opcode for cast operations.
static bool classof(const SExpr *E)
unsigned index() const
Returns the index into the.
TIL_UnaryOpcode unaryOpcode() const
LiteralT(const LiteralT< T > &L)
void reserveCheck(size_t N, MemRegionRef A)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
Variable(const Variable &Vd, SExpr *D)
const BasicBlock * targetBlock() const
SFunction(Variable *Vd, SExpr *B)
Project(SExpr *R, const clang::ValueDecl *Cvd)
LiteralPtr(const clang::ValueDecl *D)
C::CType compare(const Apply *E, C &Cmp) const
Variable(SExpr *D, const clang::ValueDecl *Cvd=nullptr)
C::CType compare(const Load *E, C &Cmp) const
Project(SExpr *R, StringRef SName)
StringRef slotName() const
Identifier(const Identifier &I)
Load a value from memory.
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
const_iterator cend() const
const_iterator cbegin() const
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)
int blockID() const
Returns the block ID. Every block has a unique ID in the CFG.
bool valid() const
Return true if this CFG is valid.
static bool classof(const SExpr *E)
Literal(const clang::Expr *C)
C::CType compare(const Code *E, C &Cmp) const
const SExpr * source() const
C::CType compare(const Alloc *E, C &Cmp) const
void setClangDecl(const clang::ValueDecl *Cvd)
Set the clang variable associated with this Phi node.
An if-then-else expression.
C::CType compare(const Identifier *E, C &Cmp) const
Variable * variableDecl()
detail::InMemoryDirectory::const_iterator E
SApply(SExpr *Sf, SExpr *A=nullptr)
Goto(BasicBlock *B, unsigned I)
static bool classof(const SExpr *E)
SExpr * maybeGetResult() 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)
const clang::ValueDecl * clangDecl() const
Return the clang declaration of the variable for this Phi node, if any.
static bool classof(const SExpr *E)
Phi Node, for code in SSA form.
C::CType compare(const Goto *E, C &Cmp) const
const BasicBlock * thenBlock() const
const SExpr * array() const
C::CType compare(const Function *E, C &Cmp) const
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 SExpr * record() const
const clang::ValueDecl * clangDecl() const
Return the clang declaration for this variable, if any.
void setClangDecl(const clang::ValueDecl *VD)
const_iterator end() const
const BasicBlock * elseBlock() const
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
const SExpr * expr() const
SExpr * definition()
Return the definition of the variable.
const SExpr * expr0() const
VariableKind kind() const
Return the kind of variable (let, function param, or self)
Alloc(const Alloc &A, SExpr *Dt)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
TIL_CastOpcode castOpcode() const
void reserve(size_t Ncp, MemRegionRef A)
C::CType compare(const Literal *E, C &Cmp) const
SCFG(const SCFG &Cfg, BlockArray &&Ba)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
ArrayRef< BasicBlock * > successors() const
const SExpr * destination() const
static bool classof(const SExpr *E)
bool isTrivial(const SExpr *E)
static bool classof(const SExpr *E)
Terminator(TIL_Opcode Op)
void simplifyIncompleteArg(til::Phi *Ph)
const_iterator begin() const
const SExpr * range() const
BasicBlock * targetBlock()
const SExpr * fun() const
Code(const Code &C, SExpr *T, SExpr *B)
void setExit(BasicBlock *BB)
C::CType compare(const SFunction *E, C &Cmp) const
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
static bool classof(const SExpr *E)
const SExpr * condition() const
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 ArrayAdd *E, C &Cmp) const
Call(SExpr *T, const clang::CallExpr *Ce=nullptr)
C::CType compare(const SApply *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.
Call a function (after all arguments have been applied).
Variable * variableDecl()
const SExpr * thenExpr() const
Alloc(SExpr *D, AllocKind K)
SFunction (self) parameter.
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
C::CType compare(const Future *E, C &Cmp) 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)