xref: /aosp_15_r20/external/llvm/lib/Analysis/CFLGraph.h (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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