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/StringRef.h"
54#include "llvm/Support/Casting.h"
55#include "llvm/Support/Compiler.h"
56#include "llvm/Support/raw_ostream.h"
79#define TIL_OPCODE_DEF(X) COP_##X,
80#include "ThreadSafetyOps.def"
177 inline static SizeType
getSizeType(
unsigned nbytes);
193 case 2:
return ST_16;
194 case 4:
return ST_32;
195 case 8:
return ST_64;
197 default:
return ST_0;
298 return ::operator
new(S, R);
307 void operator delete(
void *) =
delete;
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);
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);
500 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
501 return Vs.reduceUndefined(*
this);
506 return Cmp.trueResult();
521 template <
class V>
typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
522 return Vs.reduceWildcard(*
this);
527 return Cmp.trueResult();
531template <
class T>
class LiteralT;
537 :
SExpr(COP_Literal), ValType(
ValueType::getValueType<void>()), Cexpr(
C) {}
555 template <
class V>
typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx);
560 return Cmp.trueResult();
565 const Expr *Cexpr =
nullptr;
589 return Vs.reduceLiteral(*
this);
591 switch (ValType.Base) {
595 return Vs.reduceLiteralT(
as<bool>());
597 switch (ValType.Size) {
623 switch (ValType.Size) {
639 return Vs.reduceLiteral(*
this);
656 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
657 return Vs.reduceLiteralPtr(*
this);
662 if (!Cvdecl || !E->Cvdecl)
663 return Cmp.comparePointers(
this, E);
664 return Cmp.comparePointers(Cvdecl, E->Cvdecl);
677 :
SExpr(COP_Function), VarDecl(Vd), Body(Bd) {
682 :
SExpr(F), VarDecl(Vd), Body(Bd) {
695 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
697 auto E0 = Vs.traverse(VarDecl->Definition, Vs.typeCtx(Ctx));
699 Variable *Nvd = Vs.enterScope(*VarDecl, E0);
700 auto E1 = Vs.
traverse(Body, Vs.declCtx(Ctx));
701 Vs.exitScope(*VarDecl);
702 return Vs.reduceFunction(*
this, Nvd, E1);
707 typename C::CType Ct =
708 Cmp.compare(VarDecl->definition(), E->VarDecl->
definition());
712 Ct = Cmp.compare(
body(), E->
body());
728 :
SExpr(COP_SFunction), VarDecl(Vd), Body(B) {
729 assert(Vd->Definition ==
nullptr);
731 Vd->Definition =
this;
735 :
SExpr(F), VarDecl(Vd), Body(B) {
736 assert(Vd->Definition ==
nullptr);
738 Vd->Definition =
this;
750 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
754 Variable *Nvd = Vs.enterScope(*VarDecl,
nullptr);
755 auto E1 = Vs.
traverse(Body, Vs.declCtx(Ctx));
756 Vs.exitScope(*VarDecl);
758 return Vs.reduceSFunction(*
this, Nvd, E1);
764 typename C::CType Ct = Cmp.compare(
body(), E->
body());
779 :
SExpr(
C), ReturnType(
T), Body(B) {}
790 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
791 auto Nt = Vs.traverse(ReturnType, Vs.typeCtx(Ctx));
792 auto Nb = Vs.traverse(Body, Vs.lazyCtx(Ctx));
793 return Vs.reduceCode(*
this, Nt, Nb);
801 return Cmp.compare(
body(), E->
body());
814 :
SExpr(
C), Range(R), Body(B) {}
825 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
826 auto Nr = Vs.traverse(Range, Vs.typeCtx(Ctx));
827 auto Nb = Vs.traverse(Body, Vs.lazyCtx(Ctx));
828 return Vs.reduceField(*
this, Nr, Nb);
833 typename C::CType Ct = Cmp.compare(
range(), E->
range());
836 return Cmp.compare(
body(), E->
body());
853 :
SExpr(A), Fun(F), Arg(Ar) {}
864 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
865 auto Nf = Vs.traverse(Fun, Vs.subExprCtx(Ctx));
866 auto Na = Vs.traverse(Arg, Vs.subExprCtx(Ctx));
867 return Vs.reduceApply(*
this, Nf, Na);
872 typename C::CType Ct = Cmp.compare(
fun(), E->
fun());
875 return Cmp.compare(
arg(), E->
arg());
888 :
SExpr(A), Sfun(Sf), Arg(Ar) {}
896 const SExpr *
arg()
const {
return Arg ? Arg : Sfun; }
901 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
902 auto Nf = Vs.traverse(Sfun, Vs.subExprCtx(Ctx));
903 typename V::R_SExpr Na = Arg ? Vs.traverse(Arg, Vs.subExprCtx(Ctx))
905 return Vs.reduceSApply(*
this, Nf, Na);
910 typename C::CType Ct = Cmp.compare(
sfun(), E->
sfun());
911 if (Cmp.notTrue(Ct) || (!
arg() && !E->
arg()))
913 return Cmp.compare(
arg(), E->
arg());
925 :
SExpr(COP_Project), Rec(R), Cvdecl(Cvd) {
926 assert(Cvd &&
"ValueDecl must not be null");
940 else Flags &= 0xFFFE;
944 if (Cvdecl->getDeclName().isIdentifier())
945 return Cvdecl->getName();
948 llvm::raw_string_ostream OS(*SlotName);
949 Cvdecl->printName(OS);
955 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
956 auto Nr = Vs.traverse(Rec, Vs.subExprCtx(Ctx));
957 return Vs.reduceProject(*
this, Nr);
962 typename C::CType Ct = Cmp.compare(
record(), E->
record());
965 return Cmp.comparePointers(Cvdecl, E->Cvdecl);
970 mutable std::optional<std::string> SlotName;
978 :
SExpr(COP_Call), Target(
T), Cexpr(Ce) {}
989 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
990 auto Nt = Vs.traverse(Target, Vs.subExprCtx(Ctx));
991 return Vs.reduceCall(*
this, Nt);
1023 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1024 auto Nd = Vs.traverse(Dtype, Vs.declCtx(Ctx));
1025 return Vs.reduceAlloc(*
this, Nd);
1030 typename C::CType Ct = Cmp.compareIntegers(
kind(), E->
kind());
1031 if (Cmp.notTrue(Ct))
1052 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1053 auto Np = Vs.traverse(Ptr, Vs.subExprCtx(Ctx));
1054 return Vs.reduceLoad(*
this, Np);
1082 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1083 auto Np = Vs.traverse(Dest, Vs.subExprCtx(Ctx));
1084 auto Nv = Vs.traverse(Source, Vs.subExprCtx(Ctx));
1085 return Vs.reduceStore(*
this, Np, Nv);
1091 if (Cmp.notTrue(Ct))
1107 :
SExpr(E), Array(A), Index(N) {}
1118 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1119 auto Na = Vs.traverse(Array, Vs.subExprCtx(Ctx));
1120 auto Ni = Vs.traverse(Index, Vs.subExprCtx(Ctx));
1121 return Vs.reduceArrayIndex(*
this, Na, Ni);
1126 typename C::CType Ct = Cmp.compare(
array(), E->
array());
1127 if (Cmp.notTrue(Ct))
1144 :
SExpr(E), Array(A), Index(N) {}
1155 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1156 auto Na = Vs.traverse(Array, Vs.subExprCtx(Ctx));
1157 auto Ni = Vs.traverse(Index, Vs.subExprCtx(Ctx));
1158 return Vs.reduceArrayAdd(*
this, Na, Ni);
1163 typename C::CType Ct = Cmp.compare(
array(), E->
array());
1164 if (Cmp.notTrue(Ct))
1194 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1195 auto Ne = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
1196 return Vs.reduceUnaryOp(*
this,
Ne);
1201 typename C::CType Ct =
1203 if (Cmp.notTrue(Ct))
1205 return Cmp.compare(
expr(), E->
expr());
1217 :
SExpr(COP_BinaryOp), Expr0(E0), Expr1(E1) {
1222 :
SExpr(B), Expr0(E0), Expr1(E1) {
1239 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1240 auto Ne0 = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
1241 auto Ne1 = Vs.traverse(Expr1, Vs.subExprCtx(Ctx));
1242 return Vs.reduceBinaryOp(*
this, Ne0, Ne1);
1247 typename C::CType Ct =
1249 if (Cmp.notTrue(Ct))
1252 if (Cmp.notTrue(Ct))
1280 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1281 auto Ne = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
1282 return Vs.reduceCast(*
this,
Ne);
1287 typename C::CType Ct =
1289 if (Cmp.notTrue(Ct))
1291 return Cmp.compare(
expr(), E->
expr());
1335 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1336 typename V::template Container<typename V::R_SExpr>
1337 Nvs(Vs, Values.size());
1339 for (
const auto *Val : Values)
1340 Nvs.push_back( Vs.traverse(Val, Vs.subExprCtx(Ctx)) );
1341 return Vs.reducePhi(*
this, Nvs);
1347 return Cmp.comparePointers(
this, E);
1363 return E->
opcode() >= COP_Goto && E->
opcode() <= COP_Return;
1378 :
Terminator(COP_Goto), TargetBlock(B), Index(I) {}
1380 :
Terminator(COP_Goto), TargetBlock(B), Index(I) {}
1388 unsigned index()
const {
return Index; }
1394 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1395 BasicBlock *Ntb = Vs.reduceBasicBlockRef(TargetBlock);
1396 return Vs.reduceGoto(*
this, Ntb);
1402 return Cmp.comparePointers(
this, E);
1442 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1443 auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx));
1444 BasicBlock *Ntb = Vs.reduceBasicBlockRef(Branches[0]);
1445 BasicBlock *Nte = Vs.reduceBasicBlockRef(Branches[1]);
1446 return Vs.reduceBranch(*
this, Nc, Ntb, Nte);
1452 return Cmp.comparePointers(
this, E);
1476 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1477 auto Ne = Vs.traverse(Retval, Vs.subExprCtx(Ctx));
1478 return Vs.reduceReturn(*
this,
Ne);
1483 return Cmp.compare(Retval, E->Retval);
1492 case COP_Goto:
return cast<Goto>(
this)->successors();
1493 case COP_Branch:
return cast<Branch>(
this)->successors();
1494 case COP_Return:
return cast<Return>(
this)->successors();
1537 :
SExpr(COP_BasicBlock), Arena(A), BlockID(0), Visited(
false) {}
1540 :
SExpr(COP_BasicBlock), Arena(A), BlockID(0), Visited(
false),
1541 Args(
std::move(As)), Instrs(
std::move(Is)), TermInstr(
T) {}
1579 return DominatorNode.isParentOfOrEqual(
Other.DominatorNode);
1583 return PostDominatorNode.isParentOfOrEqual(
Other.PostDominatorNode);
1588 Args.reserveCheck(1, Arena);
1594 Instrs.reserveCheck(1, Arena);
1595 Instrs.push_back(
V);
1613 auto I = llvm::find(Predecessors, BB);
1614 return std::distance(Predecessors.cbegin(), I);
1618 typename V::R_BasicBlock
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1619 typename V::template Container<SExpr*> Nas(Vs, Args.size());
1620 typename V::template Container<SExpr*> Nis(Vs, Instrs.size());
1623 Vs.enterBasicBlock(*
this);
1625 for (
const auto *E : Args) {
1626 auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
1629 for (
const auto *E : Instrs) {
1630 auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
1633 auto Nt = Vs.traverse(TermInstr, Ctx);
1636 Vs.exitBasicBlock(*
this);
1638 return Vs.reduceBasicBlock(*
this, Nas, Nis, Nt);
1644 return Cmp.comparePointers(
this, E);
1651 unsigned renumberInstrs(
unsigned id);
1655 void computeDominator();
1656 void computePostDominator();
1662 SCFG *CFGPtr =
nullptr;
1665 unsigned BlockID : 31;
1668 LLVM_PREFERRED_TYPE(
bool)
1669 unsigned Visited : 1;
1700 :
SExpr(COP_SCFG), Arena(A), Blocks(A, Nblocks) {
1703 auto *
V =
new (A)
Phi();
1704 Exit->addArgument(
V);
1705 Exit->setTerminator(
new (A)
Return(
V));
1711 :
SExpr(COP_SCFG), Arena(Cfg.Arena), Blocks(
std::move(Ba)) {
1718 bool valid()
const {
return Entry && Exit && Blocks.size() > 0; }
1749 assert(BB->CFGPtr ==
nullptr);
1751 Blocks.reserveCheck(1, Arena);
1752 Blocks.push_back(BB);
1761 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1763 typename V::template Container<BasicBlock *> Bbs(Vs, Blocks.size());
1765 for (
const auto *B : Blocks) {
1766 Bbs.push_back( B->traverse(Vs, Vs.subExprCtx(Ctx)) );
1769 return Vs.reduceSCFG(*
this, Bbs);
1775 return Cmp.comparePointers(
this, E);
1780 void renumberInstrs();
1786 unsigned NumInstructions = 0;
1799 StringRef
name()
const {
return Name; }
1802 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1803 return Vs.reduceIdentifier(*
this);
1808 return Cmp.compareStrings(
name(), E->
name());
1820 :
SExpr(COP_IfThenElse), Condition(
C), ThenExpr(
T), ElseExpr(E) {}
1822 :
SExpr(I), Condition(
C), ThenExpr(
T), ElseExpr(E) {}
1836 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1837 auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx));
1838 auto Nt = Vs.traverse(ThenExpr, Vs.subExprCtx(Ctx));
1839 auto Ne = Vs.traverse(ElseExpr, Vs.subExprCtx(Ctx));
1840 return Vs.reduceIfThenElse(*
this, Nc, Nt,
Ne);
1846 if (Cmp.notTrue(Ct))
1849 if (Cmp.notTrue(Ct))
1881 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1883 auto E0 = Vs.traverse(VarDecl->Definition, Vs.subExprCtx(Ctx));
1885 Variable *Nvd = Vs.enterScope(*VarDecl, E0);
1887 Vs.exitScope(*VarDecl);
1888 return Vs.reduceLet(*
this, Nvd, E1);
1893 typename C::CType Ct =
1894 Cmp.compare(VarDecl->definition(), E->VarDecl->
definition());
1895 if (Cmp.notTrue(Ct))
1898 Ct = Cmp.compare(
body(), E->
body());
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
__device__ __2f16 float __ockl_bool s
__SIZE_TYPE__ size_t
The unsigned integer type of the result of the sizeof operator.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
This represents one expression.
Stmt - This represents one statement.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
static bool classof(const SExpr *E)
Alloc(const Alloc &A, SExpr *Dt)
C::CType compare(const Alloc *E, C &Cmp) const
Alloc(SExpr *D, AllocKind K)
const SExpr * dataType() const
const SExpr * arg() const
Apply(const Apply &A, SExpr *F, SExpr *Ar)
Apply(SExpr *F, SExpr *A)
const SExpr * fun() const
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
static bool classof(const SExpr *E)
C::CType compare(const Apply *E, C &Cmp) const
const SExpr * array() const
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
ArrayAdd(SExpr *A, SExpr *N)
ArrayAdd(const ArrayAdd &E, SExpr *A, SExpr *N)
C::CType compare(const ArrayAdd *E, C &Cmp) const
const SExpr * index() const
static bool classof(const SExpr *E)
ArrayIndex(const ArrayIndex &E, SExpr *A, SExpr *N)
static bool classof(const SExpr *E)
ArrayIndex(SExpr *A, SExpr *N)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
C::CType compare(const ArrayIndex *E, C &Cmp) const
const SExpr * array() const
const SExpr * index() const
A basic block is part of an SCFG.
unsigned addPredecessor(BasicBlock *Pred)
BasicBlock(BasicBlock &B, MemRegionRef A, InstrArray &&As, InstrArray &&Is, Terminator *T)
int blockID() const
Returns the block ID. Every block has a unique ID in the CFG.
const InstrArray & arguments() const
const InstrArray & instructions() const
bool Dominates(const BasicBlock &Other)
void reserveInstructions(unsigned Nins)
SimpleArray< BasicBlock * > BlockArray
const Terminator * terminator() const
const BlockArray & predecessors() const
size_t numSuccessors() const
ArrayRef< BasicBlock * > successors() const
void reserveArguments(unsigned Nargs)
C::CType compare(const BasicBlock *E, C &Cmp) const
ArrayRef< BasicBlock * > successors()
void addArgument(Phi *V)
Add a new argument.
Terminator * terminator()
size_t numPredecessors() const
Returns the number of predecessors.
bool PostDominates(const BasicBlock &Other)
BasicBlock(MemRegionRef A)
V::R_BasicBlock traverse(V &Vs, typename V::R_Ctx Ctx)
static bool classof(const SExpr *E)
InstrArray & instructions()
void reservePredecessors(unsigned NumPreds)
unsigned findPredecessorIndex(const BasicBlock *BB) const
Return the index of BB, or Predecessors.size if BB is not a predecessor.
void setTerminator(Terminator *E)
BlockArray & predecessors()
Returns a list of predecessors.
SimpleArray< SExpr * > InstrArray
const BasicBlock * parent() const
void addInstruction(SExpr *V)
Add a new instruction.
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
BinaryOp(TIL_BinaryOpcode Op, SExpr *E0, SExpr *E1)
const SExpr * expr0() const
static bool classof(const SExpr *E)
BinaryOp(const BinaryOp &B, SExpr *E0, SExpr *E1)
TIL_BinaryOpcode binaryOpcode() const
C::CType compare(const BinaryOp *E, C &Cmp) const
const SExpr * expr1() const
const SExpr * condition() const
Branch(SExpr *C, BasicBlock *T, BasicBlock *E)
const BasicBlock * elseBlock() const
C::CType compare(const Branch *E, C &Cmp) const
Branch(const Branch &Br, SExpr *C, BasicBlock *T, BasicBlock *E)
static bool classof(const SExpr *E)
ArrayRef< BasicBlock * > successors() const
Return the list of basic blocks that this terminator can branch to.
const BasicBlock * thenBlock() const
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
const SExpr * target() const
Call(const Call &C, SExpr *T)
Call(SExpr *T, const CallExpr *Ce=nullptr)
C::CType compare(const Call *E, C &Cmp) const
static bool classof(const SExpr *E)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
const CallExpr * clangCallExpr() const
C::CType compare(const Cast *E, C &Cmp) const
const SExpr * expr() const
Cast(TIL_CastOpcode Op, SExpr *E)
static bool classof(const SExpr *E)
Cast(const Cast &C, SExpr *E)
TIL_CastOpcode castOpcode() const
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)
const SExpr * returnType() const
C::CType compare(const Code *E, C &Cmp) const
const SExpr * body() const
Code(const Code &C, SExpr *T, SExpr *B)
const SExpr * range() const
const SExpr * body() const
static bool classof(const SExpr *E)
Field(SExpr *R, SExpr *B)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
C::CType compare(const Field *E, C &Cmp) const
Field(const Field &C, SExpr *R, SExpr *B)
const SExpr * body() const
Function(const Function &F, Variable *Vd, SExpr *Bd)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
const Variable * variableDecl() const
C::CType compare(const Function *E, C &Cmp) const
static bool classof(const SExpr *E)
Variable * variableDecl()
Function(Variable *Vd, SExpr *Bd)
C::CType compare(const Future *E, C &Cmp) const
static bool classof(const SExpr *E)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
SExpr * maybeGetResult() const
virtual SExpr * compute()
BasicBlock * targetBlock()
ArrayRef< BasicBlock * > successors() const
Return the list of basic blocks that this terminator can branch to.
Goto(const Goto &G, BasicBlock *B, unsigned I)
C::CType compare(const Goto *E, C &Cmp) const
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
Goto(BasicBlock *B, unsigned I)
unsigned index() const
Returns the index into the.
static bool classof(const SExpr *E)
const BasicBlock * targetBlock() const
C::CType compare(const Identifier *E, C &Cmp) const
Identifier(const Identifier &)=default
static bool classof(const SExpr *E)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
const SExpr * condition() const
IfThenElse(const IfThenElse &I, SExpr *C, SExpr *T, SExpr *E)
const SExpr * thenExpr() const
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
C::CType compare(const IfThenElse *E, C &Cmp) const
static bool classof(const SExpr *E)
const SExpr * elseExpr() const
IfThenElse(SExpr *C, SExpr *T, SExpr *E)
Let(const Let &L, Variable *Vd, SExpr *Bd)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
const Variable * variableDecl() const
C::CType compare(const Let *E, C &Cmp) const
Let(Variable *Vd, SExpr *Bd)
static bool classof(const SExpr *E)
const SExpr * body() const
Variable * variableDecl()
const ValueDecl * clangDecl() const
C::CType compare(const LiteralPtr *E, C &Cmp) const
LiteralPtr(const LiteralPtr &)=default
void setClangDecl(const ValueDecl *VD)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
LiteralPtr(const ValueDecl *D)
static bool classof(const SExpr *E)
LiteralT & operator=(const LiteralT< T > &)=delete
LiteralT(const LiteralT< T > &L)
Literal(const Literal &)=default
static bool classof(const SExpr *E)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
const LiteralT< T > & as() const
ValueType valueType() const
C::CType compare(const Literal *E, C &Cmp) const
const Expr * clangExpr() const
const SExpr * pointer() const
C::CType compare(const Load *E, C &Cmp) const
static bool classof(const SExpr *E)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
Load(const Load &L, SExpr *P)
Phi Node, for code in SSA form.
SimpleArray< SExpr * > ValArray
static bool classof(const SExpr *E)
C::CType compare(const Phi *E, C &Cmp) const
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
const ValueDecl * clangDecl() const
Return the clang declaration of the variable for this Phi node, if any.
void setClangDecl(const ValueDecl *Cvd)
Set the clang variable associated with this Phi node.
Phi(MemRegionRef A, unsigned Nvals)
Phi(const Phi &P, ValArray &&Vs)
const ValArray & values() const
const ValueDecl * clangDecl() const
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
const SExpr * record() const
static bool classof(const SExpr *E)
C::CType compare(const Project *E, C &Cmp) const
Project(SExpr *R, const ValueDecl *Cvd)
StringRef slotName() const
Return from the enclosing function, passing the return value to the caller.
Return(const Return &R, SExpr *Rval)
const SExpr * returnValue() const
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
ArrayRef< BasicBlock * > successors() const
Return an empty list.
static bool classof(const SExpr *E)
C::CType compare(const Return *E, C &Cmp) const
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
const SExpr * sfun() const
bool isDelegation() const
SApply(SExpr *Sf, SExpr *A=nullptr)
const SExpr * arg() const
C::CType compare(const SApply *E, C &Cmp) const
SApply(SApply &A, SExpr *Sf, SExpr *Ar=nullptr)
static bool classof(const SExpr *E)
An SCFG is a control-flow graph.
void setEntry(BasicBlock *BB)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
const BasicBlock * entry() const
BlockArray::iterator iterator
void setExit(BasicBlock *BB)
C::CType compare(const SCFG *E, C &Cmp) const
bool normal() const
Return true if this CFG has been normalized.
static bool classof(const SExpr *E)
SCFG(MemRegionRef A, unsigned Nblocks)
const_iterator begin() const
const_iterator end() const
const_iterator cend() const
const BasicBlock * exit() const
BlockArray::const_iterator const_iterator
const_iterator cbegin() const
unsigned numInstructions()
Return the total number of instructions in the CFG.
size_t numBlocks() const
Return the number of blocks in the CFG.
bool valid() const
Return true if this CFG is valid.
SimpleArray< BasicBlock * > BlockArray
Base class for AST nodes in the typed intermediate language.
BasicBlock * block() const
Returns the block, if this is an instruction in a basic block, otherwise returns null.
void setID(BasicBlock *B, unsigned id)
Set the basic block and instruction ID for this expression.
SExpr & operator=(const SExpr &)=delete
TIL_Opcode opcode() const
unsigned id() const
Returns the instruction ID for this expression.
static bool classof(const SExpr *E)
Variable * variableDecl()
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
SFunction(Variable *Vd, SExpr *B)
SFunction(const SFunction &F, Variable *Vd, SExpr *B)
const Variable * variableDecl() const
const SExpr * body() const
C::CType compare(const SFunction *E, C &Cmp) const
const BasicBlock ** const_iterator
Store(SExpr *P, SExpr *V)
C::CType compare(const Store *E, C &Cmp) const
const SExpr * destination() const
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
Store(const Store &S, SExpr *P, SExpr *V)
const SExpr * source() const
static bool classof(const SExpr *E)
Base class for basic block terminators: Branch, Goto, and Return.
ArrayRef< BasicBlock * > successors() const
Return the list of basic blocks that this terminator can branch to.
Terminator(const SExpr &E)
static bool classof(const SExpr *E)
Terminator(TIL_Opcode Op)
static bool classof(const SExpr *E)
const SExpr * expr() const
UnaryOp(const UnaryOp &U, SExpr *E)
TIL_UnaryOpcode unaryOpcode() const
C::CType compare(const UnaryOp *E, C &Cmp) const
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
UnaryOp(TIL_UnaryOpcode Op, SExpr *E)
C::CType compare(const Undefined *E, C &Cmp) const
Undefined & operator=(const Undefined &)=delete
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
Undefined(const Stmt *S=nullptr)
static bool classof(const SExpr *E)
Undefined(const Undefined &U)
Variable(SExpr *D, const ValueDecl *Cvd=nullptr)
void setName(StringRef S)
Variable(const Variable &Vd, SExpr *D)
C::CType compare(const Variable *E, C &Cmp) const
void setDefinition(SExpr *E)
StringRef name() const
Return the name of the variable, if any.
static bool classof(const SExpr *E)
Variable(StringRef s, SExpr *D=nullptr)
SExpr * definition()
Return the definition of the variable.
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
const SExpr * definition() const
const ValueDecl * clangDecl() const
Return the clang declaration for this variable, if any.
void setClangDecl(const ValueDecl *VD)
@ VK_SFun
SFunction (self) parameter.
@ VK_Fun
Function parameter.
void setKind(VariableKind K)
VariableKind kind() const
Return the kind of variable (let, function param, or self)
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
static bool classof(const SExpr *E)
C::CType compare(const Wildcard *E, C &Cmp) const
Wildcard(const Wildcard &)=default
bool isTrivial(const SExpr *E)
TIL_UnaryOpcode
Opcode for unary arithmetic operations.
void simplifyIncompleteArg(til::Phi *Ph)
const TIL_BinaryOpcode BOP_Min
const TIL_UnaryOpcode UOP_Min
StringRef getBinaryOpcodeString(TIL_BinaryOpcode Op)
Return the name of a binary opcode.
StringRef getUnaryOpcodeString(TIL_UnaryOpcode Op)
Return the name of a unary opcode.
TIL_CastOpcode
Opcode for cast operations.
const TIL_CastOpcode CAST_Max
TIL_BinaryOpcode
Opcode for binary arithmetic operations.
SExpr * simplifyToCanonicalVal(SExpr *E)
const TIL_BinaryOpcode BOP_Max
const TIL_CastOpcode CAST_Min
const TIL_UnaryOpcode UOP_Max
const SExpr * getCanonicalVal(const SExpr *E)
TIL_Opcode
Enum for the different distinct classes of SExpr.
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
const FunctionProtoType * T
U cast(CodeGen::Address addr)
@ Other
Other implicit parameter.
bool isParentOf(const TopologyNode &OtherNode)
bool isParentOfOrEqual(const TopologyNode &OtherNode)
ValueTypes are data types that can actually be held in registers.
ValueType(BaseType B, SizeType Sz, bool S, unsigned char VS)
static ValueType getValueType()
static SizeType getSizeType(unsigned nbytes)