@@ -67,9 +67,10 @@ class BindingKey {
67
67
isa<ObjCIvarRegion, CXXDerivedObjectRegion>(r)) &&
68
68
" Not a base" );
69
69
}
70
- public:
71
70
71
+ public:
72
72
bool isDirect () const { return P.getInt () & Direct; }
73
+ bool isDefault () const { return !isDirect (); }
73
74
bool hasSymbolicOffset () const { return P.getInt () & Symbolic; }
74
75
75
76
const MemRegion *getRegion () const { return P.getPointer (); }
@@ -232,27 +233,86 @@ class RegionBindingsRef : public llvm::ImmutableMapRef<const MemRegion *,
232
233
233
234
void printJson (raw_ostream &Out, const char *NL = " \n " ,
234
235
unsigned int Space = 0 , bool IsDot = false ) const {
235
- for (iterator I = begin (), E = end (); I != E; ++I) {
236
- // TODO: We might need a .printJson for I.getKey() as well.
236
+ using namespace llvm ;
237
+ DenseMap<const MemRegion *, std::string> StringifyCache;
238
+ auto ToString = [&StringifyCache](const MemRegion *R) {
239
+ auto [Place, Inserted] = StringifyCache.try_emplace (R);
240
+ if (!Inserted)
241
+ return Place->second ;
242
+ std::string Res;
243
+ raw_string_ostream OS (Res);
244
+ OS << R;
245
+ Place->second = Res;
246
+ return Res;
247
+ };
248
+
249
+ using Cluster =
250
+ std::pair<const MemRegion *, ImmutableMap<BindingKey, SVal>>;
251
+ using Binding = std::pair<BindingKey, SVal>;
252
+
253
+ const auto MemSpaceBeforeRegionName = [&ToString](const Cluster *L,
254
+ const Cluster *R) {
255
+ if (isa<MemSpaceRegion>(L->first ) && !isa<MemSpaceRegion>(R->first ))
256
+ return true ;
257
+ if (!isa<MemSpaceRegion>(L->first ) && isa<MemSpaceRegion>(R->first ))
258
+ return false ;
259
+ return ToString (L->first ) < ToString (R->first );
260
+ };
261
+
262
+ const auto SymbolicBeforeOffset = [&ToString](const BindingKey &L,
263
+ const BindingKey &R) {
264
+ if (L.hasSymbolicOffset () && !R.hasSymbolicOffset ())
265
+ return true ;
266
+ if (!L.hasSymbolicOffset () && R.hasSymbolicOffset ())
267
+ return false ;
268
+ if (L.hasSymbolicOffset () && R.hasSymbolicOffset ())
269
+ return ToString (L.getRegion ()) < ToString (R.getRegion ());
270
+ return L.getOffset () < R.getOffset ();
271
+ };
272
+
273
+ const auto DefaultBindingBeforeDirectBindings =
274
+ [&SymbolicBeforeOffset](const Binding *LPtr, const Binding *RPtr) {
275
+ const BindingKey &L = LPtr->first ;
276
+ const BindingKey &R = RPtr->first ;
277
+ if (L.isDefault () && !R.isDefault ())
278
+ return true ;
279
+ if (!L.isDefault () && R.isDefault ())
280
+ return false ;
281
+ assert (L.isDefault () == R.isDefault ());
282
+ return SymbolicBeforeOffset (L, R);
283
+ };
284
+
285
+ const auto AddrOf = [](const auto &Item) { return &Item; };
286
+
287
+ std::vector<const Cluster *> SortedClusters;
288
+ SortedClusters.reserve (std::distance (begin (), end ()));
289
+ append_range (SortedClusters, map_range (*this , AddrOf));
290
+ llvm::sort (SortedClusters, MemSpaceBeforeRegionName);
291
+
292
+ for (auto [Idx, C] : llvm::enumerate (SortedClusters)) {
293
+ const auto &[BaseRegion, Bindings] = *C;
237
294
Indent (Out, Space, IsDot)
238
- << " { \" cluster\" : \" " << I.getKey () << " \" , \" pointer\" : \" "
239
- << (const void *)I.getKey () << " \" , \" items\" : [" << NL;
295
+ << " { \" cluster\" : \" " << BaseRegion << " \" , \" pointer\" : \" "
296
+ << (const void *)BaseRegion << " \" , \" items\" : [" << NL;
297
+
298
+ std::vector<const Binding *> SortedBindings;
299
+ SortedBindings.reserve (std::distance (Bindings.begin (), Bindings.end ()));
300
+ append_range (SortedBindings, map_range (Bindings, AddrOf));
301
+ llvm::sort (SortedBindings, DefaultBindingBeforeDirectBindings);
240
302
241
303
++Space;
242
- const ClusterBindings &CB = I.getData ();
243
- for (ClusterBindings::iterator CI = CB.begin (), CE = CB.end (); CI != CE;
244
- ++CI) {
245
- Indent (Out, Space, IsDot) << " { " << CI.getKey () << " , \" value\" : " ;
246
- CI.getData ().printJson (Out, /* AddQuotes=*/ true );
304
+ for (auto [Idx, B] : llvm::enumerate (SortedBindings)) {
305
+ const auto &[Key, Value] = *B;
306
+ Indent (Out, Space, IsDot) << " { " << Key << " , \" value\" : " ;
307
+ Value.printJson (Out, /* AddQuotes=*/ true );
247
308
Out << " }" ;
248
- if (std::next (CI) != CE )
309
+ if (Idx != SortedBindings. size () - 1 )
249
310
Out << ' ,' ;
250
311
Out << NL;
251
312
}
252
-
253
313
--Space;
254
314
Indent (Out, Space, IsDot) << " ]}" ;
255
- if (std::next (I) != E )
315
+ if (Idx != SortedClusters. size () - 1 )
256
316
Out << ' ,' ;
257
317
Out << NL;
258
318
}
0 commit comments