14
14
#include " Plugins/Language/Swift/SwiftStringIndex.h"
15
15
#include " Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h"
16
16
#include " Plugins/TypeSystem/Clang/TypeSystemClang.h"
17
+ #include " lldb/Core/ValueObject.h"
17
18
#include " lldb/DataFormatters/FormattersHelpers.h"
18
19
#include " lldb/DataFormatters/StringPrinter.h"
19
20
#include " lldb/Target/Process.h"
23
24
#include " lldb/Utility/Timer.h"
24
25
#include " swift/AST/Types.h"
25
26
#include " swift/Demangling/ManglingMacros.h"
27
+ #include " llvm/ADT/None.h"
26
28
#include " llvm/ADT/Optional.h"
27
29
#include " llvm/ADT/StringRef.h"
28
30
@@ -71,6 +73,33 @@ bool lldb_private::formatters::swift::SwiftSharedString_SummaryProvider(
71
73
StringPrinter::ReadStringAndDumpToStreamOptions ());
72
74
}
73
75
76
+ struct StringSlice {
77
+ uint64_t start, end;
78
+ };
79
+
80
+ template <typename AddrT>
81
+ static void applySlice (AddrT &address, uint64_t &length,
82
+ Optional<StringSlice> slice) {
83
+ if (!slice)
84
+ return ;
85
+
86
+ // No slicing is performed when the slice starts beyond the string's bounds.
87
+ if (slice->start > length)
88
+ return ;
89
+
90
+ // The slicing logic does handle the corner case where slice->start == length.
91
+
92
+ auto offset = slice->start ;
93
+ auto slice_length = slice->end - slice->start ;
94
+
95
+ // Adjust from the start.
96
+ address += offset;
97
+ length -= offset;
98
+
99
+ // Reduce to the slice length, unless it's larger than the remaining length.
100
+ length = std::min (slice_length, length);
101
+ }
102
+
74
103
static bool readStringFromAddress (
75
104
uint64_t startAddress, uint64_t length, ValueObject &valobj, Stream &stream,
76
105
const TypeSummaryOptions &summary_options,
@@ -95,10 +124,11 @@ static bool readStringFromAddress(
95
124
StringPrinter::StringElementType::UTF8>(read_options);
96
125
};
97
126
98
- bool lldb_private::formatters::swift::StringGuts_SummaryProvider (
127
+ static bool makeStringGutsSummary (
99
128
ValueObject &valobj, Stream &stream,
100
129
const TypeSummaryOptions &summary_options,
101
- StringPrinter::ReadStringAndDumpToStreamOptions read_options) {
130
+ StringPrinter::ReadStringAndDumpToStreamOptions read_options,
131
+ Optional<StringSlice> slice = None) {
102
132
LLDB_SCOPED_TIMER ();
103
133
104
134
static ConstString g__object (" _object" );
@@ -278,11 +308,13 @@ bool lldb_private::formatters::swift::StringGuts_SummaryProvider(
278
308
if (count > maxCount)
279
309
return false ;
280
310
281
- uint64_t buffer[2 ] = {raw0, raw1};
311
+ uint64_t rawBuffer[2 ] = {raw0, raw1};
312
+ auto *buffer = (uint8_t *)&rawBuffer;
313
+ applySlice (buffer, count, slice);
282
314
283
315
StringPrinter::ReadBufferAndDumpToStreamOptions options (read_options);
284
- options.SetData (
285
- DataExtractor ( buffer, count, process->GetByteOrder (), ptrSize));
316
+ options.SetData (lldb_private::DataExtractor (
317
+ buffer, count, process->GetByteOrder (), ptrSize));
286
318
options.SetStream (&stream);
287
319
options.SetSourceSize (count);
288
320
options.SetBinaryZeroIsTerminator (false );
@@ -300,6 +332,7 @@ bool lldb_private::formatters::swift::StringGuts_SummaryProvider(
300
332
return false ;
301
333
uint64_t bias = (ptrSize == 8 ? 32 : 20 );
302
334
auto address = objectAddress + bias;
335
+ applySlice (address, count, slice);
303
336
return readStringFromAddress (
304
337
address, count, valobj, stream, summary_options, read_options);
305
338
}
@@ -315,6 +348,7 @@ bool lldb_private::formatters::swift::StringGuts_SummaryProvider(
315
348
if (error.Fail ())
316
349
return false ;
317
350
351
+ applySlice (address, count, slice);
318
352
return readStringFromAddress (
319
353
start, count, valobj, stream, summary_options, read_options);
320
354
}
@@ -333,7 +367,8 @@ bool lldb_private::formatters::swift::StringGuts_SummaryProvider(
333
367
lldb::eBasicTypeObjCID);
334
368
335
369
// We may have an NSString pointer inline, so try formatting it directly.
336
- DataExtractor DE (&objectAddress, ptrSize, process->GetByteOrder (), ptrSize);
370
+ lldb_private::DataExtractor DE (&objectAddress, ptrSize,
371
+ process->GetByteOrder (), ptrSize);
337
372
auto nsstring = ValueObject::CreateValueObjectFromData (
338
373
" nsstring" , DE, valobj.GetExecutionContextRef (), id_type);
339
374
if (!nsstring || nsstring->GetError ().Fail ())
@@ -352,6 +387,13 @@ bool lldb_private::formatters::swift::StringGuts_SummaryProvider(
352
387
return false ;
353
388
}
354
389
390
+ bool lldb_private::formatters::swift::StringGuts_SummaryProvider (
391
+ ValueObject &valobj, Stream &stream,
392
+ const TypeSummaryOptions &summary_options,
393
+ StringPrinter::ReadStringAndDumpToStreamOptions read_options) {
394
+ return makeStringGutsSummary (valobj, stream, summary_options, read_options);
395
+ }
396
+
355
397
bool lldb_private::formatters::swift::String_SummaryProvider (
356
398
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
357
399
return String_SummaryProvider (
@@ -371,6 +413,53 @@ bool lldb_private::formatters::swift::String_SummaryProvider(
371
413
return false ;
372
414
}
373
415
416
+ bool lldb_private::formatters::swift::Substring_SummaryProvider (
417
+ ValueObject &valobj, Stream &stream,
418
+ const TypeSummaryOptions &summary_options) {
419
+ static ConstString g__slice (" _slice" );
420
+ static ConstString g__base (" _base" );
421
+ static ConstString g__startIndex (" _startIndex" );
422
+ static ConstString g__endIndex (" _endIndex" );
423
+ static ConstString g__rawBits (" _rawBits" );
424
+ auto slice_sp = valobj.GetChildMemberWithName (g__slice, true );
425
+ if (!slice_sp)
426
+ return false ;
427
+ auto base_sp = slice_sp->GetChildMemberWithName (g__base, true );
428
+ if (!base_sp)
429
+ return false ;
430
+
431
+ auto get_index =
432
+ [&slice_sp](ConstString index_name) -> Optional<StringIndex> {
433
+ auto raw_bits_sp = slice_sp->GetChildAtNamePath ({index_name, g__rawBits});
434
+ if (!raw_bits_sp)
435
+ return None;
436
+ bool success = false ;
437
+ StringIndex index =
438
+ raw_bits_sp->GetSyntheticValue ()->GetValueAsUnsigned (0 , &success);
439
+ if (!success)
440
+ return None;
441
+ return index;
442
+ };
443
+
444
+ Optional<StringIndex> start_index = get_index (g__startIndex);
445
+ Optional<StringIndex> end_index = get_index (g__endIndex);
446
+ if (!start_index || !end_index)
447
+ return false ;
448
+
449
+ if (!start_index->matchesEncoding (*end_index))
450
+ return false ;
451
+
452
+ static ConstString g_guts (" _guts" );
453
+ auto guts_sp = base_sp->GetChildMemberWithName (g_guts, true );
454
+ if (!guts_sp)
455
+ return false ;
456
+
457
+ StringPrinter::ReadStringAndDumpToStreamOptions read_options;
458
+ StringSlice slice{start_index->encodedOffset (), end_index->encodedOffset ()};
459
+ return makeStringGutsSummary (*guts_sp, stream, summary_options, read_options,
460
+ slice);
461
+ }
462
+
374
463
bool lldb_private::formatters::swift::StringIndex_SummaryProvider (
375
464
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
376
465
static ConstString g__rawBits (" _rawBits" );
0 commit comments