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