1*9880d681SAndroid Build Coastguard Worker //======- CFLGraph.h - Abstract stratified sets implementation. --------======// 2*9880d681SAndroid Build Coastguard Worker // 3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure 4*9880d681SAndroid Build Coastguard Worker // 5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source 6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details. 7*9880d681SAndroid Build Coastguard Worker // 8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 9*9880d681SAndroid Build Coastguard Worker /// \file 10*9880d681SAndroid Build Coastguard Worker /// This file defines CFLGraph, an auxiliary data structure used by CFL-based 11*9880d681SAndroid Build Coastguard Worker /// alias analysis. 12*9880d681SAndroid Build Coastguard Worker /// 13*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 14*9880d681SAndroid Build Coastguard Worker 15*9880d681SAndroid Build Coastguard Worker #ifndef LLVM_ANALYSIS_CFLGRAPH_H 16*9880d681SAndroid Build Coastguard Worker #define LLVM_ANALYSIS_CFLGRAPH_H 17*9880d681SAndroid Build Coastguard Worker 18*9880d681SAndroid Build Coastguard Worker #include "AliasAnalysisSummary.h" 19*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallPtrSet.h" 20*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/MemoryBuiltins.h" 21*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/InstVisitor.h" 22*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Instructions.h" 23*9880d681SAndroid Build Coastguard Worker 24*9880d681SAndroid Build Coastguard Worker namespace llvm { 25*9880d681SAndroid Build Coastguard Worker namespace cflaa { 26*9880d681SAndroid Build Coastguard Worker 27*9880d681SAndroid Build Coastguard Worker /// \brief The Program Expression Graph (PEG) of CFL analysis 28*9880d681SAndroid Build Coastguard Worker /// CFLGraph is auxiliary data structure used by CFL-based alias analysis to 29*9880d681SAndroid Build Coastguard Worker /// describe flow-insensitive pointer-related behaviors. Given an LLVM function, 30*9880d681SAndroid Build Coastguard Worker /// the main purpose of this graph is to abstract away unrelated facts and 31*9880d681SAndroid Build Coastguard Worker /// translate the rest into a form that can be easily digested by CFL analyses. 32*9880d681SAndroid Build Coastguard Worker /// Each Node in the graph is an InstantiatedValue, and each edge represent a 33*9880d681SAndroid Build Coastguard Worker /// pointer assignment between InstantiatedValue. Pointer 34*9880d681SAndroid Build Coastguard Worker /// references/dereferences are not explicitly stored in the graph: we 35*9880d681SAndroid Build Coastguard Worker /// implicitly assume that for each node (X, I) it has a dereference edge to (X, 36*9880d681SAndroid Build Coastguard Worker /// I+1) and a reference edge to (X, I-1). 37*9880d681SAndroid Build Coastguard Worker class CFLGraph { 38*9880d681SAndroid Build Coastguard Worker public: 39*9880d681SAndroid Build Coastguard Worker typedef InstantiatedValue Node; 40*9880d681SAndroid Build Coastguard Worker 41*9880d681SAndroid Build Coastguard Worker struct Edge { 42*9880d681SAndroid Build Coastguard Worker Node Other; 43*9880d681SAndroid Build Coastguard Worker }; 44*9880d681SAndroid Build Coastguard Worker 45*9880d681SAndroid Build Coastguard Worker typedef std::vector<Edge> EdgeList; 46*9880d681SAndroid Build Coastguard Worker 47*9880d681SAndroid Build Coastguard Worker struct NodeInfo { 48*9880d681SAndroid Build Coastguard Worker EdgeList Edges; 49*9880d681SAndroid Build Coastguard Worker AliasAttrs Attr; 50*9880d681SAndroid Build Coastguard Worker }; 51*9880d681SAndroid Build Coastguard Worker 52*9880d681SAndroid Build Coastguard Worker class ValueInfo { 53*9880d681SAndroid Build Coastguard Worker std::vector<NodeInfo> Levels; 54*9880d681SAndroid Build Coastguard Worker 55*9880d681SAndroid Build Coastguard Worker public: addNodeToLevel(unsigned Level)56*9880d681SAndroid Build Coastguard Worker bool addNodeToLevel(unsigned Level) { 57*9880d681SAndroid Build Coastguard Worker auto NumLevels = Levels.size(); 58*9880d681SAndroid Build Coastguard Worker if (NumLevels > Level) 59*9880d681SAndroid Build Coastguard Worker return false; 60*9880d681SAndroid Build Coastguard Worker Levels.resize(Level + 1); 61*9880d681SAndroid Build Coastguard Worker return true; 62*9880d681SAndroid Build Coastguard Worker } 63*9880d681SAndroid Build Coastguard Worker getNodeInfoAtLevel(unsigned Level)64*9880d681SAndroid Build Coastguard Worker NodeInfo &getNodeInfoAtLevel(unsigned Level) { 65*9880d681SAndroid Build Coastguard Worker assert(Level < Levels.size()); 66*9880d681SAndroid Build Coastguard Worker return Levels[Level]; 67*9880d681SAndroid Build Coastguard Worker } getNodeInfoAtLevel(unsigned Level)68*9880d681SAndroid Build Coastguard Worker const NodeInfo &getNodeInfoAtLevel(unsigned Level) const { 69*9880d681SAndroid Build Coastguard Worker assert(Level < Levels.size()); 70*9880d681SAndroid Build Coastguard Worker return Levels[Level]; 71*9880d681SAndroid Build Coastguard Worker } 72*9880d681SAndroid Build Coastguard Worker getNumLevels()73*9880d681SAndroid Build Coastguard Worker unsigned getNumLevels() const { return Levels.size(); } 74*9880d681SAndroid Build Coastguard Worker }; 75*9880d681SAndroid Build Coastguard Worker 76*9880d681SAndroid Build Coastguard Worker private: 77*9880d681SAndroid Build Coastguard Worker typedef DenseMap<Value *, ValueInfo> ValueMap; 78*9880d681SAndroid Build Coastguard Worker ValueMap ValueImpls; 79*9880d681SAndroid Build Coastguard Worker getNode(Node N)80*9880d681SAndroid Build Coastguard Worker const NodeInfo *getNode(Node N) const { 81*9880d681SAndroid Build Coastguard Worker auto Itr = ValueImpls.find(N.Val); 82*9880d681SAndroid Build Coastguard Worker if (Itr == ValueImpls.end() || Itr->second.getNumLevels() <= N.DerefLevel) 83*9880d681SAndroid Build Coastguard Worker return nullptr; 84*9880d681SAndroid Build Coastguard Worker return &Itr->second.getNodeInfoAtLevel(N.DerefLevel); 85*9880d681SAndroid Build Coastguard Worker } getNode(Node N)86*9880d681SAndroid Build Coastguard Worker NodeInfo *getNode(Node N) { 87*9880d681SAndroid Build Coastguard Worker auto Itr = ValueImpls.find(N.Val); 88*9880d681SAndroid Build Coastguard Worker if (Itr == ValueImpls.end() || Itr->second.getNumLevels() <= N.DerefLevel) 89*9880d681SAndroid Build Coastguard Worker return nullptr; 90*9880d681SAndroid Build Coastguard Worker return &Itr->second.getNodeInfoAtLevel(N.DerefLevel); 91*9880d681SAndroid Build Coastguard Worker } 92*9880d681SAndroid Build Coastguard Worker 93*9880d681SAndroid Build Coastguard Worker public: 94*9880d681SAndroid Build Coastguard Worker typedef ValueMap::const_iterator const_value_iterator; 95*9880d681SAndroid Build Coastguard Worker 96*9880d681SAndroid Build Coastguard Worker bool addNode(Node N, AliasAttrs Attr = AliasAttrs()) { 97*9880d681SAndroid Build Coastguard Worker assert(N.Val != nullptr); 98*9880d681SAndroid Build Coastguard Worker auto &ValInfo = ValueImpls[N.Val]; 99*9880d681SAndroid Build Coastguard Worker auto Changed = ValInfo.addNodeToLevel(N.DerefLevel); 100*9880d681SAndroid Build Coastguard Worker ValInfo.getNodeInfoAtLevel(N.DerefLevel).Attr |= Attr; 101*9880d681SAndroid Build Coastguard Worker return Changed; 102*9880d681SAndroid Build Coastguard Worker } 103*9880d681SAndroid Build Coastguard Worker addAttr(Node N,AliasAttrs Attr)104*9880d681SAndroid Build Coastguard Worker void addAttr(Node N, AliasAttrs Attr) { 105*9880d681SAndroid Build Coastguard Worker auto *Info = getNode(N); 106*9880d681SAndroid Build Coastguard Worker assert(Info != nullptr); 107*9880d681SAndroid Build Coastguard Worker Info->Attr |= Attr; 108*9880d681SAndroid Build Coastguard Worker } 109*9880d681SAndroid Build Coastguard Worker 110*9880d681SAndroid Build Coastguard Worker void addEdge(Node From, Node To, int64_t Offset = 0) { 111*9880d681SAndroid Build Coastguard Worker assert(getNode(To) != nullptr); 112*9880d681SAndroid Build Coastguard Worker 113*9880d681SAndroid Build Coastguard Worker auto *FromInfo = getNode(From); 114*9880d681SAndroid Build Coastguard Worker assert(FromInfo != nullptr); 115*9880d681SAndroid Build Coastguard Worker FromInfo->Edges.push_back(Edge{To}); 116*9880d681SAndroid Build Coastguard Worker } 117*9880d681SAndroid Build Coastguard Worker attrFor(Node N)118*9880d681SAndroid Build Coastguard Worker AliasAttrs attrFor(Node N) const { 119*9880d681SAndroid Build Coastguard Worker auto *Info = getNode(N); 120*9880d681SAndroid Build Coastguard Worker assert(Info != nullptr); 121*9880d681SAndroid Build Coastguard Worker return Info->Attr; 122*9880d681SAndroid Build Coastguard Worker } 123*9880d681SAndroid Build Coastguard Worker value_mappings()124*9880d681SAndroid Build Coastguard Worker iterator_range<const_value_iterator> value_mappings() const { 125*9880d681SAndroid Build Coastguard Worker return make_range<const_value_iterator>(ValueImpls.begin(), 126*9880d681SAndroid Build Coastguard Worker ValueImpls.end()); 127*9880d681SAndroid Build Coastguard Worker } 128*9880d681SAndroid Build Coastguard Worker }; 129*9880d681SAndroid Build Coastguard Worker 130*9880d681SAndroid Build Coastguard Worker ///\brief A builder class used to create CFLGraph instance from a given function 131*9880d681SAndroid Build Coastguard Worker /// The CFL-AA that uses this builder must provide its own type as a template 132*9880d681SAndroid Build Coastguard Worker /// argument. This is necessary for interprocedural processing: CFLGraphBuilder 133*9880d681SAndroid Build Coastguard Worker /// needs a way of obtaining the summary of other functions when callinsts are 134*9880d681SAndroid Build Coastguard Worker /// encountered. 135*9880d681SAndroid Build Coastguard Worker /// As a result, we expect the said CFL-AA to expose a getAliasSummary() public 136*9880d681SAndroid Build Coastguard Worker /// member function that takes a Function& and returns the corresponding summary 137*9880d681SAndroid Build Coastguard Worker /// as a const AliasSummary*. 138*9880d681SAndroid Build Coastguard Worker template <typename CFLAA> class CFLGraphBuilder { 139*9880d681SAndroid Build Coastguard Worker // Input of the builder 140*9880d681SAndroid Build Coastguard Worker CFLAA &Analysis; 141*9880d681SAndroid Build Coastguard Worker const TargetLibraryInfo &TLI; 142*9880d681SAndroid Build Coastguard Worker 143*9880d681SAndroid Build Coastguard Worker // Output of the builder 144*9880d681SAndroid Build Coastguard Worker CFLGraph Graph; 145*9880d681SAndroid Build Coastguard Worker SmallVector<Value *, 4> ReturnedValues; 146*9880d681SAndroid Build Coastguard Worker 147*9880d681SAndroid Build Coastguard Worker // Helper class 148*9880d681SAndroid Build Coastguard Worker /// Gets the edges our graph should have, based on an Instruction* 149*9880d681SAndroid Build Coastguard Worker class GetEdgesVisitor : public InstVisitor<GetEdgesVisitor, void> { 150*9880d681SAndroid Build Coastguard Worker CFLAA &AA; 151*9880d681SAndroid Build Coastguard Worker const TargetLibraryInfo &TLI; 152*9880d681SAndroid Build Coastguard Worker 153*9880d681SAndroid Build Coastguard Worker CFLGraph &Graph; 154*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<Value *> &ReturnValues; 155*9880d681SAndroid Build Coastguard Worker hasUsefulEdges(ConstantExpr * CE)156*9880d681SAndroid Build Coastguard Worker static bool hasUsefulEdges(ConstantExpr *CE) { 157*9880d681SAndroid Build Coastguard Worker // ConstantExpr doesn't have terminators, invokes, or fences, so only 158*9880d681SAndroid Build Coastguard Worker // needs 159*9880d681SAndroid Build Coastguard Worker // to check for compares. 160*9880d681SAndroid Build Coastguard Worker return CE->getOpcode() != Instruction::ICmp && 161*9880d681SAndroid Build Coastguard Worker CE->getOpcode() != Instruction::FCmp; 162*9880d681SAndroid Build Coastguard Worker } 163*9880d681SAndroid Build Coastguard Worker 164*9880d681SAndroid Build Coastguard Worker // Returns possible functions called by CS into the given SmallVectorImpl. 165*9880d681SAndroid Build Coastguard Worker // Returns true if targets found, false otherwise. getPossibleTargets(CallSite CS,SmallVectorImpl<Function * > & Output)166*9880d681SAndroid Build Coastguard Worker static bool getPossibleTargets(CallSite CS, 167*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<Function *> &Output) { 168*9880d681SAndroid Build Coastguard Worker if (auto *Fn = CS.getCalledFunction()) { 169*9880d681SAndroid Build Coastguard Worker Output.push_back(Fn); 170*9880d681SAndroid Build Coastguard Worker return true; 171*9880d681SAndroid Build Coastguard Worker } 172*9880d681SAndroid Build Coastguard Worker 173*9880d681SAndroid Build Coastguard Worker // TODO: If the call is indirect, we might be able to enumerate all 174*9880d681SAndroid Build Coastguard Worker // potential 175*9880d681SAndroid Build Coastguard Worker // targets of the call and return them, rather than just failing. 176*9880d681SAndroid Build Coastguard Worker return false; 177*9880d681SAndroid Build Coastguard Worker } 178*9880d681SAndroid Build Coastguard Worker 179*9880d681SAndroid Build Coastguard Worker void addNode(Value *Val, AliasAttrs Attr = AliasAttrs()) { 180*9880d681SAndroid Build Coastguard Worker assert(Val != nullptr && Val->getType()->isPointerTy()); 181*9880d681SAndroid Build Coastguard Worker if (auto GVal = dyn_cast<GlobalValue>(Val)) { 182*9880d681SAndroid Build Coastguard Worker if (Graph.addNode(InstantiatedValue{GVal, 0}, 183*9880d681SAndroid Build Coastguard Worker getGlobalOrArgAttrFromValue(*GVal))) 184*9880d681SAndroid Build Coastguard Worker Graph.addNode(InstantiatedValue{GVal, 1}, getAttrUnknown()); 185*9880d681SAndroid Build Coastguard Worker } else if (auto CExpr = dyn_cast<ConstantExpr>(Val)) { 186*9880d681SAndroid Build Coastguard Worker if (hasUsefulEdges(CExpr)) { 187*9880d681SAndroid Build Coastguard Worker if (Graph.addNode(InstantiatedValue{CExpr, 0})) 188*9880d681SAndroid Build Coastguard Worker visitConstantExpr(CExpr); 189*9880d681SAndroid Build Coastguard Worker } 190*9880d681SAndroid Build Coastguard Worker } else 191*9880d681SAndroid Build Coastguard Worker Graph.addNode(InstantiatedValue{Val, 0}, Attr); 192*9880d681SAndroid Build Coastguard Worker } 193*9880d681SAndroid Build Coastguard Worker 194*9880d681SAndroid Build Coastguard Worker void addAssignEdge(Value *From, Value *To, int64_t Offset = 0) { 195*9880d681SAndroid Build Coastguard Worker assert(From != nullptr && To != nullptr); 196*9880d681SAndroid Build Coastguard Worker if (!From->getType()->isPointerTy() || !To->getType()->isPointerTy()) 197*9880d681SAndroid Build Coastguard Worker return; 198*9880d681SAndroid Build Coastguard Worker addNode(From); 199*9880d681SAndroid Build Coastguard Worker if (To != From) { 200*9880d681SAndroid Build Coastguard Worker addNode(To); 201*9880d681SAndroid Build Coastguard Worker Graph.addEdge(InstantiatedValue{From, 0}, InstantiatedValue{To, 0}, 202*9880d681SAndroid Build Coastguard Worker Offset); 203*9880d681SAndroid Build Coastguard Worker } 204*9880d681SAndroid Build Coastguard Worker } 205*9880d681SAndroid Build Coastguard Worker addDerefEdge(Value * From,Value * To)206*9880d681SAndroid Build Coastguard Worker void addDerefEdge(Value *From, Value *To) { 207*9880d681SAndroid Build Coastguard Worker assert(From != nullptr && To != nullptr); 208*9880d681SAndroid Build Coastguard Worker if (!From->getType()->isPointerTy() || !To->getType()->isPointerTy()) 209*9880d681SAndroid Build Coastguard Worker return; 210*9880d681SAndroid Build Coastguard Worker addNode(From); 211*9880d681SAndroid Build Coastguard Worker addNode(To); 212*9880d681SAndroid Build Coastguard Worker Graph.addNode(InstantiatedValue{From, 1}); 213*9880d681SAndroid Build Coastguard Worker Graph.addEdge(InstantiatedValue{From, 1}, InstantiatedValue{To, 0}); 214*9880d681SAndroid Build Coastguard Worker } 215*9880d681SAndroid Build Coastguard Worker 216*9880d681SAndroid Build Coastguard Worker public: GetEdgesVisitor(CFLGraphBuilder & Builder)217*9880d681SAndroid Build Coastguard Worker GetEdgesVisitor(CFLGraphBuilder &Builder) 218*9880d681SAndroid Build Coastguard Worker : AA(Builder.Analysis), TLI(Builder.TLI), Graph(Builder.Graph), 219*9880d681SAndroid Build Coastguard Worker ReturnValues(Builder.ReturnedValues) {} 220*9880d681SAndroid Build Coastguard Worker visitInstruction(Instruction &)221*9880d681SAndroid Build Coastguard Worker void visitInstruction(Instruction &) { 222*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unsupported instruction encountered"); 223*9880d681SAndroid Build Coastguard Worker } 224*9880d681SAndroid Build Coastguard Worker visitReturnInst(ReturnInst & Inst)225*9880d681SAndroid Build Coastguard Worker void visitReturnInst(ReturnInst &Inst) { 226*9880d681SAndroid Build Coastguard Worker if (auto RetVal = Inst.getReturnValue()) { 227*9880d681SAndroid Build Coastguard Worker if (RetVal->getType()->isPointerTy()) { 228*9880d681SAndroid Build Coastguard Worker addNode(RetVal); 229*9880d681SAndroid Build Coastguard Worker ReturnValues.push_back(RetVal); 230*9880d681SAndroid Build Coastguard Worker } 231*9880d681SAndroid Build Coastguard Worker } 232*9880d681SAndroid Build Coastguard Worker } 233*9880d681SAndroid Build Coastguard Worker visitPtrToIntInst(PtrToIntInst & Inst)234*9880d681SAndroid Build Coastguard Worker void visitPtrToIntInst(PtrToIntInst &Inst) { 235*9880d681SAndroid Build Coastguard Worker auto *Ptr = Inst.getOperand(0); 236*9880d681SAndroid Build Coastguard Worker addNode(Ptr, getAttrEscaped()); 237*9880d681SAndroid Build Coastguard Worker } 238*9880d681SAndroid Build Coastguard Worker visitIntToPtrInst(IntToPtrInst & Inst)239*9880d681SAndroid Build Coastguard Worker void visitIntToPtrInst(IntToPtrInst &Inst) { 240*9880d681SAndroid Build Coastguard Worker auto *Ptr = &Inst; 241*9880d681SAndroid Build Coastguard Worker addNode(Ptr, getAttrUnknown()); 242*9880d681SAndroid Build Coastguard Worker } 243*9880d681SAndroid Build Coastguard Worker visitCastInst(CastInst & Inst)244*9880d681SAndroid Build Coastguard Worker void visitCastInst(CastInst &Inst) { 245*9880d681SAndroid Build Coastguard Worker auto *Src = Inst.getOperand(0); 246*9880d681SAndroid Build Coastguard Worker addAssignEdge(Src, &Inst); 247*9880d681SAndroid Build Coastguard Worker } 248*9880d681SAndroid Build Coastguard Worker visitBinaryOperator(BinaryOperator & Inst)249*9880d681SAndroid Build Coastguard Worker void visitBinaryOperator(BinaryOperator &Inst) { 250*9880d681SAndroid Build Coastguard Worker auto *Op1 = Inst.getOperand(0); 251*9880d681SAndroid Build Coastguard Worker auto *Op2 = Inst.getOperand(1); 252*9880d681SAndroid Build Coastguard Worker addAssignEdge(Op1, &Inst); 253*9880d681SAndroid Build Coastguard Worker addAssignEdge(Op2, &Inst); 254*9880d681SAndroid Build Coastguard Worker } 255*9880d681SAndroid Build Coastguard Worker visitAtomicCmpXchgInst(AtomicCmpXchgInst & Inst)256*9880d681SAndroid Build Coastguard Worker void visitAtomicCmpXchgInst(AtomicCmpXchgInst &Inst) { 257*9880d681SAndroid Build Coastguard Worker auto *Ptr = Inst.getPointerOperand(); 258*9880d681SAndroid Build Coastguard Worker auto *Val = Inst.getNewValOperand(); 259*9880d681SAndroid Build Coastguard Worker addDerefEdge(Ptr, Val); 260*9880d681SAndroid Build Coastguard Worker } 261*9880d681SAndroid Build Coastguard Worker visitAtomicRMWInst(AtomicRMWInst & Inst)262*9880d681SAndroid Build Coastguard Worker void visitAtomicRMWInst(AtomicRMWInst &Inst) { 263*9880d681SAndroid Build Coastguard Worker auto *Ptr = Inst.getPointerOperand(); 264*9880d681SAndroid Build Coastguard Worker auto *Val = Inst.getValOperand(); 265*9880d681SAndroid Build Coastguard Worker addDerefEdge(Ptr, Val); 266*9880d681SAndroid Build Coastguard Worker } 267*9880d681SAndroid Build Coastguard Worker visitPHINode(PHINode & Inst)268*9880d681SAndroid Build Coastguard Worker void visitPHINode(PHINode &Inst) { 269*9880d681SAndroid Build Coastguard Worker for (Value *Val : Inst.incoming_values()) 270*9880d681SAndroid Build Coastguard Worker addAssignEdge(Val, &Inst); 271*9880d681SAndroid Build Coastguard Worker } 272*9880d681SAndroid Build Coastguard Worker visitGetElementPtrInst(GetElementPtrInst & Inst)273*9880d681SAndroid Build Coastguard Worker void visitGetElementPtrInst(GetElementPtrInst &Inst) { 274*9880d681SAndroid Build Coastguard Worker auto *Op = Inst.getPointerOperand(); 275*9880d681SAndroid Build Coastguard Worker addAssignEdge(Op, &Inst); 276*9880d681SAndroid Build Coastguard Worker } 277*9880d681SAndroid Build Coastguard Worker visitSelectInst(SelectInst & Inst)278*9880d681SAndroid Build Coastguard Worker void visitSelectInst(SelectInst &Inst) { 279*9880d681SAndroid Build Coastguard Worker // Condition is not processed here (The actual statement producing 280*9880d681SAndroid Build Coastguard Worker // the condition result is processed elsewhere). For select, the 281*9880d681SAndroid Build Coastguard Worker // condition is evaluated, but not loaded, stored, or assigned 282*9880d681SAndroid Build Coastguard Worker // simply as a result of being the condition of a select. 283*9880d681SAndroid Build Coastguard Worker 284*9880d681SAndroid Build Coastguard Worker auto *TrueVal = Inst.getTrueValue(); 285*9880d681SAndroid Build Coastguard Worker auto *FalseVal = Inst.getFalseValue(); 286*9880d681SAndroid Build Coastguard Worker addAssignEdge(TrueVal, &Inst); 287*9880d681SAndroid Build Coastguard Worker addAssignEdge(FalseVal, &Inst); 288*9880d681SAndroid Build Coastguard Worker } 289*9880d681SAndroid Build Coastguard Worker visitAllocaInst(AllocaInst & Inst)290*9880d681SAndroid Build Coastguard Worker void visitAllocaInst(AllocaInst &Inst) { addNode(&Inst); } 291*9880d681SAndroid Build Coastguard Worker visitLoadInst(LoadInst & Inst)292*9880d681SAndroid Build Coastguard Worker void visitLoadInst(LoadInst &Inst) { 293*9880d681SAndroid Build Coastguard Worker auto *Ptr = Inst.getPointerOperand(); 294*9880d681SAndroid Build Coastguard Worker auto *Val = &Inst; 295*9880d681SAndroid Build Coastguard Worker addDerefEdge(Ptr, Val); 296*9880d681SAndroid Build Coastguard Worker } 297*9880d681SAndroid Build Coastguard Worker visitStoreInst(StoreInst & Inst)298*9880d681SAndroid Build Coastguard Worker void visitStoreInst(StoreInst &Inst) { 299*9880d681SAndroid Build Coastguard Worker auto *Ptr = Inst.getPointerOperand(); 300*9880d681SAndroid Build Coastguard Worker auto *Val = Inst.getValueOperand(); 301*9880d681SAndroid Build Coastguard Worker addDerefEdge(Ptr, Val); 302*9880d681SAndroid Build Coastguard Worker } 303*9880d681SAndroid Build Coastguard Worker visitVAArgInst(VAArgInst & Inst)304*9880d681SAndroid Build Coastguard Worker void visitVAArgInst(VAArgInst &Inst) { 305*9880d681SAndroid Build Coastguard Worker // We can't fully model va_arg here. For *Ptr = Inst.getOperand(0), it 306*9880d681SAndroid Build Coastguard Worker // does 307*9880d681SAndroid Build Coastguard Worker // two things: 308*9880d681SAndroid Build Coastguard Worker // 1. Loads a value from *((T*)*Ptr). 309*9880d681SAndroid Build Coastguard Worker // 2. Increments (stores to) *Ptr by some target-specific amount. 310*9880d681SAndroid Build Coastguard Worker // For now, we'll handle this like a landingpad instruction (by placing 311*9880d681SAndroid Build Coastguard Worker // the 312*9880d681SAndroid Build Coastguard Worker // result in its own group, and having that group alias externals). 313*9880d681SAndroid Build Coastguard Worker addNode(&Inst, getAttrUnknown()); 314*9880d681SAndroid Build Coastguard Worker } 315*9880d681SAndroid Build Coastguard Worker isFunctionExternal(Function * Fn)316*9880d681SAndroid Build Coastguard Worker static bool isFunctionExternal(Function *Fn) { 317*9880d681SAndroid Build Coastguard Worker return !Fn->hasExactDefinition(); 318*9880d681SAndroid Build Coastguard Worker } 319*9880d681SAndroid Build Coastguard Worker tryInterproceduralAnalysis(CallSite CS,const SmallVectorImpl<Function * > & Fns)320*9880d681SAndroid Build Coastguard Worker bool tryInterproceduralAnalysis(CallSite CS, 321*9880d681SAndroid Build Coastguard Worker const SmallVectorImpl<Function *> &Fns) { 322*9880d681SAndroid Build Coastguard Worker assert(Fns.size() > 0); 323*9880d681SAndroid Build Coastguard Worker 324*9880d681SAndroid Build Coastguard Worker if (CS.arg_size() > MaxSupportedArgsInSummary) 325*9880d681SAndroid Build Coastguard Worker return false; 326*9880d681SAndroid Build Coastguard Worker 327*9880d681SAndroid Build Coastguard Worker // Exit early if we'll fail anyway 328*9880d681SAndroid Build Coastguard Worker for (auto *Fn : Fns) { 329*9880d681SAndroid Build Coastguard Worker if (isFunctionExternal(Fn) || Fn->isVarArg()) 330*9880d681SAndroid Build Coastguard Worker return false; 331*9880d681SAndroid Build Coastguard Worker // Fail if the caller does not provide enough arguments 332*9880d681SAndroid Build Coastguard Worker assert(Fn->arg_size() <= CS.arg_size()); 333*9880d681SAndroid Build Coastguard Worker if (!AA.getAliasSummary(*Fn)) 334*9880d681SAndroid Build Coastguard Worker return false; 335*9880d681SAndroid Build Coastguard Worker } 336*9880d681SAndroid Build Coastguard Worker 337*9880d681SAndroid Build Coastguard Worker for (auto *Fn : Fns) { 338*9880d681SAndroid Build Coastguard Worker auto Summary = AA.getAliasSummary(*Fn); 339*9880d681SAndroid Build Coastguard Worker assert(Summary != nullptr); 340*9880d681SAndroid Build Coastguard Worker 341*9880d681SAndroid Build Coastguard Worker auto &RetParamRelations = Summary->RetParamRelations; 342*9880d681SAndroid Build Coastguard Worker for (auto &Relation : RetParamRelations) { 343*9880d681SAndroid Build Coastguard Worker auto IRelation = instantiateExternalRelation(Relation, CS); 344*9880d681SAndroid Build Coastguard Worker if (IRelation.hasValue()) { 345*9880d681SAndroid Build Coastguard Worker Graph.addNode(IRelation->From); 346*9880d681SAndroid Build Coastguard Worker Graph.addNode(IRelation->To); 347*9880d681SAndroid Build Coastguard Worker Graph.addEdge(IRelation->From, IRelation->To); 348*9880d681SAndroid Build Coastguard Worker } 349*9880d681SAndroid Build Coastguard Worker } 350*9880d681SAndroid Build Coastguard Worker 351*9880d681SAndroid Build Coastguard Worker auto &RetParamAttributes = Summary->RetParamAttributes; 352*9880d681SAndroid Build Coastguard Worker for (auto &Attribute : RetParamAttributes) { 353*9880d681SAndroid Build Coastguard Worker auto IAttr = instantiateExternalAttribute(Attribute, CS); 354*9880d681SAndroid Build Coastguard Worker if (IAttr.hasValue()) 355*9880d681SAndroid Build Coastguard Worker Graph.addNode(IAttr->IValue, IAttr->Attr); 356*9880d681SAndroid Build Coastguard Worker } 357*9880d681SAndroid Build Coastguard Worker } 358*9880d681SAndroid Build Coastguard Worker 359*9880d681SAndroid Build Coastguard Worker return true; 360*9880d681SAndroid Build Coastguard Worker } 361*9880d681SAndroid Build Coastguard Worker visitCallSite(CallSite CS)362*9880d681SAndroid Build Coastguard Worker void visitCallSite(CallSite CS) { 363*9880d681SAndroid Build Coastguard Worker auto Inst = CS.getInstruction(); 364*9880d681SAndroid Build Coastguard Worker 365*9880d681SAndroid Build Coastguard Worker // Make sure all arguments and return value are added to the graph first 366*9880d681SAndroid Build Coastguard Worker for (Value *V : CS.args()) 367*9880d681SAndroid Build Coastguard Worker if (V->getType()->isPointerTy()) 368*9880d681SAndroid Build Coastguard Worker addNode(V); 369*9880d681SAndroid Build Coastguard Worker if (Inst->getType()->isPointerTy()) 370*9880d681SAndroid Build Coastguard Worker addNode(Inst); 371*9880d681SAndroid Build Coastguard Worker 372*9880d681SAndroid Build Coastguard Worker // Check if Inst is a call to a library function that 373*9880d681SAndroid Build Coastguard Worker // allocates/deallocates 374*9880d681SAndroid Build Coastguard Worker // on the heap. Those kinds of functions do not introduce any aliases. 375*9880d681SAndroid Build Coastguard Worker // TODO: address other common library functions such as realloc(), 376*9880d681SAndroid Build Coastguard Worker // strdup(), 377*9880d681SAndroid Build Coastguard Worker // etc. 378*9880d681SAndroid Build Coastguard Worker if (isMallocLikeFn(Inst, &TLI) || isCallocLikeFn(Inst, &TLI) || 379*9880d681SAndroid Build Coastguard Worker isFreeCall(Inst, &TLI)) 380*9880d681SAndroid Build Coastguard Worker return; 381*9880d681SAndroid Build Coastguard Worker 382*9880d681SAndroid Build Coastguard Worker // TODO: Add support for noalias args/all the other fun function 383*9880d681SAndroid Build Coastguard Worker // attributes 384*9880d681SAndroid Build Coastguard Worker // that we can tack on. 385*9880d681SAndroid Build Coastguard Worker SmallVector<Function *, 4> Targets; 386*9880d681SAndroid Build Coastguard Worker if (getPossibleTargets(CS, Targets)) 387*9880d681SAndroid Build Coastguard Worker if (tryInterproceduralAnalysis(CS, Targets)) 388*9880d681SAndroid Build Coastguard Worker return; 389*9880d681SAndroid Build Coastguard Worker 390*9880d681SAndroid Build Coastguard Worker // Because the function is opaque, we need to note that anything 391*9880d681SAndroid Build Coastguard Worker // could have happened to the arguments (unless the function is marked 392*9880d681SAndroid Build Coastguard Worker // readonly or readnone), and that the result could alias just about 393*9880d681SAndroid Build Coastguard Worker // anything, too (unless the result is marked noalias). 394*9880d681SAndroid Build Coastguard Worker if (!CS.onlyReadsMemory()) 395*9880d681SAndroid Build Coastguard Worker for (Value *V : CS.args()) { 396*9880d681SAndroid Build Coastguard Worker if (V->getType()->isPointerTy()) { 397*9880d681SAndroid Build Coastguard Worker // The argument itself escapes. 398*9880d681SAndroid Build Coastguard Worker Graph.addAttr(InstantiatedValue{V, 0}, getAttrEscaped()); 399*9880d681SAndroid Build Coastguard Worker // The fate of argument memory is unknown. Note that since 400*9880d681SAndroid Build Coastguard Worker // AliasAttrs is transitive with respect to dereference, we only 401*9880d681SAndroid Build Coastguard Worker // need to specify it for the first-level memory. 402*9880d681SAndroid Build Coastguard Worker Graph.addNode(InstantiatedValue{V, 1}, getAttrUnknown()); 403*9880d681SAndroid Build Coastguard Worker } 404*9880d681SAndroid Build Coastguard Worker } 405*9880d681SAndroid Build Coastguard Worker 406*9880d681SAndroid Build Coastguard Worker if (Inst->getType()->isPointerTy()) { 407*9880d681SAndroid Build Coastguard Worker auto *Fn = CS.getCalledFunction(); 408*9880d681SAndroid Build Coastguard Worker if (Fn == nullptr || !Fn->doesNotAlias(0)) 409*9880d681SAndroid Build Coastguard Worker // No need to call addNode() since we've added Inst at the 410*9880d681SAndroid Build Coastguard Worker // beginning of this function and we know it is not a global. 411*9880d681SAndroid Build Coastguard Worker Graph.addAttr(InstantiatedValue{Inst, 0}, getAttrUnknown()); 412*9880d681SAndroid Build Coastguard Worker } 413*9880d681SAndroid Build Coastguard Worker } 414*9880d681SAndroid Build Coastguard Worker 415*9880d681SAndroid Build Coastguard Worker /// Because vectors/aggregates are immutable and unaddressable, there's 416*9880d681SAndroid Build Coastguard Worker /// nothing we can do to coax a value out of them, other than calling 417*9880d681SAndroid Build Coastguard Worker /// Extract{Element,Value}. We can effectively treat them as pointers to 418*9880d681SAndroid Build Coastguard Worker /// arbitrary memory locations we can store in and load from. visitExtractElementInst(ExtractElementInst & Inst)419*9880d681SAndroid Build Coastguard Worker void visitExtractElementInst(ExtractElementInst &Inst) { 420*9880d681SAndroid Build Coastguard Worker auto *Ptr = Inst.getVectorOperand(); 421*9880d681SAndroid Build Coastguard Worker auto *Val = &Inst; 422*9880d681SAndroid Build Coastguard Worker addDerefEdge(Ptr, Val); 423*9880d681SAndroid Build Coastguard Worker } 424*9880d681SAndroid Build Coastguard Worker visitInsertElementInst(InsertElementInst & Inst)425*9880d681SAndroid Build Coastguard Worker void visitInsertElementInst(InsertElementInst &Inst) { 426*9880d681SAndroid Build Coastguard Worker auto *Vec = Inst.getOperand(0); 427*9880d681SAndroid Build Coastguard Worker auto *Val = Inst.getOperand(1); 428*9880d681SAndroid Build Coastguard Worker addAssignEdge(Vec, &Inst); 429*9880d681SAndroid Build Coastguard Worker addDerefEdge(&Inst, Val); 430*9880d681SAndroid Build Coastguard Worker } 431*9880d681SAndroid Build Coastguard Worker visitLandingPadInst(LandingPadInst & Inst)432*9880d681SAndroid Build Coastguard Worker void visitLandingPadInst(LandingPadInst &Inst) { 433*9880d681SAndroid Build Coastguard Worker // Exceptions come from "nowhere", from our analysis' perspective. 434*9880d681SAndroid Build Coastguard Worker // So we place the instruction its own group, noting that said group may 435*9880d681SAndroid Build Coastguard Worker // alias externals 436*9880d681SAndroid Build Coastguard Worker addNode(&Inst, getAttrUnknown()); 437*9880d681SAndroid Build Coastguard Worker } 438*9880d681SAndroid Build Coastguard Worker visitInsertValueInst(InsertValueInst & Inst)439*9880d681SAndroid Build Coastguard Worker void visitInsertValueInst(InsertValueInst &Inst) { 440*9880d681SAndroid Build Coastguard Worker auto *Agg = Inst.getOperand(0); 441*9880d681SAndroid Build Coastguard Worker auto *Val = Inst.getOperand(1); 442*9880d681SAndroid Build Coastguard Worker addAssignEdge(Agg, &Inst); 443*9880d681SAndroid Build Coastguard Worker addDerefEdge(&Inst, Val); 444*9880d681SAndroid Build Coastguard Worker } 445*9880d681SAndroid Build Coastguard Worker visitExtractValueInst(ExtractValueInst & Inst)446*9880d681SAndroid Build Coastguard Worker void visitExtractValueInst(ExtractValueInst &Inst) { 447*9880d681SAndroid Build Coastguard Worker auto *Ptr = Inst.getAggregateOperand(); 448*9880d681SAndroid Build Coastguard Worker addDerefEdge(Ptr, &Inst); 449*9880d681SAndroid Build Coastguard Worker } 450*9880d681SAndroid Build Coastguard Worker visitShuffleVectorInst(ShuffleVectorInst & Inst)451*9880d681SAndroid Build Coastguard Worker void visitShuffleVectorInst(ShuffleVectorInst &Inst) { 452*9880d681SAndroid Build Coastguard Worker auto *From1 = Inst.getOperand(0); 453*9880d681SAndroid Build Coastguard Worker auto *From2 = Inst.getOperand(1); 454*9880d681SAndroid Build Coastguard Worker addAssignEdge(From1, &Inst); 455*9880d681SAndroid Build Coastguard Worker addAssignEdge(From2, &Inst); 456*9880d681SAndroid Build Coastguard Worker } 457*9880d681SAndroid Build Coastguard Worker visitConstantExpr(ConstantExpr * CE)458*9880d681SAndroid Build Coastguard Worker void visitConstantExpr(ConstantExpr *CE) { 459*9880d681SAndroid Build Coastguard Worker switch (CE->getOpcode()) { 460*9880d681SAndroid Build Coastguard Worker default: 461*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Unknown instruction type encountered!"); 462*9880d681SAndroid Build Coastguard Worker // Build the switch statement using the Instruction.def file. 463*9880d681SAndroid Build Coastguard Worker #define HANDLE_INST(NUM, OPCODE, CLASS) \ 464*9880d681SAndroid Build Coastguard Worker case Instruction::OPCODE: \ 465*9880d681SAndroid Build Coastguard Worker this->visit##OPCODE(*(CLASS *)CE); \ 466*9880d681SAndroid Build Coastguard Worker break; 467*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Instruction.def" 468*9880d681SAndroid Build Coastguard Worker } 469*9880d681SAndroid Build Coastguard Worker } 470*9880d681SAndroid Build Coastguard Worker }; 471*9880d681SAndroid Build Coastguard Worker 472*9880d681SAndroid Build Coastguard Worker // Helper functions 473*9880d681SAndroid Build Coastguard Worker 474*9880d681SAndroid Build Coastguard Worker // Determines whether or not we an instruction is useless to us (e.g. 475*9880d681SAndroid Build Coastguard Worker // FenceInst) hasUsefulEdges(Instruction * Inst)476*9880d681SAndroid Build Coastguard Worker static bool hasUsefulEdges(Instruction *Inst) { 477*9880d681SAndroid Build Coastguard Worker bool IsNonInvokeRetTerminator = isa<TerminatorInst>(Inst) && 478*9880d681SAndroid Build Coastguard Worker !isa<InvokeInst>(Inst) && 479*9880d681SAndroid Build Coastguard Worker !isa<ReturnInst>(Inst); 480*9880d681SAndroid Build Coastguard Worker return !isa<CmpInst>(Inst) && !isa<FenceInst>(Inst) && 481*9880d681SAndroid Build Coastguard Worker !IsNonInvokeRetTerminator; 482*9880d681SAndroid Build Coastguard Worker } 483*9880d681SAndroid Build Coastguard Worker addArgumentToGraph(Argument & Arg)484*9880d681SAndroid Build Coastguard Worker void addArgumentToGraph(Argument &Arg) { 485*9880d681SAndroid Build Coastguard Worker if (Arg.getType()->isPointerTy()) { 486*9880d681SAndroid Build Coastguard Worker Graph.addNode(InstantiatedValue{&Arg, 0}, 487*9880d681SAndroid Build Coastguard Worker getGlobalOrArgAttrFromValue(Arg)); 488*9880d681SAndroid Build Coastguard Worker // Pointees of a formal parameter is known to the caller 489*9880d681SAndroid Build Coastguard Worker Graph.addNode(InstantiatedValue{&Arg, 1}, getAttrCaller()); 490*9880d681SAndroid Build Coastguard Worker } 491*9880d681SAndroid Build Coastguard Worker } 492*9880d681SAndroid Build Coastguard Worker 493*9880d681SAndroid Build Coastguard Worker // Given an Instruction, this will add it to the graph, along with any 494*9880d681SAndroid Build Coastguard Worker // Instructions that are potentially only available from said Instruction 495*9880d681SAndroid Build Coastguard Worker // For example, given the following line: 496*9880d681SAndroid Build Coastguard Worker // %0 = load i16* getelementptr ([1 x i16]* @a, 0, 0), align 2 497*9880d681SAndroid Build Coastguard Worker // addInstructionToGraph would add both the `load` and `getelementptr` 498*9880d681SAndroid Build Coastguard Worker // instructions to the graph appropriately. addInstructionToGraph(GetEdgesVisitor & Visitor,Instruction & Inst)499*9880d681SAndroid Build Coastguard Worker void addInstructionToGraph(GetEdgesVisitor &Visitor, Instruction &Inst) { 500*9880d681SAndroid Build Coastguard Worker if (!hasUsefulEdges(&Inst)) 501*9880d681SAndroid Build Coastguard Worker return; 502*9880d681SAndroid Build Coastguard Worker 503*9880d681SAndroid Build Coastguard Worker Visitor.visit(Inst); 504*9880d681SAndroid Build Coastguard Worker } 505*9880d681SAndroid Build Coastguard Worker 506*9880d681SAndroid Build Coastguard Worker // Builds the graph needed for constructing the StratifiedSets for the given 507*9880d681SAndroid Build Coastguard Worker // function buildGraphFrom(Function & Fn)508*9880d681SAndroid Build Coastguard Worker void buildGraphFrom(Function &Fn) { 509*9880d681SAndroid Build Coastguard Worker GetEdgesVisitor Visitor(*this); 510*9880d681SAndroid Build Coastguard Worker 511*9880d681SAndroid Build Coastguard Worker for (auto &Bb : Fn.getBasicBlockList()) 512*9880d681SAndroid Build Coastguard Worker for (auto &Inst : Bb.getInstList()) 513*9880d681SAndroid Build Coastguard Worker addInstructionToGraph(Visitor, Inst); 514*9880d681SAndroid Build Coastguard Worker 515*9880d681SAndroid Build Coastguard Worker for (auto &Arg : Fn.args()) 516*9880d681SAndroid Build Coastguard Worker addArgumentToGraph(Arg); 517*9880d681SAndroid Build Coastguard Worker } 518*9880d681SAndroid Build Coastguard Worker 519*9880d681SAndroid Build Coastguard Worker public: CFLGraphBuilder(CFLAA & Analysis,const TargetLibraryInfo & TLI,Function & Fn)520*9880d681SAndroid Build Coastguard Worker CFLGraphBuilder(CFLAA &Analysis, const TargetLibraryInfo &TLI, Function &Fn) 521*9880d681SAndroid Build Coastguard Worker : Analysis(Analysis), TLI(TLI) { 522*9880d681SAndroid Build Coastguard Worker buildGraphFrom(Fn); 523*9880d681SAndroid Build Coastguard Worker } 524*9880d681SAndroid Build Coastguard Worker getCFLGraph()525*9880d681SAndroid Build Coastguard Worker const CFLGraph &getCFLGraph() const { return Graph; } getReturnValues()526*9880d681SAndroid Build Coastguard Worker const SmallVector<Value *, 4> &getReturnValues() const { 527*9880d681SAndroid Build Coastguard Worker return ReturnedValues; 528*9880d681SAndroid Build Coastguard Worker } 529*9880d681SAndroid Build Coastguard Worker }; 530*9880d681SAndroid Build Coastguard Worker } 531*9880d681SAndroid Build Coastguard Worker } 532*9880d681SAndroid Build Coastguard Worker 533*9880d681SAndroid Build Coastguard Worker #endif 534