1 //=== FlatStore.cpp - Flat region-based store model -------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "clang/GR/PathSensitive/GRState.h"
11 #include "llvm/ADT/ImmutableIntervalMap.h"
12 #include "llvm/Support/ErrorHandling.h"
14 using namespace clang
;
17 // The actual store type.
18 typedef llvm::ImmutableIntervalMap
<SVal
> BindingVal
;
19 typedef llvm::ImmutableMap
<const MemRegion
*, BindingVal
> RegionBindings
;
22 class FlatStoreManager
: public StoreManager
{
23 RegionBindings::Factory RBFactory
;
24 BindingVal::Factory BVFactory
;
27 FlatStoreManager(GRStateManager
&mgr
)
29 RBFactory(mgr
.getAllocator()),
30 BVFactory(mgr
.getAllocator()) {}
32 SVal
Retrieve(Store store
, Loc L
, QualType T
);
33 Store
Bind(Store store
, Loc L
, SVal val
);
34 Store
Remove(Store St
, Loc L
);
35 Store
BindCompoundLiteral(Store store
, const CompoundLiteralExpr
* cl
,
36 const LocationContext
*LC
, SVal v
);
38 Store
getInitialStore(const LocationContext
*InitLoc
) {
39 return RBFactory
.getEmptyMap().getRoot();
42 SubRegionMap
*getSubRegionMap(Store store
) {
46 SVal
ArrayToPointer(Loc Array
);
47 Store
RemoveDeadBindings(Store store
, const StackFrameContext
*LCtx
,
48 SymbolReaper
& SymReaper
,
49 llvm::SmallVectorImpl
<const MemRegion
*>& RegionRoots
){
53 Store
BindDecl(Store store
, const VarRegion
*VR
, SVal initVal
);
55 Store
BindDeclWithNoInit(Store store
, const VarRegion
*VR
);
57 typedef llvm::DenseSet
<SymbolRef
> InvalidatedSymbols
;
59 Store
InvalidateRegions(Store store
, const MemRegion
* const *I
,
60 const MemRegion
* const *E
, const Expr
*Ex
,
61 unsigned Count
, InvalidatedSymbols
*IS
,
62 bool invalidateGlobals
, InvalidatedRegions
*Regions
);
64 void print(Store store
, llvm::raw_ostream
& Out
, const char* nl
,
66 void iterBindings(Store store
, BindingsHandler
& f
);
69 static RegionBindings
getRegionBindings(Store store
) {
70 return RegionBindings(static_cast<const RegionBindings::TreeTy
*>(store
));
73 class RegionInterval
{
77 RegionInterval(const MemRegion
*r
, int64_t s
, int64_t e
) : R(r
), I(s
, e
){}
80 RegionInterval
RegionToInterval(const MemRegion
*R
);
82 SVal
RetrieveRegionWithNoBinding(const MemRegion
*R
, QualType T
);
84 } // end anonymous namespace
86 StoreManager
*clang::CreateFlatStoreManager(GRStateManager
&StMgr
) {
87 return new FlatStoreManager(StMgr
);
90 SVal
FlatStoreManager::Retrieve(Store store
, Loc L
, QualType T
) {
91 const MemRegion
*R
= cast
<loc::MemRegionVal
>(L
).getRegion();
92 RegionInterval RI
= RegionToInterval(R
);
93 // FIXME: FlatStore should handle regions with unknown intervals.
97 RegionBindings B
= getRegionBindings(store
);
98 const BindingVal
*BV
= B
.lookup(RI
.R
);
100 const SVal
*V
= BVFactory
.lookup(*BV
, RI
.I
);
104 return RetrieveRegionWithNoBinding(R
, T
);
106 return RetrieveRegionWithNoBinding(R
, T
);
109 SVal
FlatStoreManager::RetrieveRegionWithNoBinding(const MemRegion
*R
,
111 if (R
->hasStackNonParametersStorage())
112 return UndefinedVal();
114 return svalBuilder
.getRegionValueSymbolVal(cast
<TypedRegion
>(R
));
117 Store
FlatStoreManager::Bind(Store store
, Loc L
, SVal val
) {
118 const MemRegion
*R
= cast
<loc::MemRegionVal
>(L
).getRegion();
119 RegionBindings B
= getRegionBindings(store
);
120 const BindingVal
*V
= B
.lookup(R
);
122 BindingVal BV
= BVFactory
.getEmptyMap();
126 RegionInterval RI
= RegionToInterval(R
);
127 // FIXME: FlatStore should handle regions with unknown intervals.
130 BV
= BVFactory
.add(BV
, RI
.I
, val
);
131 B
= RBFactory
.add(B
, RI
.R
, BV
);
135 Store
FlatStoreManager::Remove(Store store
, Loc L
) {
139 Store
FlatStoreManager::BindCompoundLiteral(Store store
,
140 const CompoundLiteralExpr
* cl
,
141 const LocationContext
*LC
,
146 SVal
FlatStoreManager::ArrayToPointer(Loc Array
) {
150 Store
FlatStoreManager::BindDecl(Store store
, const VarRegion
*VR
,
152 return Bind(store
, svalBuilder
.makeLoc(VR
), initVal
);
155 Store
FlatStoreManager::BindDeclWithNoInit(Store store
, const VarRegion
*VR
) {
159 Store
FlatStoreManager::InvalidateRegions(Store store
,
160 const MemRegion
* const *I
,
161 const MemRegion
* const *E
,
162 const Expr
*Ex
, unsigned Count
,
163 InvalidatedSymbols
*IS
,
164 bool invalidateGlobals
,
165 InvalidatedRegions
*Regions
) {
166 assert(false && "Not implemented");
170 void FlatStoreManager::print(Store store
, llvm::raw_ostream
& Out
,
171 const char* nl
, const char *sep
) {
174 void FlatStoreManager::iterBindings(Store store
, BindingsHandler
& f
) {
177 FlatStoreManager::RegionInterval
178 FlatStoreManager::RegionToInterval(const MemRegion
*R
) {
179 switch (R
->getKind()) {
180 case MemRegion::VarRegionKind
: {
181 QualType T
= cast
<VarRegion
>(R
)->getValueType();
182 int64_t Size
= Ctx
.getTypeSize(T
);
183 return RegionInterval(R
, 0, Size
-1);
186 case MemRegion::ElementRegionKind
:
187 case MemRegion::FieldRegionKind
: {
188 RegionOffset Offset
= R
->getAsOffset();
189 // We cannot compute offset for all regions, for example, elements
190 // with symbolic offsets.
191 if (!Offset
.getRegion())
192 return RegionInterval(0, 0, 0);
193 int64_t Start
= Offset
.getOffset();
194 int64_t Size
= Ctx
.getTypeSize(cast
<TypedRegion
>(R
)->getValueType());
195 return RegionInterval(Offset
.getRegion(), Start
, Start
+Size
);
199 llvm_unreachable("Region kind unhandled.");
200 return RegionInterval(0, 0, 0);