@@ -252,7 +252,8 @@ bool lldb_private::formatters::NSIndexSetSummaryProvider(
252
252
if (!process_sp)
253
253
return false ;
254
254
255
- ObjCLanguageRuntime *runtime = ObjCLanguageRuntime::Get (*process_sp);
255
+ AppleObjCRuntime *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(
256
+ ObjCLanguageRuntime::Get (*process_sp));
256
257
257
258
if (!runtime)
258
259
return false ;
@@ -279,20 +280,56 @@ bool lldb_private::formatters::NSIndexSetSummaryProvider(
279
280
280
281
do {
281
282
if (class_name == " NSIndexSet" || class_name == " NSMutableIndexSet" ) {
283
+ // Foundation version 2000 added a bitmask if the index set fit in 64 bits
284
+ // and a Tagged Pointer version if the bitmask is small enough to fit in
285
+ // the tagged pointer payload.
286
+ // It also changed the layout (but not the size) of the set descriptor.
287
+
288
+ // First check whether this is a tagged pointer. The bitmask will be in
289
+ // the payload of the tagged pointer.
290
+ uint64_t payload;
291
+ if (runtime->GetFoundationVersion () >= 2000
292
+ && descriptor->GetTaggedPointerInfo (nullptr , nullptr , &payload)) {
293
+ count = llvm::popcount (payload);
294
+ break ;
295
+ }
296
+ // The first 32 bits describe the index set in all cases:
282
297
Status error;
283
298
uint32_t mode = process_sp->ReadUnsignedIntegerFromMemory (
284
- valobj_addr + ptr_size, 4 , 0 , error);
299
+ valobj_addr + ptr_size, 4 , 0 , error);
285
300
if (error.Fail ())
286
301
return false ;
287
- // this means the set is empty - count = 0
288
- if ((mode & 1 ) == 1 ) {
289
- count = 0 ;
290
- break ;
302
+ // Now check if the index is held in a bitmask in the object:
303
+ if (runtime->GetFoundationVersion () >= 2000 ) {
304
+ // The first two bits are "isSingleRange" and "isBitfield". If this is
305
+ // a bitfield we handle it here, otherwise set mode appropriately and
306
+ // the rest of the treatment is in common.
307
+ if ((mode & 2 ) == 2 ) {
308
+ // The bitfield is a 64 bit uint at the beginning of the data var.
309
+ uint64_t bitfield = process_sp->ReadUnsignedIntegerFromMemory (
310
+ valobj_addr + 2 * ptr_size, 8 , 0 , error);
311
+ if (error.Fail ())
312
+ return false ;
313
+ count = llvm::popcount (bitfield);
314
+ break ;
315
+ }
316
+ // It wasn't a bitfield, so read the isSingleRange from its new loc:
317
+ if ((mode & 1 ) == 1 )
318
+ mode = 1 ; // this means the set only has one range
319
+ else
320
+ mode = 2 ; // this means the set has multiple ranges
321
+ } else {
322
+ // this means the set is empty - count = 0
323
+ if ((mode & 1 ) == 1 ) {
324
+ count = 0 ;
325
+ break ;
326
+ }
327
+
328
+ if ((mode & 2 ) == 2 )
329
+ mode = 1 ; // this means the set only has one range
330
+ else
331
+ mode = 2 ; // this means the set has multiple ranges
291
332
}
292
- if ((mode & 2 ) == 2 )
293
- mode = 1 ; // this means the set only has one range
294
- else
295
- mode = 2 ; // this means the set has multiple ranges
296
333
if (mode == 1 ) {
297
334
count = process_sp->ReadUnsignedIntegerFromMemory (
298
335
valobj_addr + 3 * ptr_size, ptr_size, 0 , error);
0 commit comments