Skip to content

Commit 4e0c5fb

Browse files
committed
Merging fixed array bounds changes
2 parents 6a05516 + b59378a commit 4e0c5fb

17 files changed

+744
-329
lines changed

clang/include/clang/3C/ABounds.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,13 @@ class ABounds {
4444
virtual ~ABounds() { }
4545

4646
virtual std::string mkString(AVarBoundsInfo *) = 0;
47-
virtual bool areSame(ABounds *) = 0;
47+
virtual bool areSame(ABounds *, AVarBoundsInfo *) = 0;
4848
virtual BoundsKey getBKey() = 0;
4949
virtual ABounds* makeCopy(BoundsKey NK) = 0;
5050

5151
// Set that maintains all the bound keys that are used inin
52+
// TODO: Is this still needed?
5253
static std::set<BoundsKey> KeysUsedInBounds;
53-
5454
static bool isKeyUsedInBounds(BoundsKey ToCheck);
5555

5656
static ABounds *getBoundsInfo(AVarBoundsInfo *AVBInfo,
@@ -66,7 +66,7 @@ class CountBound : public ABounds {
6666
virtual ~CountBound() { }
6767

6868
std::string mkString(AVarBoundsInfo *ABI) override ;
69-
bool areSame(ABounds *O) override;
69+
bool areSame(ABounds *O, AVarBoundsInfo *ABI) override;
7070
BoundsKey getBKey() override;
7171
ABounds* makeCopy(BoundsKey NK) override;
7272

@@ -88,7 +88,7 @@ class ByteBound : public ABounds {
8888
virtual ~ByteBound() { }
8989

9090
std::string mkString(AVarBoundsInfo *ABI) override ;
91-
bool areSame(ABounds *O) override;
91+
bool areSame(ABounds *O, AVarBoundsInfo *ABI) override;
9292
BoundsKey getBKey() override;
9393
ABounds* makeCopy(BoundsKey NK) override;
9494

@@ -111,7 +111,7 @@ class RangeBound : public ABounds {
111111
virtual ~RangeBound() { }
112112

113113
std::string mkString(AVarBoundsInfo *ABI) override ;
114-
bool areSame(ABounds *O) override;
114+
bool areSame(ABounds *O, AVarBoundsInfo *ABI) override;
115115

116116
BoundsKey getBKey() override {
117117
assert (false && "Not implemented.");

clang/include/clang/3C/AVarBoundsInfo.h

Lines changed: 55 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -89,40 +89,65 @@ enum BoundsPriority {
8989
};
9090

9191
class AVarBoundsInfo;
92-
92+
typedef std::map<ABounds::BoundsKind, std::set<BoundsKey>> BndsKindMap;
9393
// The main class that handles figuring out bounds of arr variables.
9494
class AvarBoundsInference {
9595
public:
96-
AvarBoundsInference(AVarBoundsInfo *BoundsInfo) : BI(BoundsInfo) { }
96+
AvarBoundsInference(AVarBoundsInfo *BoundsInfo) : BI(BoundsInfo) {
97+
clearInferredBounds();
98+
}
99+
100+
// Clear all possible inferred bounds for all the BoundsKeys
101+
void clearInferredBounds() {
102+
CurrIterInferBounds.clear();
103+
BKsFailedFlowInference.clear();
104+
}
97105

98106
// Infer bounds for the given key from the set of given ARR atoms.
99107
// The flag FromPB requests the inference to use potential length variables.
100108
bool inferBounds(BoundsKey K, AVarGraph &BKGraph, bool FromPB = false);
109+
110+
// Get a consistent bound for all the arrays whose bounds have been
111+
// inferred.
112+
bool convergeInferredBounds();
101113
private:
102-
bool inferPossibleBounds(BoundsKey K, ABounds *SB,
103-
AVarGraph &BKGraph,
104-
std::set<ABounds *> &EB);
114+
// Find all the reachable variables form FromVarK that are visible
115+
// in DstScope
116+
bool getReachableBoundKeys(const ProgramVarScope *DstScope,
117+
BoundsKey FromVarK,
118+
std::set<BoundsKey> &PotK,
119+
AVarGraph &BKGraph,
120+
bool CheckImmediate = false);
105121

106-
bool intersectBounds(std::set<ProgramVar *> &ProgVars,
107-
ABounds::BoundsKind BK,
108-
std::set<ABounds *> &CurrB);
122+
// Check if bounds specified by Bnds are declared bounds of K.
123+
bool areDeclaredBounds(BoundsKey K,
124+
const std::pair<ABounds::BoundsKind,
125+
std::set<BoundsKey>> &Bnds);
109126

110-
bool getRelevantBounds(std::set<BoundsKey> &RBKeys,
111-
std::set<ABounds *> &ResBounds);
127+
// Get all the bounds of the given array i.e., BK
128+
bool getRelevantBounds(BoundsKey BK,
129+
BndsKindMap &ResBounds);
112130

113-
bool predictBounds(BoundsKey K, std::set<BoundsKey> &Neighbours,
114-
AVarGraph &BKGraph,
115-
ABounds **KB);
131+
// Predict possible bounds for DstArrK from the bounds of Neighbours.
132+
// Return true if there is any change in the captured bounds information.
133+
bool predictBounds(BoundsKey DstArrK, std::set<BoundsKey> &Neighbours,
134+
AVarGraph &BKGraph);
116135

117136

118-
void mergeReachableProgramVars(std::set<ProgramVar *> &AllVars);
137+
void mergeReachableProgramVars(std::set<BoundsKey> &AllVars);
119138

120139
AVarBoundsInfo *BI;
140+
141+
// Potential Bounds for each bounds key inferred for the current iteration.
142+
std::map<BoundsKey, BndsKindMap> CurrIterInferBounds;
143+
// BoundsKey that failed the flow inference.
144+
std::set<BoundsKey> BKsFailedFlowInference;
121145
};
122146

123147
class AVarBoundsInfo {
124148
public:
125-
AVarBoundsInfo() : ProgVarGraph(this), CtxSensProgVarGraph(this) {
149+
AVarBoundsInfo() : ProgVarGraph(this), CtxSensProgVarGraph(this),
150+
RevCtxSensProgVarGraph(this) {
126151
BCount = 1;
127152
PVarInfo.clear();
128153
InProgramArrPtrBoundsKeys.clear();
@@ -227,6 +252,8 @@ class AVarBoundsInfo {
227252
const CVarSet &SrcCVarSet,
228253
bool JsonFormat = false) const;
229254

255+
bool areSameProgramVar(BoundsKey B1, BoundsKey B2);
256+
230257
private:
231258
friend class AvarBoundsInference;
232259

@@ -238,7 +265,7 @@ class AVarBoundsInfo {
238265
BoundsKey BCount;
239266
// Map of VarKeys and corresponding program variables.
240267
std::map<BoundsKey, ProgramVar *> PVarInfo;
241-
// Map of APSInt (constants) and corresponding VarKeys.
268+
// Map of APSInt (constants) and a BoundKey that correspond to it.
242269
std::map<uint64_t, BoundsKey> ConstVarKeys;
243270
// Map of BoundsKey and corresponding prioritized bounds information.
244271
// Note that although each PSL could have multiple ConstraintKeys Ex: **p.
@@ -272,9 +299,11 @@ class AVarBoundsInfo {
272299

273300
// Graph of all program variables.
274301
AVarGraph ProgVarGraph;
275-
// Graph that contains only edges between context-sensitive
276-
// BoundsKey and corresponding original BoundsKey.
302+
// Graph that contains only edges from normal BoundsKey to
303+
// context-sensitive BoundsKey.
277304
AVarGraph CtxSensProgVarGraph;
305+
// Same as above but in the reverse direction.
306+
AVarGraph RevCtxSensProgVarGraph;
278307
// Stats on techniques used to find length for various variables.
279308
AVarBoundsStats BoundsInferStats;
280309
// This is the map of pointer variable bounds key and set of bounds key
@@ -305,19 +334,22 @@ class AVarBoundsInfo {
305334
// Check if the provided bounds key corresponds to function return.
306335
bool isFunctionReturn(BoundsKey BK);
307336

308-
// Of all teh pointer bounds key, find arr pointers.
337+
// Of all the pointer bounds key, find arr pointers.
309338
void computerArrPointers(ProgramInfo *PI, std::set<BoundsKey> &Ret);
310339

340+
// Get all the array pointers that need bounds.
341+
void getBoundsNeededArrPointers(const std::set<BoundsKey> &ArrPtrs,
342+
std::set<BoundsKey> &AB);
343+
311344
// Keep only highest priority bounds for all the provided BoundsKeys
312345
// returns true if any thing changed, else false.
313346
bool keepHighestPriorityBounds(std::set<BoundsKey> &ArrPtrs);
314347

315348
// Perform worklist based inference on the requested array variables using
316-
// the provided graph.
317-
// The flag FromPB requests the algorithm to use potential length variables.
318-
bool performWorkListInference(std::set<BoundsKey> &ArrNeededBounds,
349+
// the provided graph and potential length variables.
350+
bool performWorkListInference(const std::set<BoundsKey> &ArrNeededBounds,
319351
AVarGraph &BKGraph,
320-
bool FromPB = false);
352+
AvarBoundsInference &BI);
321353

322354
void insertParamKey(ParamDeclType ParamDecl, BoundsKey NK);
323355
};

clang/include/clang/3C/ArrayBoundsInferenceConsumer.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,15 @@
2222
class LocalVarABVisitor;
2323
class ConstraintResolver;
2424

25+
class AllocBasedBoundsInference : public ASTConsumer {
26+
public:
27+
explicit AllocBasedBoundsInference(ProgramInfo &I, clang::ASTContext *C) : Info(I) { }
28+
virtual void HandleTranslationUnit(ASTContext &Context);
29+
30+
private:
31+
ProgramInfo &Info;
32+
};
33+
2534
// This class handles determining bounds of global array variables.
2635
// i.e., function parameters, structure fields and global variables.
2736
class GlobalABVisitor: public clang::RecursiveASTVisitor<GlobalABVisitor> {
@@ -96,7 +105,8 @@ class LengthVarInference : public StmtVisitor<LengthVarInference> {
96105
std::unique_ptr<CFG> Cfg;
97106
};
98107

99-
void HandleArrayVariablesBoundsDetection(ASTContext *C, ProgramInfo &I);
108+
void HandleArrayVariablesBoundsDetection(ASTContext *C, ProgramInfo &I,
109+
bool UseHeuristics = true);
100110

101111
// Add constraints based on heuristics to the parameters of the
102112
// provided function.

clang/include/clang/3C/ConstraintsGraph.h

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ class DataGraph :
114114
N = nullptr;
115115
}
116116
this->Nodes.clear();
117+
invalidateBFSCache();
117118
}
118119

119120
void removeEdge(Data Src, Data Dst) {
@@ -126,15 +127,27 @@ class DataGraph :
126127
(*NDst)->removeEdge(*E);
127128
delete E;
128129
}
130+
invalidateBFSCache();
129131
}
130132

131133
void addEdge(Data L, Data R) {
132134
NodeType *BL = this->findOrCreateNode(L);
133135
NodeType *BR = this->findOrCreateNode(R);
134136
BL->connectTo(*BR);
137+
invalidateBFSCache();
135138
}
136139

137-
bool getNeighbors(Data D, std::set<Data> &DataSet, bool Succ){
140+
void addUniqueEdge(Data L, Data R) {
141+
NodeType *BL = this->findOrCreateNode(L);
142+
NodeType *BR = this->findOrCreateNode(R);
143+
llvm::SmallVector<EdgeType*, 10> Edges;
144+
BL->findEdgesTo(*BR, Edges);
145+
if (Edges.empty()) {
146+
addEdge(L, R);
147+
}
148+
}
149+
150+
bool getNeighbors(Data D, std::set<Data> &DataSet, bool Succ) {
138151
auto *N = this->findNode(NodeType(D));
139152
if (N == this->end())
140153
return false;
@@ -161,8 +174,16 @@ class DataGraph :
161174
auto *N = this->findNode(NodeType(Start));
162175
if (N == this->end())
163176
return;
164-
for (auto TNode : llvm::breadth_first(*N))
165-
Fn(TNode->getData());
177+
// Insert into BFS cache.
178+
if (BFSCache.find(Start) == BFSCache.end()) {
179+
std::set<Data> ReachableNodes;
180+
for (auto TNode : llvm::breadth_first(*N)) {
181+
ReachableNodes.insert(TNode->getData());
182+
}
183+
BFSCache[Start] = ReachableNodes;
184+
}
185+
for (auto SN : BFSCache[Start])
186+
Fn(SN);
166187
}
167188

168189
protected:
@@ -183,6 +204,11 @@ class DataGraph :
183204
template <typename G>
184205
friend struct llvm::GraphTraits;
185206
friend class GraphVizOutputGraph;
207+
std::map<Data, std::set<Data>> BFSCache;
208+
209+
void invalidateBFSCache() {
210+
BFSCache.clear();
211+
}
186212
};
187213

188214
// Specialize the graph for the checked and pointer type constraint graphs. This

clang/include/clang/3C/ProgramVar.h

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#include "clang/AST/ASTContext.h"
2020
#include "clang/3C/PersistentSourceLoc.h"
2121

22+
// Unique ID for a program variable or constant literal, both of
23+
// which could serve as bounds
2224
typedef uint32_t BoundsKey;
2325

2426
// Class representing scope of a program variable.
@@ -27,9 +29,9 @@ class ProgramVarScope {
2729
enum ScopeKind {
2830
// Function scope.
2931
FunctionScopeKind,
30-
// Function parameter scope.
32+
// Parameters of a particular function.
3133
FunctionParamScopeKind,
32-
// Context sensitive argument scope.
34+
// All arguments to a particular call
3335
CtxFunctionArgScopeKind,
3436
// Struct scope.
3537
StructScopeKind,
@@ -215,6 +217,17 @@ class CtxFunctionArgScope : public FunctionParamScope {
215217
const PersistentSourceLoc &CtxPSL) :
216218
FunctionParamScope(FN, IsSt) {
217219
PSL = CtxPSL;
220+
std::string FileName = PSL.getFileName();
221+
CtxIDStr = "";
222+
if (!FileName.empty()) {
223+
llvm::sys::fs::UniqueID UId;
224+
if (llvm::sys::fs::getUniqueID(FileName, UId)) {
225+
CtxIDStr = std::to_string(UId.getDevice()) + ":" +
226+
std::to_string(UId.getFile()) + ":";
227+
}
228+
}
229+
CtxIDStr += std::to_string(PSL.getLineNo()) + ":" +
230+
std::to_string(PSL.getColSNo());
218231
this->Kind = CtxFunctionArgScopeKind;
219232
}
220233

@@ -261,16 +274,16 @@ class CtxFunctionArgScope : public FunctionParamScope {
261274
}
262275

263276
std::string getStr() const {
264-
return "CtxFuncArg_" + FName;
277+
return FName + "_Ctx_" + CtxIDStr;
265278
}
266279

267280
static const CtxFunctionArgScope *
268281
getCtxFunctionParamScope(const FunctionParamScope *FPS,
269282
const PersistentSourceLoc &PSL);
270283

271284
private:
272-
PersistentSourceLoc PSL;
273-
285+
PersistentSourceLoc PSL; // source code location of this function call
286+
std::string CtxIDStr;
274287
static std::set<CtxFunctionArgScope, PVSComp> AllCtxFnArgScopes;
275288
};
276289

@@ -354,7 +367,7 @@ class ProgramVar {
354367
BoundsKey K;
355368
std::string VarName;
356369
const ProgramVarScope *VScope;
357-
bool IsConstant;
370+
bool IsConstant; // is a literal integer, not a variable
358371
// TODO: All the ProgramVars may not be used. We should try to figure out
359372
// a way to free unused program vars.
360373
static std::set<ProgramVar *> AllProgramVars;

clang/include/clang/3C/Utils.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ bool isFunctionAllocator(std::string FuncName);
124124
// Is the given variable built in type?
125125
bool isPointerType(clang::ValueDecl *VD);
126126

127+
// Is this a pointer or array type?
128+
bool isPtrOrArrayType(const clang::QualType &QT);
129+
127130
// Check if provided type is a var arg type?
128131
bool isVarArgType(const std::string &TypeName);
129132

0 commit comments

Comments
 (0)