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/raw_ostream.h"
71namespace threadSafety {
78#define TIL_OPCODE_DEF(X) COP_##X,
79#include "ThreadSafetyOps.def"
192 case 2:
return ST_16;
193 case 4:
return ST_32;
194 case 8:
return ST_64;
196 default:
return ST_0;
261inline ValueType ValueType::getValueType<long double>() {
297 return ::operator
new(S, R);
306 void operator delete(
void *) =
delete;
332namespace ThreadSafetyTIL {
336 return Op == COP_Variable || Op == COP_Literal || Op == COP_LiteralPtr;
369 :
SExpr(COP_Variable), Name(
s), Definition(
D) {
374 :
SExpr(COP_Variable), Name(Cvd ? Cvd->
getName() :
"_x"),
375 Definition(
D), Cvdecl(Cvd) {
380 :
SExpr(Vd), Name(Vd.Name), Definition(
D), Cvdecl(Vd.Cvdecl) {
390 StringRef
name()
const {
return Name; }
407 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
409 return Vs.reduceVariableRef(
this);
414 return Cmp.compareVariableRefs(
this,
E);
467 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
468 assert(Result &&
"Cannot traverse Future that has not been forced.");
469 return Vs.traverse(Result, Ctx);
474 if (!Result || !
E->Result)
475 return Cmp.comparePointers(
this,
E);
476 return Cmp.compare(Result,
E->Result);
483 SExpr *Result =
nullptr;
499 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
500 return Vs.reduceUndefined(*
this);
505 return Cmp.trueResult();
520 template <
class V>
typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
521 return Vs.reduceWildcard(*
this);
526 return Cmp.trueResult();
530template <
class T>
class LiteralT;
536 :
SExpr(COP_Literal), ValType(
ValueType::getValueType<void>()), Cexpr(
C) {}
554 template <
class V>
typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx);
559 return Cmp.trueResult();
564 const Expr *Cexpr =
nullptr;
588 return Vs.reduceLiteral(*
this);
590 switch (ValType.
Base) {
594 return Vs.reduceLiteralT(as<bool>());
596 switch (ValType.
Size) {
599 return Vs.reduceLiteralT(as<int8_t>());
601 return Vs.reduceLiteralT(as<uint8_t>());
604 return Vs.reduceLiteralT(as<int16_t>());
606 return Vs.reduceLiteralT(as<uint16_t>());
609 return Vs.reduceLiteralT(as<int32_t>());
611 return Vs.reduceLiteralT(as<uint32_t>());
614 return Vs.reduceLiteralT(as<int64_t>());
616 return Vs.reduceLiteralT(as<uint64_t>());
622 switch (ValType.
Size) {
624 return Vs.reduceLiteralT(as<float>());
626 return Vs.reduceLiteralT(as<double>());
632 return Vs.reduceLiteralT(as<StringRef>());
634 return Vs.reduceLiteralT(as<void*>());
638 return Vs.reduceLiteral(*
this);
655 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
656 return Vs.reduceLiteralPtr(*
this);
661 if (!Cvdecl || !
E->Cvdecl)
662 return Cmp.comparePointers(
this,
E);
663 return Cmp.comparePointers(Cvdecl,
E->Cvdecl);
694 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
699 auto E1 = Vs.
traverse(Body, Vs.declCtx(Ctx));
701 return Vs.reduceFunction(*
this, Nvd, E1);
706 typename C::CType Ct =
707 Cmp.compare(
VarDecl->definition(),
E->VarDecl->definition());
711 Ct = Cmp.compare(
body(),
E->body());
728 assert(Vd->Definition ==
nullptr);
730 Vd->Definition =
this;
735 assert(Vd->Definition ==
nullptr);
737 Vd->Definition =
this;
749 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
754 auto E1 = Vs.
traverse(Body, Vs.declCtx(Ctx));
757 return Vs.reduceSFunction(*
this, Nvd, E1);
763 typename C::CType Ct = Cmp.compare(
body(),
E->body());
778 :
SExpr(
C), ReturnType(
T), Body(B) {}
789 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
790 auto Nt = Vs.traverse(ReturnType, Vs.typeCtx(Ctx));
791 auto Nb = Vs.traverse(Body, Vs.lazyCtx(Ctx));
792 return Vs.reduceCode(*
this, Nt, Nb);
797 typename C::CType Ct = Cmp.compare(
returnType(),
E->returnType());
800 return Cmp.compare(
body(),
E->body());
813 :
SExpr(
C), Range(R), Body(B) {}
824 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
825 auto Nr = Vs.traverse(Range, Vs.typeCtx(Ctx));
826 auto Nb = Vs.traverse(Body, Vs.lazyCtx(Ctx));
827 return Vs.reduceField(*
this, Nr, Nb);
832 typename C::CType Ct = Cmp.compare(
range(),
E->range());
835 return Cmp.compare(
body(),
E->body());
852 :
SExpr(A), Fun(F), Arg(Ar) {}
863 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
864 auto Nf = Vs.traverse(Fun, Vs.subExprCtx(Ctx));
865 auto Na = Vs.traverse(Arg, Vs.subExprCtx(Ctx));
866 return Vs.reduceApply(*
this, Nf, Na);
871 typename C::CType Ct = Cmp.compare(
fun(),
E->fun());
874 return Cmp.compare(
arg(),
E->arg());
887 :
SExpr(A), Sfun(Sf), Arg(Ar) {}
895 const SExpr *
arg()
const {
return Arg ? Arg : Sfun; }
900 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
901 auto Nf = Vs.traverse(Sfun, Vs.subExprCtx(Ctx));
902 typename V::R_SExpr Na = Arg ? Vs.traverse(Arg, Vs.subExprCtx(Ctx))
904 return Vs.reduceSApply(*
this, Nf, Na);
909 typename C::CType Ct = Cmp.compare(
sfun(),
E->sfun());
910 if (Cmp.notTrue(Ct) || (!
arg() && !
E->arg()))
912 return Cmp.compare(
arg(),
E->arg());
924 :
SExpr(COP_Project), Rec(R), Cvdecl(Cvd) {
925 assert(Cvd &&
"ValueDecl must not be null");
939 else Flags &= 0xFFFE;
947 llvm::raw_string_ostream OS(*SlotName);
954 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
955 auto Nr = Vs.traverse(Rec, Vs.subExprCtx(Ctx));
956 return Vs.reduceProject(*
this, Nr);
961 typename C::CType Ct = Cmp.compare(
record(),
E->record());
964 return Cmp.comparePointers(Cvdecl,
E->Cvdecl);
969 mutable std::optional<std::string> SlotName;
988 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
989 auto Nt = Vs.traverse(
Target, Vs.subExprCtx(Ctx));
990 return Vs.reduceCall(*
this, Nt);
995 return Cmp.compare(
target(),
E->target());
1022 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1023 auto Nd = Vs.traverse(Dtype, Vs.declCtx(Ctx));
1024 return Vs.reduceAlloc(*
this, Nd);
1029 typename C::CType Ct = Cmp.compareIntegers(
kind(),
E->kind());
1030 if (Cmp.notTrue(Ct))
1032 return Cmp.compare(
dataType(),
E->dataType());
1051 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1052 auto Np = Vs.traverse(Ptr, Vs.subExprCtx(Ctx));
1053 return Vs.reduceLoad(*
this, Np);
1058 return Cmp.compare(
pointer(),
E->pointer());
1081 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1082 auto Np = Vs.traverse(Dest, Vs.subExprCtx(Ctx));
1083 auto Nv = Vs.traverse(Source, Vs.subExprCtx(Ctx));
1084 return Vs.reduceStore(*
this, Np, Nv);
1089 typename C::CType Ct = Cmp.compare(
destination(),
E->destination());
1090 if (Cmp.notTrue(Ct))
1092 return Cmp.compare(
source(),
E->source());
1106 :
SExpr(
E), Array(A), Index(N) {}
1117 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1118 auto Na = Vs.traverse(Array, Vs.subExprCtx(Ctx));
1119 auto Ni = Vs.traverse(Index, Vs.subExprCtx(Ctx));
1120 return Vs.reduceArrayIndex(*
this, Na, Ni);
1125 typename C::CType Ct = Cmp.compare(
array(),
E->array());
1126 if (Cmp.notTrue(Ct))
1128 return Cmp.compare(
index(),
E->index());
1143 :
SExpr(
E), Array(A), Index(N) {}
1154 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1155 auto Na = Vs.traverse(Array, Vs.subExprCtx(Ctx));
1156 auto Ni = Vs.traverse(Index, Vs.subExprCtx(Ctx));
1157 return Vs.reduceArrayAdd(*
this, Na, Ni);
1162 typename C::CType Ct = Cmp.compare(
array(),
E->array());
1163 if (Cmp.notTrue(Ct))
1165 return Cmp.compare(
index(),
E->index());
1193 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1194 auto Ne = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
1195 return Vs.reduceUnaryOp(*
this,
Ne);
1200 typename C::CType Ct =
1202 if (Cmp.notTrue(Ct))
1204 return Cmp.compare(
expr(),
E->expr());
1216 :
SExpr(COP_BinaryOp), Expr0(E0), Expr1(E1) {
1221 :
SExpr(B), Expr0(E0), Expr1(E1) {
1238 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1239 auto Ne0 = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
1240 auto Ne1 = Vs.traverse(Expr1, Vs.subExprCtx(Ctx));
1241 return Vs.reduceBinaryOp(*
this, Ne0, Ne1);
1246 typename C::CType Ct =
1248 if (Cmp.notTrue(Ct))
1250 Ct = Cmp.compare(
expr0(),
E->expr0());
1251 if (Cmp.notTrue(Ct))
1253 return Cmp.compare(
expr1(),
E->expr1());
1279 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1280 auto Ne = Vs.traverse(Expr0, Vs.subExprCtx(Ctx));
1281 return Vs.reduceCast(*
this,
Ne);
1286 typename C::CType Ct =
1287 Cmp.compareIntegers(
castOpcode(),
E->castOpcode());
1288 if (Cmp.notTrue(Ct))
1290 return Cmp.compare(
expr(),
E->expr());
1334 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1335 typename V::template Container<typename V::R_SExpr>
1336 Nvs(Vs, Values.
size());
1338 for (
const auto *Val : Values)
1339 Nvs.push_back( Vs.traverse(Val, Vs.subExprCtx(Ctx)) );
1340 return Vs.reducePhi(*
this, Nvs);
1346 return Cmp.comparePointers(
this,
E);
1362 return E->opcode() >= COP_Goto &&
E->opcode() <= COP_Return;
1381 :
Terminator(COP_Goto), TargetBlock(B), Index(I) {}
1383 :
Terminator(COP_Goto), TargetBlock(B), Index(I) {}
1391 unsigned index()
const {
return Index; }
1397 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1398 BasicBlock *Ntb = Vs.reduceBasicBlockRef(TargetBlock);
1399 return Vs.reduceGoto(*
this, Ntb);
1405 return Cmp.comparePointers(
this,
E);
1445 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1446 auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx));
1447 BasicBlock *Ntb = Vs.reduceBasicBlockRef(Branches[0]);
1448 BasicBlock *Nte = Vs.reduceBasicBlockRef(Branches[1]);
1449 return Vs.reduceBranch(*
this, Nc, Ntb, Nte);
1455 return Cmp.comparePointers(
this,
E);
1479 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1480 auto Ne = Vs.traverse(Retval, Vs.subExprCtx(Ctx));
1481 return Vs.reduceReturn(*
this,
Ne);
1486 return Cmp.compare(Retval,
E->Retval);
1495 case COP_Goto:
return cast<Goto>(
this)->successors();
1496 case COP_Branch:
return cast<Branch>(
this)->successors();
1497 case COP_Return:
return cast<Return>(
this)->successors();
1499 return std::nullopt;
1540 :
SExpr(COP_BasicBlock), Arena(A), BlockID(0), Visited(
false) {}
1543 :
SExpr(COP_BasicBlock), Arena(A), BlockID(0), Visited(
false),
1544 Args(
std::move(As)), Instrs(
std::move(Is)), TermInstr(
T) {}
1616 auto I = llvm::find(Predecessors, BB);
1617 return std::distance(Predecessors.
cbegin(), I);
1621 typename V::R_BasicBlock
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1622 typename V::template Container<SExpr*> Nas(Vs, Args.
size());
1623 typename V::template Container<SExpr*> Nis(Vs, Instrs.
size());
1626 Vs.enterBasicBlock(*
this);
1628 for (
const auto *
E : Args) {
1629 auto Ne = Vs.traverse(
E, Vs.subExprCtx(Ctx));
1632 for (
const auto *
E : Instrs) {
1633 auto Ne = Vs.traverse(
E, Vs.subExprCtx(Ctx));
1636 auto Nt = Vs.traverse(TermInstr, Ctx);
1639 Vs.exitBasicBlock(*
this);
1641 return Vs.reduceBasicBlock(*
this, Nas, Nis, Nt);
1647 return Cmp.comparePointers(
this,
E);
1654 unsigned renumberInstrs(
unsigned id);
1658 void computeDominator();
1659 void computePostDominator();
1665 SCFG *CFGPtr =
nullptr;
1668 unsigned BlockID : 31;
1702 :
SExpr(COP_SCFG), Arena(A), Blocks(A, Nblocks) {
1705 auto *
V =
new (A)
Phi();
1713 :
SExpr(COP_SCFG), Arena(Cfg.Arena), Blocks(
std::move(Ba)) {
1720 bool valid()
const {
return Entry && Exit && Blocks.
size() > 0; }
1751 assert(BB->CFGPtr ==
nullptr);
1763 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1765 typename V::template Container<BasicBlock *> Bbs(Vs, Blocks.
size());
1767 for (
const auto *B : Blocks) {
1768 Bbs.push_back( B->traverse(Vs, Vs.subExprCtx(Ctx)) );
1771 return Vs.reduceSCFG(*
this, Bbs);
1777 return Cmp.comparePointers(
this,
E);
1782 void renumberInstrs();
1788 unsigned NumInstructions = 0;
1789 bool Normal =
false;
1801 StringRef
name()
const {
return Name; }
1804 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1805 return Vs.reduceIdentifier(*
this);
1810 return Cmp.compareStrings(
name(),
E->name());
1822 :
SExpr(COP_IfThenElse), Condition(
C), ThenExpr(
T), ElseExpr(
E) {}
1824 :
SExpr(I), Condition(
C), ThenExpr(
T), ElseExpr(
E) {}
1838 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1839 auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx));
1840 auto Nt = Vs.traverse(ThenExpr, Vs.subExprCtx(Ctx));
1841 auto Ne = Vs.traverse(ElseExpr, Vs.subExprCtx(Ctx));
1842 return Vs.reduceIfThenElse(*
this, Nc, Nt,
Ne);
1847 typename C::CType Ct = Cmp.compare(
condition(),
E->condition());
1848 if (Cmp.notTrue(Ct))
1850 Ct = Cmp.compare(
thenExpr(),
E->thenExpr());
1851 if (Cmp.notTrue(Ct))
1853 return Cmp.compare(
elseExpr(),
E->elseExpr());
1883 typename V::R_SExpr
traverse(
V &Vs,
typename V::R_Ctx Ctx) {
1890 return Vs.reduceLet(*
this, Nvd, E1);
1895 typename C::CType Ct =
1896 Cmp.compare(
VarDecl->definition(),
E->VarDecl->definition());
1897 if (Cmp.notTrue(Ct))
1900 Ct = Cmp.compare(
body(),
E->body());
llvm::DenseSet< const void * > Visited
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
llvm::MachO::Target Target
static std::string getName(const CallEvent &Call)
__device__ __2f16 float __ockl_bool s
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
bool isIdentifier() const
Predicate functions for querying what type of name this is.
This represents one expression.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
virtual void printName(raw_ostream &OS, const PrintingPolicy &Policy) const
Pretty-print the unqualified name of this declaration.
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.
@ Definition
This declaration is definitely a definition.
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)
Alloc(const Alloc &A, SExpr *Dt)
C::CType compare(const Alloc *E, C &Cmp) const
Alloc(SExpr *D, AllocKind K)
const SExpr * dataType() const
Apply an argument to a function.
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
Pointer arithmetic, restricted to arrays only.
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)
If p is a reference to an array, then p[i] is a reference to the i'th element of the array.
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)
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.
const BasicBlock * parent() const
void addInstruction(SExpr *V)
Add a new instruction.
Simple arithmetic binary operations, e.g.
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
A conditional branch to two other blocks.
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)
ArrayRef< BasicBlock * > successors()
Return the list of basic blocks that this terminator can branch to.
static bool classof(const SExpr *E)
const BasicBlock * thenBlock() const
V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx)
Call a function (after all arguments have been applied).
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)
A block of code – e.g. the body of a function.
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)
A typed, writable location in memory.
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)
Placeholder for an expression that has not yet been created.
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()
Jump to another basic block.
BasicBlock * targetBlock()
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)
ArrayRef< BasicBlock * > successors()
Return the list of basic blocks that this terminator can branch to.
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)
An if-then-else expression.
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()
A Literal pointer to an object allocated in memory.
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
Load a value from memory.
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
Project a named slot from a C++ struct or class.
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()
Return an empty list.
static bool classof(const SExpr *E)
C::CType compare(const Return *E, C &Cmp) const
Apply a self-argument to a self-applicable function.
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
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)
const_iterator begin() const
const_iterator end() const
const_iterator cend() const
const BasicBlock * exit() const
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.
A self-applicable function.
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
void reserve(size_t Ncp, MemRegionRef A)
const_iterator cend() const
void push_back(const T &Elem)
const_iterator cbegin() const
void reserveCheck(size_t N, MemRegionRef A)
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
Terminator(const SExpr &E)
static bool classof(const SExpr *E)
ArrayRef< BasicBlock * > successors()
Return the list of basic blocks that this terminator can branch to.
Terminator(TIL_Opcode Op)
Simple arithmetic unary operations, e.g.
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)
Placeholder for expressions that cannot be represented in the TIL.
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)
Placeholder for a wildcard that matches any other expression.
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.
const FunctionProtoType * T
@ 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)