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"
170 return a.
Base ==
b.Base;
223 return ::operator
new(S, R);
232 void operator delete(
void *) =
delete;
262 return Op == COP_Variable || Op == COP_Literal || Op == COP_LiteralPtr;
295 :
SExpr(COP_Variable), Name(
s), Definition(D) {
300 :
SExpr(COP_Variable), Name(Cvd ? Cvd->getName() :
"_x"),
301 Definition(D), Cvdecl(Cvd) {
306 :
SExpr(Vd), Name(Vd.Name), Definition(D), Cvdecl(Vd.Cvdecl) {
316 StringRef
name()
const {
return Name; }
333 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
335 return Vs.reduceVariableRef(
this);
340 return Cmp.compareVariableRefs(
this, E);
393 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
394 assert(Result &&
"Cannot traverse Future that has not been forced.");
395 return Vs.traverse(Result, Ctx);
400 if (!Result || !E->Result)
401 return Cmp.comparePointers(
this, E);
402 return Cmp.compare(Result, E->Result);
425 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
426 return Vs.reduceUndefined(*
this);
431 return Cmp.trueResult();
446 template <
class V>
typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
447 return Vs.reduceWildcard(*
this);
452 return Cmp.trueResult();
477 template <
class V>
typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx);
507 switch (ValType.Base) {
509 return Vs.reduceLiteralT(
as<bool>());
521 llvm_unreachable(
"Invalid BaseType");
526 typename C::CType Ct =
Cmp.compareIntegers(ValType.Base, E->ValType.
Base);
529 switch (ValType.Base) {
531 return Cmp.compareIntegers(
as<bool>().value(), E->
as<
bool>().value());
534 E->
as<
char32_t>().value());
536 return Cmp.compareIntegers(
as<int64_t>().value(), E->
as<int64_t>().value());
539 E->
as<uint64_t>().value());
542 E->
as<StringRef>().value());
544 return Cmp.trueResult();
546 llvm_unreachable(
"Invalid BaseType");
563 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
564 return Vs.reduceLiteralPtr(*
this);
569 if (!Cvdecl || !E->Cvdecl)
570 return Cmp.comparePointers(
this, E);
571 return Cmp.comparePointers(Cvdecl, E->Cvdecl);
584 :
SExpr(COP_Function), VarDecl(Vd), Body(Bd) {
589 :
SExpr(F), VarDecl(Vd), Body(Bd) {
602 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
604 auto E0 = Vs.traverse(VarDecl->Definition, Vs.typeCtx(Ctx));
606 Variable *Nvd = Vs.enterScope(*VarDecl, E0);
607 auto E1 = Vs.
traverse(Body, Vs.declCtx(Ctx));
608 Vs.exitScope(*VarDecl);
609 return Vs.reduceFunction(*
this, Nvd, E1);
614 typename C::CType Ct =
615 Cmp.compare(VarDecl->definition(), E->VarDecl->
definition());
635 :
SExpr(COP_SFunction), VarDecl(Vd), Body(B) {
636 assert(Vd->Definition ==
nullptr);
638 Vd->Definition =
this;
642 :
SExpr(F), VarDecl(Vd), Body(B) {
643 assert(Vd->Definition ==
nullptr);
645 Vd->Definition =
this;
657 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
661 Variable *Nvd = Vs.enterScope(*VarDecl,
nullptr);
662 auto E1 = Vs.
traverse(Body, Vs.declCtx(Ctx));
663 Vs.exitScope(*VarDecl);
665 return Vs.reduceSFunction(*
this, Nvd, E1);
671 typename C::CType Ct =
Cmp.compare(
body(), E->
body());
686 :
SExpr(
C), ReturnType(T), Body(B) {}
697 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
698 auto Nt = Vs.traverse(ReturnType, Vs.typeCtx(Ctx));
699 auto Nb = Vs.traverse(Body, Vs.lazyCtx(Ctx));
700 return Vs.reduceCode(*
this, Nt, Nb);
721 :
SExpr(
C), Range(R), Body(B) {}
732 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
733 auto Nr = Vs.traverse(Range, Vs.typeCtx(Ctx));
734 auto Nb = Vs.traverse(Body, Vs.lazyCtx(Ctx));
735 return Vs.reduceField(*
this, Nr, Nb);
760 :
SExpr(A), Fun(F), Arg(Ar) {}
771 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
772 auto Nf = Vs.traverse(Fun, Vs.subExprCtx(Ctx));
773 auto Na = Vs.traverse(Arg, Vs.subExprCtx(Ctx));
774 return Vs.reduceApply(*
this, Nf, Na);
779 typename C::CType Ct =
Cmp.compare(
fun(), E->
fun());
795 :
SExpr(A), Sfun(Sf), Arg(Ar) {}
803 const SExpr *
arg()
const {
return Arg ? Arg : Sfun; }
808 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
809 auto Nf = Vs.traverse(Sfun, Vs.subExprCtx(Ctx));
810 typename V::R_SExpr Na = Arg ? Vs.traverse(Arg, Vs.subExprCtx(Ctx))
812 return Vs.reduceSApply(*
this, Nf, Na);
817 typename C::CType Ct =
Cmp.compare(
sfun(), E->
sfun());
818 if (
Cmp.notTrue(Ct) || (!
arg() && !E->
arg()))
832 :
SExpr(COP_Project), Rec(R), Cvdecl(Cvd) {
833 assert(Cvd &&
"ValueDecl must not be null");
847 else Flags &= 0xFFFE;
851 if (Cvdecl->getDeclName().isIdentifier())
852 return Cvdecl->getName();
855 llvm::raw_string_ostream OS(*SlotName);
856 Cvdecl->printName(OS);
862 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
863 auto Nr = Vs.traverse(Rec, Vs.subExprCtx(Ctx));
864 return Vs.reduceProject(*
this, Nr);
872 return Cmp.comparePointers(Cvdecl, E->Cvdecl);
877 mutable std::optional<std::string> SlotName;
885 :
SExpr(COP_Call), Target(T), Cexpr(Ce) {}
896 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
897 auto Nt = Vs.traverse(Target, Vs.subExprCtx(Ctx));
898 return Vs.reduceCall(*
this, Nt);
930 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
931 auto Nd = Vs.traverse(Dtype, Vs.declCtx(Ctx));
932 return Vs.reduceAlloc(*
this, Nd);
937 typename C::CType Ct =
Cmp.compareIntegers(
kind(), E->
kind());
959 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
960 auto Np = Vs.traverse(Ptr, Vs.subExprCtx(Ctx));
961 return Vs.reduceLoad(*
this, Np);
989 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
990 auto Np = Vs.traverse(Dest, Vs.subExprCtx(Ctx));
991 auto Nv = Vs.traverse(Source, Vs.subExprCtx(Ctx));
992 return Vs.reduceStore(*
this, Np, Nv);
1014 :
SExpr(E), Array(A), Index(N) {}
1025 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1026 auto Na = Vs.traverse(Array, Vs.subExprCtx(Ctx));
1027 auto Ni = Vs.traverse(Index, Vs.subExprCtx(Ctx));
1028 return Vs.reduceArrayIndex(*
this, Na, Ni);
1034 if (
Cmp.notTrue(Ct))
1051 :
SExpr(E), Array(A), Index(N) {}
1062 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1063 auto Na = Vs.traverse(Array, Vs.subExprCtx(Ctx));
1064 auto Ni = Vs.traverse(Index, Vs.subExprCtx(Ctx));
1065 return Vs.reduceArrayAdd(*
this, Na, Ni);
1071 if (
Cmp.notTrue(Ct))
1101 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1102 auto Ne = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
1103 return Vs.reduceUnaryOp(*
this, Ne);
1108 typename C::CType Ct =
1110 if (
Cmp.notTrue(Ct))
1124 :
SExpr(COP_BinaryOp), Expr0(E0), Expr1(E1) {
1129 :
SExpr(B), Expr0(E0), Expr1(E1) {
1146 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1147 auto Ne0 = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
1148 auto Ne1 = Vs.traverse(Expr1, Vs.subExprCtx(Ctx));
1149 return Vs.reduceBinaryOp(*
this, Ne0, Ne1);
1154 typename C::CType Ct =
1156 if (
Cmp.notTrue(Ct))
1159 if (
Cmp.notTrue(Ct))
1187 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1188 auto Ne = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
1189 return Vs.reduceCast(*
this, Ne);
1194 typename C::CType Ct =
1196 if (
Cmp.notTrue(Ct))
1242 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1243 typename V::template Container<typename V::R_SExpr>
1244 Nvs(Vs, Values.size());
1246 for (
const auto *Val : Values)
1247 Nvs.push_back( Vs.traverse(Val, Vs.subExprCtx(Ctx)) );
1248 return Vs.reducePhi(*
this, Nvs);
1254 return Cmp.comparePointers(
this, E);
1270 return E->
opcode() >= COP_Goto && E->
opcode() <= COP_Return;
1285 :
Terminator(COP_Goto), TargetBlock(B), Index(I) {}
1287 :
Terminator(COP_Goto), TargetBlock(B), Index(I) {}
1295 unsigned index()
const {
return Index; }
1301 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1302 BasicBlock *Ntb = Vs.reduceBasicBlockRef(TargetBlock);
1303 return Vs.reduceGoto(*
this, Ntb);
1309 return Cmp.comparePointers(
this, E);
1349 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1350 auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx));
1351 BasicBlock *Ntb = Vs.reduceBasicBlockRef(Branches[0]);
1352 BasicBlock *Nte = Vs.reduceBasicBlockRef(Branches[1]);
1353 return Vs.reduceBranch(*
this, Nc, Ntb, Nte);
1359 return Cmp.comparePointers(
this, E);
1383 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1384 auto Ne = Vs.traverse(Retval, Vs.subExprCtx(Ctx));
1385 return Vs.reduceReturn(*
this, Ne);
1390 return Cmp.compare(Retval, E->Retval);
1399 case COP_Goto:
return cast<Goto>(
this)->successors();
1400 case COP_Branch:
return cast<Branch>(
this)->successors();
1401 case COP_Return:
return cast<Return>(
this)->successors();
1444 :
SExpr(COP_BasicBlock), Arena(A), BlockID(0), Visited(
false) {}
1447 :
SExpr(COP_BasicBlock), Arena(A), BlockID(0), Visited(
false),
1448 Args(
std::move(As)), Instrs(
std::move(Is)), TermInstr(T) {}
1486 return DominatorNode.isParentOfOrEqual(
Other.DominatorNode);
1490 return PostDominatorNode.isParentOfOrEqual(
Other.PostDominatorNode);
1495 Args.reserveCheck(1, Arena);
1501 Instrs.reserveCheck(1, Arena);
1502 Instrs.push_back(
V);
1520 auto I = llvm::find(Predecessors, BB);
1521 return std::distance(Predecessors.cbegin(), I);
1525 typename V::R_BasicBlock
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1526 typename V::template Container<SExpr*> Nas(Vs, Args.size());
1527 typename V::template Container<SExpr*> Nis(Vs, Instrs.size());
1530 Vs.enterBasicBlock(*
this);
1532 for (
const auto *E : Args) {
1533 auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
1536 for (
const auto *E : Instrs) {
1537 auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
1540 auto Nt = Vs.traverse(TermInstr, Ctx);
1543 Vs.exitBasicBlock(*
this);
1545 return Vs.reduceBasicBlock(*
this, Nas, Nis, Nt);
1551 return Cmp.comparePointers(
this, E);
1558 unsigned renumberInstrs(
unsigned id);
1562 void computeDominator();
1563 void computePostDominator();
1569 SCFG *CFGPtr =
nullptr;
1572 unsigned BlockID : 31;
1575 LLVM_PREFERRED_TYPE(
bool)
1576 unsigned Visited : 1;
1607 :
SExpr(COP_SCFG), Arena(A), Blocks(A, Nblocks) {
1610 auto *
V =
new (A)
Phi();
1611 Exit->addArgument(
V);
1612 Exit->setTerminator(
new (A)
Return(
V));
1618 :
SExpr(COP_SCFG), Arena(Cfg.Arena), Blocks(
std::move(Ba)) {
1625 bool valid()
const {
return Entry && Exit && Blocks.size() > 0; }
1656 assert(BB->CFGPtr ==
nullptr);
1658 Blocks.reserveCheck(1, Arena);
1659 Blocks.push_back(BB);
1668 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1670 typename V::template Container<BasicBlock *> Bbs(Vs, Blocks.size());
1672 for (
const auto *B : Blocks) {
1673 Bbs.push_back( B->traverse(Vs, Vs.subExprCtx(Ctx)) );
1676 return Vs.reduceSCFG(*
this, Bbs);
1682 return Cmp.comparePointers(
this, E);
1687 void renumberInstrs();
1693 unsigned NumInstructions = 0;
1706 StringRef
name()
const {
return Name; }
1709 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1710 return Vs.reduceIdentifier(*
this);
1727 :
SExpr(COP_IfThenElse), Condition(
C), ThenExpr(T), ElseExpr(E) {}
1729 :
SExpr(I), Condition(
C), ThenExpr(T), ElseExpr(E) {}
1743 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1744 auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx));
1745 auto Nt = Vs.traverse(ThenExpr, Vs.subExprCtx(Ctx));
1746 auto Ne = Vs.traverse(ElseExpr, Vs.subExprCtx(Ctx));
1747 return Vs.reduceIfThenElse(*
this, Nc, Nt, Ne);
1753 if (
Cmp.notTrue(Ct))
1756 if (
Cmp.notTrue(Ct))
1788 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1790 auto E0 = Vs.traverse(VarDecl->Definition, Vs.subExprCtx(Ctx));
1792 Variable *Nvd = Vs.enterScope(*VarDecl, E0);
1794 Vs.exitScope(*VarDecl);
1795 return Vs.reduceLet(*
this, Nvd, E1);
1800 typename C::CType Ct =
1801 Cmp.compare(VarDecl->definition(), E->VarDecl->
definition());
1802 if (
Cmp.notTrue(Ct))
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)
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 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.
bool operator==(const ValueType &a, const ValueType &b)
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)
LiteralT(T) -> LiteralT< T >
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.
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.
static ValueType getValueType()