28 #include "llvm/ADT/DenseMap.h"
29 #include "llvm/ADT/SmallVector.h"
30 #include "llvm/ADT/StringRef.h"
35 using namespace clang;
36 using namespace threadSafety;
40 switch (CE->getStmtClass()) {
41 case Stmt::IntegerLiteralClass:
42 return cast<IntegerLiteral>(CE)->
getValue().toString(10,
true);
43 case Stmt::StringLiteralClass: {
44 std::string ret(
"\"");
45 ret += cast<StringLiteral>(CE)->getString();
49 case Stmt::CharacterLiteralClass:
50 case Stmt::CXXNullPtrLiteralExprClass:
51 case Stmt::GNUNullExprClass:
52 case Stmt::CXXBoolLiteralExprClass:
53 case Stmt::FloatingLiteralClass:
54 case Stmt::ImaginaryLiteralClass:
55 case Stmt::ObjCStringLiteralClass:
63 if (
const auto *Ph = dyn_cast<til::Phi>(E))
71 auto It =
SMap.find(S);
84 return ME ? ME->
isArrow() :
false;
106 if (
const MemberExpr *ME = dyn_cast<MemberExpr>(DeclExp)) {
110 dyn_cast<CXXMemberCallExpr>(DeclExp)) {
111 Ctx.
SelfArg = CE->getImplicitObjectArgument();
113 Ctx.
NumArgs = CE->getNumArgs();
115 }
else if (
const CallExpr *CE = dyn_cast<CallExpr>(DeclExp)) {
116 Ctx.
NumArgs = CE->getNumArgs();
119 dyn_cast<CXXConstructExpr>(DeclExp)) {
121 Ctx.
NumArgs = CE->getNumArgs();
123 }
else if (D && isa<CXXDestructorDecl>(D)) {
130 if (SelfDecl && !Ctx.
SelfArg) {
132 SelfDecl->getLocation());
156 if (
auto* SLit = dyn_cast<StringLiteral>(AttrExp)) {
157 if (SLit->getString() == StringRef(
"*"))
167 if (
auto *OE = dyn_cast<CXXOperatorCallExpr>(AttrExp)) {
168 if (OE->getOperator() == OO_Exclaim) {
170 AttrExp = OE->getArg(0);
173 else if (
auto *UO = dyn_cast<UnaryOperator>(AttrExp)) {
174 if (UO->getOpcode() == UO_LNot) {
176 AttrExp = UO->getSubExpr();
184 if (!E || isa<til::Literal>(E))
188 if (
auto *CE = dyn_cast_or_null<til::Cast>(E)) {
207 switch (S->getStmtClass()) {
208 case Stmt::DeclRefExprClass:
209 return translateDeclRefExpr(cast<DeclRefExpr>(S), Ctx);
210 case Stmt::CXXThisExprClass:
211 return translateCXXThisExpr(cast<CXXThisExpr>(S), Ctx);
212 case Stmt::MemberExprClass:
213 return translateMemberExpr(cast<MemberExpr>(S), Ctx);
214 case Stmt::CallExprClass:
215 return translateCallExpr(cast<CallExpr>(S), Ctx);
216 case Stmt::CXXMemberCallExprClass:
217 return translateCXXMemberCallExpr(cast<CXXMemberCallExpr>(S), Ctx);
218 case Stmt::CXXOperatorCallExprClass:
219 return translateCXXOperatorCallExpr(cast<CXXOperatorCallExpr>(S), Ctx);
220 case Stmt::UnaryOperatorClass:
221 return translateUnaryOperator(cast<UnaryOperator>(S), Ctx);
222 case Stmt::BinaryOperatorClass:
223 case Stmt::CompoundAssignOperatorClass:
224 return translateBinaryOperator(cast<BinaryOperator>(S), Ctx);
226 case Stmt::ArraySubscriptExprClass:
227 return translateArraySubscriptExpr(cast<ArraySubscriptExpr>(S), Ctx);
228 case Stmt::ConditionalOperatorClass:
229 return translateAbstractConditionalOperator(
230 cast<ConditionalOperator>(S), Ctx);
231 case Stmt::BinaryConditionalOperatorClass:
232 return translateAbstractConditionalOperator(
233 cast<BinaryConditionalOperator>(S), Ctx);
236 case Stmt::ParenExprClass:
237 return translate(cast<ParenExpr>(S)->getSubExpr(), Ctx);
238 case Stmt::ExprWithCleanupsClass:
239 return translate(cast<ExprWithCleanups>(S)->getSubExpr(), Ctx);
240 case Stmt::CXXBindTemporaryExprClass:
241 return translate(cast<CXXBindTemporaryExpr>(S)->getSubExpr(), Ctx);
244 case Stmt::CharacterLiteralClass:
245 case Stmt::CXXNullPtrLiteralExprClass:
246 case Stmt::GNUNullExprClass:
247 case Stmt::CXXBoolLiteralExprClass:
248 case Stmt::FloatingLiteralClass:
249 case Stmt::ImaginaryLiteralClass:
250 case Stmt::IntegerLiteralClass:
251 case Stmt::StringLiteralClass:
252 case Stmt::ObjCStringLiteralClass:
255 case Stmt::DeclStmtClass:
256 return translateDeclStmt(cast<DeclStmt>(S), Ctx);
260 if (
const CastExpr *CE = dyn_cast<CastExpr>(S))
261 return translateCastExpr(CE, Ctx);
271 if (
const ParmVarDecl *PV = dyn_cast_or_null<ParmVarDecl>(VD)) {
274 unsigned I = PV->getFunctionScopeIndex();
295 assert(SelfVar &&
"We have no variable for 'this'!");
300 if (
auto *V = dyn_cast<til::Variable>(E))
301 return V->clangDecl();
302 if (
auto *Ph = dyn_cast<til::Phi>(E))
303 return Ph->clangDecl();
304 if (
auto *
P = dyn_cast<til::Project>(E))
305 return P->clangDecl();
306 if (
auto *L = dyn_cast<til::LiteralPtr>(E))
307 return L->clangDecl();
315 if (
auto *C = dyn_cast<til::Cast>(E))
341 if (
auto *VD = dyn_cast<CXXMethodDecl>(D))
353 if (CapabilityExprMode) {
356 if (LockReturnedAttr* At = FD->getAttr<LockReturnedAttr>()) {
359 LRCallCtx.SelfArg = SelfE;
361 LRCallCtx.FunArgs = CE->
getArgs();
368 for (
const auto *Arg : CE->
arguments()) {
375 til::SExpr *SExprBuilder::translateCXXMemberCallExpr(
377 if (CapabilityExprMode) {
386 return translateCallExpr(cast<CallExpr>(ME), Ctx,
390 til::SExpr *SExprBuilder::translateCXXOperatorCallExpr(
392 if (CapabilityExprMode) {
395 if (k == OO_Star || k == OO_Arrow) {
401 return translateCallExpr(cast<CallExpr>(OCE), Ctx);
414 if (CapabilityExprMode) {
476 if (
const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(LHS)) {
478 CV = lookupVarDecl(VD);
484 E1 = addStatement(E1,
nullptr, VD);
487 return updateVarDecl(VD, E1);
498 case BO_Mul:
return translateBinOp(
til::BOP_Mul, BO, Ctx);
499 case BO_Div:
return translateBinOp(
til::BOP_Div, BO, Ctx);
500 case BO_Rem:
return translateBinOp(
til::BOP_Rem, BO, Ctx);
501 case BO_Add:
return translateBinOp(
til::BOP_Add, BO, Ctx);
502 case BO_Sub:
return translateBinOp(
til::BOP_Sub, BO, Ctx);
503 case BO_Shl:
return translateBinOp(
til::BOP_Shl, BO, Ctx);
504 case BO_Shr:
return translateBinOp(
til::BOP_Shr, BO, Ctx);
505 case BO_LT:
return translateBinOp(
til::BOP_Lt, BO, Ctx);
506 case BO_GT:
return translateBinOp(
til::BOP_Lt, BO, Ctx,
true);
507 case BO_LE:
return translateBinOp(
til::BOP_Leq, BO, Ctx);
508 case BO_GE:
return translateBinOp(
til::BOP_Leq, BO, Ctx,
true);
509 case BO_EQ:
return translateBinOp(
til::BOP_Eq, BO, Ctx);
510 case BO_NE:
return translateBinOp(
til::BOP_Neq, BO, Ctx);
517 case BO_Assign:
return translateBinAssign(
til::BOP_Eq, BO, Ctx,
true);
518 case BO_MulAssign:
return translateBinAssign(
til::BOP_Mul, BO, Ctx);
519 case BO_DivAssign:
return translateBinAssign(
til::BOP_Div, BO, Ctx);
520 case BO_RemAssign:
return translateBinAssign(
til::BOP_Rem, BO, Ctx);
521 case BO_AddAssign:
return translateBinAssign(
til::BOP_Add, BO, Ctx);
522 case BO_SubAssign:
return translateBinAssign(
til::BOP_Sub, BO, Ctx);
523 case BO_ShlAssign:
return translateBinAssign(
til::BOP_Shl, BO, Ctx);
524 case BO_ShrAssign:
return translateBinAssign(
til::BOP_Shr, BO, Ctx);
525 case BO_AndAssign:
return translateBinAssign(
til::BOP_BitAnd, BO, Ctx);
526 case BO_XorAssign:
return translateBinAssign(
til::BOP_BitXor, BO, Ctx);
527 case BO_OrAssign:
return translateBinAssign(
til::BOP_BitOr, BO, Ctx);
540 case CK_LValueToRValue: {
552 case CK_DerivedToBase:
553 case CK_UncheckedDerivedToBase:
554 case CK_ArrayToPointerDecay:
555 case CK_FunctionToPointerDecay: {
562 if (CapabilityExprMode)
578 SExprBuilder::translateAbstractConditionalOperator(
590 if (
VarDecl *VD = dyn_cast_or_null<VarDecl>(*I)) {
591 Expr *E = VD->getInit();
597 return addVarDecl(VD, SE);
617 CurrentInstructions.push_back(E);
625 auto It = LVarIdxMap.find(VD);
626 if (It != LVarIdxMap.end()) {
627 assert(CurrentLVarMap[It->second].first == VD);
628 return CurrentLVarMap[It->second].second;
646 LVarIdxMap.insert(std::make_pair(VD, CurrentLVarMap.
size()));
648 CurrentLVarMap.
push_back(std::make_pair(VD, E));
655 auto It = LVarIdxMap.find(VD);
656 if (It == LVarIdxMap.end()) {
662 CurrentLVarMap.
elem(It->second).second =
E;
669 void SExprBuilder::makePhiNodeVar(
unsigned i,
unsigned NPreds,
til::SExpr *E) {
670 unsigned ArgIndex = CurrentBlockInfo->ProcessedPredecessors;
671 assert(ArgIndex > 0 && ArgIndex < NPreds);
674 if (CurrE->
block() == CurrentBB) {
678 assert(Ph &&
"Expecting Phi node.");
688 for (
unsigned PIdx = 0; PIdx < ArgIndex; ++PIdx)
689 Ph->
values()[PIdx] = CurrE;
700 CurrentArguments.push_back(Ph);
702 IncompleteArgs.push_back(Ph);
705 CurrentLVarMap.
elem(i).second = Ph;
710 void SExprBuilder::mergeEntryMap(LVarDefinitionMap
Map) {
711 assert(CurrentBlockInfo &&
"Not processing a block!");
713 if (!CurrentLVarMap.
valid()) {
715 CurrentLVarMap = std::move(Map);
718 if (CurrentLVarMap.
sameAs(Map))
722 unsigned ESz = CurrentLVarMap.
size();
723 unsigned MSz = Map.size();
726 for (
unsigned i=0; i<Sz; ++i) {
727 if (CurrentLVarMap[i].first != Map[i].first) {
733 if (CurrentLVarMap[i].second != Map[i].second)
734 makePhiNodeVar(i, NPreds, Map[i].second);
738 CurrentLVarMap.
downsize(Map.size());
744 void SExprBuilder::mergeEntryMapBackEdge() {
753 assert(CurrentBlockInfo &&
"Not processing a block!");
755 if (CurrentBlockInfo->HasBackEdges)
757 CurrentBlockInfo->HasBackEdges =
true;
760 unsigned Sz = CurrentLVarMap.
size();
763 for (
unsigned i=0; i < Sz; ++i) {
764 makePhiNodeVar(i, NPreds,
nullptr);
771 void SExprBuilder::mergePhiNodesBackEdge(
const CFGBlock *Blk) {
773 unsigned ArgIndex = BBInfo[Blk->
getBlockID()].ProcessedPredecessors;
774 assert(ArgIndex > 0 && ArgIndex < BB->numPredecessors());
777 til::Phi *Ph = dyn_cast_or_null<til::Phi>(PE);
778 assert(Ph &&
"Expecting Phi Node.");
779 assert(Ph->
values()[ArgIndex] ==
nullptr &&
"Wrong index for back edge.");
782 assert(E &&
"Couldn't find local variable for Phi node.");
787 void SExprBuilder::enterCFG(
CFG *Cfg,
const NamedDecl *D,
791 Scfg =
new (Arena)
til::SCFG(Arena, NBlocks);
794 BBInfo.resize(NBlocks);
795 BlockMap.resize(NBlocks,
nullptr);
797 for (
auto *B : *Cfg) {
800 BlockMap[B->getBlockID()] = BB;
804 auto Parms = isa<ObjCMethodDecl>(D) ? cast<ObjCMethodDecl>(D)->parameters()
805 : cast<FunctionDecl>(D)->parameters();
806 for (
auto *Pm : Parms) {
815 til::SExpr *V = addStatement(Ld,
nullptr, Pm);
820 void SExprBuilder::enterCFGBlock(
const CFGBlock *B) {
824 Scfg->
add(CurrentBB);
833 void SExprBuilder::handlePredecessor(
const CFGBlock *Pred) {
837 BlockInfo *PredInfo = &BBInfo[Pred->
getBlockID()];
838 assert(PredInfo->UnprocessedSuccessors > 0);
840 if (--PredInfo->UnprocessedSuccessors == 0)
841 mergeEntryMap(std::move(PredInfo->ExitMap));
843 mergeEntryMap(PredInfo->ExitMap.clone());
845 ++CurrentBlockInfo->ProcessedPredecessors;
848 void SExprBuilder::handlePredecessorBackEdge(
const CFGBlock *Pred) {
849 mergeEntryMapBackEdge();
852 void SExprBuilder::enterCFGBlockBody(
const CFGBlock *B) {
856 static_cast<unsigned>(CurrentArguments.size()), Arena);
857 for (
auto *A : CurrentArguments)
861 void SExprBuilder::handleStatement(
const Stmt *S) {
866 void SExprBuilder::handleDestructorCall(
const VarDecl *VD,
872 addStatement(E,
nullptr);
875 void SExprBuilder::exitCFGBlockBody(
const CFGBlock *B) {
877 static_cast<unsigned>(CurrentInstructions.size()), Arena);
878 for (
auto *V : CurrentInstructions)
888 auto *Tm =
new (Arena)
til::Goto(BB, Idx);
902 void SExprBuilder::handleSuccessor(
const CFGBlock *Succ) {
903 ++CurrentBlockInfo->UnprocessedSuccessors;
906 void SExprBuilder::handleSuccessorBackEdge(
const CFGBlock *Succ) {
907 mergePhiNodesBackEdge(Succ);
908 ++BBInfo[Succ->
getBlockID()].ProcessedPredecessors;
911 void SExprBuilder::exitCFGBlock(
const CFGBlock *B) {
912 CurrentArguments.clear();
913 CurrentInstructions.clear();
914 CurrentBlockInfo->ExitMap = std::move(CurrentLVarMap);
916 CurrentBlockInfo =
nullptr;
920 for (
auto *Ph : IncompleteArgs) {
925 CurrentArguments.clear();
926 CurrentInstructions.clear();
927 IncompleteArgs.clear();
A call to an overloaded operator written using operator syntax.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
CastKind getCastKind() const
Simple arithmetic unary operations, e.g.
static const Decl * getCanonicalDecl(const Decl *D)
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
Apply a self-argument to a self-applicable function.
Expr ** getArgs()
Retrieve the call arguments.
til::SExpr * lookupStmt(const Stmt *S)
const DeclGroupRef getDeclGroup() const
A (possibly-)qualified type.
A conditional branch to two other blocks.
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
succ_iterator succ_begin()
static bool hasCppPointerType(const til::SExpr *E)
Defines the SourceManager interface.
const ValArray & values() const
til::SExpr * translate(const Stmt *S, CallingContext *Ctx)
static const ValueDecl * getValueDeclFromSExpr(const til::SExpr *E)
Represents a call to a C++ constructor.
void push_back(const T &Elem)
VarDecl - An instance of this class is created to represent a variable declaration or definition...
const Expr * getCallee() const
static bool isCalleeArrow(const Expr *E)
unsigned succ_size() const
unsigned addPredecessor(BasicBlock *Pred)
static const CXXMethodDecl * getFirstVirtualDecl(const CXXMethodDecl *D)
ParmVarDecl - Represents a parameter to a function.
Defines the clang::Expr interface and subclasses for C++ expressions.
If p is a reference to an array, then p[i] is a reference to the i'th element of the array...
til::SCFG * buildCFG(CFGWalker &Walker)
method_iterator end_overridden_methods() const
InstrArray & instructions()
Project a named slot from a C++ struct or class.
Expr * getImplicitObjectArgument() const
Retrieves the implicit object argument for the member call.
CXXMethodDecl * getCanonicalDecl() override
void reserveInstructions(unsigned Nins)
static void maybeUpdateVD(til::SExpr *E, const ValueDecl *VD)
Expr * getTrueExpr() const
void downsize(unsigned i)
unsigned pred_size() const
A builtin binary operation expression such as "x + y" or "x <= y".
std::string getNameAsString() const
getNameAsString - Get a human-readable name for the declaration, even if it is one of the special kin...
Expr * IgnoreParenCasts() LLVM_READONLY
IgnoreParenCasts - Ignore parentheses and casts.
A basic block is part of an SCFG.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
unsigned findPredecessorIndex(const BasicBlock *BB) const
Return the index of BB, or Predecessors.size if BB is not a predecessor.
bool isTrivialType(const ASTContext &Context) const
Return true if this is a trivial type per (C++0x [basic.types]p9)
detail::InMemoryDirectory::const_iterator I
Placeholder for expressions that cannot be represented in the TIL.
Represents the this expression in C++.
void addInstruction(SExpr *V)
Add a new instruction.
An SCFG is a control-flow graph.
CXXMethodDecl * getMethodDecl() const
Retrieves the declaration of the called method.
CastKind
CastKind - The kind of operation required for a conversion.
CFGBlock - Represents a single basic block in a source-level CFG.
bool isCXXInstanceMember() const
Determine whether the given declaration is an instance member of a C++ class.
void addArgument(Phi *V)
Add a new argument.
const CXXMethodDecl *const * method_iterator
Apply an argument to a function.
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)
Stmt * getTerminatorCondition(bool StripParens=true)
CFG - Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt...
const InstrArray & arguments() const
Represents a C++ destructor within a class.
Defines an enumeration for C++ overloaded operators.
const ParmVarDecl * getParamDecl(unsigned i) const
char __ovld __cnfn min(char x, char y)
Returns y if y < x, otherwise it returns x.
static SVal getValue(SVal val, SValBuilder &svalBuilder)
Jump to another basic block.
Expr * getSubExpr() const
unsigned getBlockID() const
UnaryOperator - This represents the unary-expression's (except sizeof and alignof), the postinc/postdec operators from postfix-expression, and various extensions.
class LLVM_ALIGNAS(8) TemplateSpecializationType unsigned NumArgs
Represents a type template specialization; the template must be a class template, a type alias templa...
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.
void reservePredecessors(unsigned NumPreds)
method_iterator begin_overridden_methods() const
Represents a call to a member function that may be written either with member call syntax (e...
DeclStmt - Adaptor class for mixing declarations with statements and expressions. ...
Represents a static or instance method of a struct/union/class.
bool sameAs(const CopyOnWriteVector &V) const
size_t numPredecessors() const
Returns the number of predecessors.
std::string getSourceLiteralString(const clang::Expr *CE)
SExprBuilder::CallingContext CallingContext
Placeholder for a wildcard that matches any other expression.
Encapsulates the lexical context of a function call.
Load a value from memory.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return 0.
void setClangDecl(const clang::ValueDecl *Cvd)
Set the clang variable associated with this Phi node.
An if-then-else expression.
const Expr *const * FunArgs
detail::InMemoryDirectory::const_iterator E
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
unsigned Map[Count]
The type of a lookup table which maps from language-specific address spaces to target-specific ones...
til::BasicBlock * lookupBlock(const CFGBlock *B)
const clang::ValueDecl * clangDecl() const
Return the clang declaration of the variable for this Phi node, if any.
Phi Node, for code in SSA form.
Expr * getFalseExpr() const
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
Simple arithmetic binary operations, e.g.
void setValues(unsigned Sz, const T &C)
CapabilityExpr translateAttrExpr(const Expr *AttrExp, const NamedDecl *D, const Expr *DeclExp, VarDecl *SelfD=nullptr)
Translate a clang expression in an attribute to a til::SExpr.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
OverloadedOperatorKind getOperator() const
Returns the kind of overloaded operator that this expression refers to.
void reserve(size_t Ncp, MemRegionRef A)
Defines the clang::SourceLocation class and associated facilities.
bool isTrivial(const SExpr *E)
void simplifyIncompleteArg(til::Phi *Ph)
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
static bool isIncompletePhi(const til::SExpr *E)
decl_type * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
A reference to a declared variable, function, enum, etc.
const NamedDecl * AttrDecl
Base class for AST nodes in the typed intermediate language.
A Literal pointer to an object allocated in memory.
An l-value expression is a reference to an object with independent storage.
Call a function (after all arguments have been applied).
NamedDecl - This represents a decl with a name.
llvm::DenseMap< const Stmt *, CFGBlock * > SMap
unsigned getNumBlockIDs() const
getNumBlockIDs - Returns the total number of BlockIDs allocated (which start at 0).
bool isPointerType() const