@@ -17,34 +17,35 @@ using namespace lldb;
17
17
using namespace lldb_private ;
18
18
using namespace lldb_private ::formatters;
19
19
20
- static ValueObjectSP GetCoroFramePtrFromHandle (ValueObject &valobj) {
21
- ValueObjectSP valobj_sp (valobj.GetNonSyntheticValue ());
20
+ static lldb::addr_t GetCoroFramePtrFromHandle (ValueObjectSP valobj_sp) {
22
21
if (!valobj_sp)
23
- return nullptr ;
22
+ return LLDB_INVALID_ADDRESS ;
24
23
25
24
// We expect a single pointer in the `coroutine_handle` class.
26
25
// We don't care about its name.
27
26
if (valobj_sp->GetNumChildren () != 1 )
28
- return nullptr ;
27
+ return LLDB_INVALID_ADDRESS ;
29
28
ValueObjectSP ptr_sp (valobj_sp->GetChildAtIndex (0 , true ));
30
29
if (!ptr_sp)
31
- return nullptr ;
30
+ return LLDB_INVALID_ADDRESS ;
32
31
if (!ptr_sp->GetCompilerType ().IsPointerType ())
33
- return nullptr ;
34
-
35
- return ptr_sp;
36
- }
37
-
38
- static Function *ExtractFunction (ValueObjectSP &frame_ptr_sp, int offset) {
39
- lldb::TargetSP target_sp = frame_ptr_sp->GetTargetSP ();
40
- lldb::ProcessSP process_sp = frame_ptr_sp->GetProcessSP ();
41
- auto ptr_size = process_sp->GetAddressByteSize ();
32
+ return LLDB_INVALID_ADDRESS;
42
33
43
34
AddressType addr_type;
44
- lldb::addr_t frame_ptr_addr = frame_ptr_sp ->GetPointerValue (&addr_type);
35
+ lldb::addr_t frame_ptr_addr = ptr_sp ->GetPointerValue (&addr_type);
45
36
if (!frame_ptr_addr || frame_ptr_addr == LLDB_INVALID_ADDRESS)
46
- return nullptr ;
37
+ return LLDB_INVALID_ADDRESS ;
47
38
lldbassert (addr_type == AddressType::eAddressTypeLoad);
39
+ if (addr_type != AddressType::eAddressTypeLoad)
40
+ return LLDB_INVALID_ADDRESS;
41
+
42
+ return frame_ptr_addr;
43
+ }
44
+
45
+ static Function *ExtractFunction (lldb::TargetSP target_sp,
46
+ lldb::addr_t frame_ptr_addr, int offset) {
47
+ lldb::ProcessSP process_sp = target_sp->GetProcessSP ();
48
+ auto ptr_size = process_sp->GetAddressByteSize ();
48
49
49
50
Status error;
50
51
auto func_ptr_addr = frame_ptr_addr + offset * ptr_size;
@@ -60,12 +61,14 @@ static Function *ExtractFunction(ValueObjectSP &frame_ptr_sp, int offset) {
60
61
return func_address.CalculateSymbolContextFunction ();
61
62
}
62
63
63
- static Function *ExtractResumeFunction (ValueObjectSP &frame_ptr_sp) {
64
- return ExtractFunction (frame_ptr_sp, 0 );
64
+ static Function *ExtractResumeFunction (lldb::TargetSP target_sp,
65
+ lldb::addr_t frame_ptr_addr) {
66
+ return ExtractFunction (target_sp, frame_ptr_addr, 0 );
65
67
}
66
68
67
- static Function *ExtractDestroyFunction (ValueObjectSP &frame_ptr_sp) {
68
- return ExtractFunction (frame_ptr_sp, 1 );
69
+ static Function *ExtractDestroyFunction (lldb::TargetSP target_sp,
70
+ lldb::addr_t frame_ptr_addr) {
71
+ return ExtractFunction (target_sp, frame_ptr_addr, 1 );
69
72
}
70
73
71
74
static bool IsNoopCoroFunction (Function *f) {
@@ -125,43 +128,26 @@ static CompilerType InferPromiseType(Function &destroy_func) {
125
128
return promise_type->GetForwardCompilerType ();
126
129
}
127
130
128
- static CompilerType GetCoroutineFrameType (TypeSystemClang &ast_ctx,
129
- CompilerType promise_type) {
130
- CompilerType void_type = ast_ctx.GetBasicType (lldb::eBasicTypeVoid);
131
- CompilerType coro_func_type = ast_ctx.CreateFunctionType (
132
- /* result_type=*/ void_type, /* args=*/ &void_type, /* num_args=*/ 1 ,
133
- /* is_variadic=*/ false , /* qualifiers=*/ 0 );
134
- CompilerType coro_abi_type;
135
- if (promise_type.IsVoidType ()) {
136
- coro_abi_type = ast_ctx.CreateStructForIdentifier (
137
- ConstString (), {{" resume" , coro_func_type.GetPointerType ()},
138
- {" destroy" , coro_func_type.GetPointerType ()}});
139
- } else {
140
- coro_abi_type = ast_ctx.CreateStructForIdentifier (
141
- ConstString (), {{" resume" , coro_func_type.GetPointerType ()},
142
- {" destroy" , coro_func_type.GetPointerType ()},
143
- {" promise" , promise_type}});
144
- }
145
- return coro_abi_type;
146
- }
147
-
148
131
bool lldb_private::formatters::StdlibCoroutineHandleSummaryProvider (
149
132
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
150
- ValueObjectSP ptr_sp (GetCoroFramePtrFromHandle (valobj));
151
- if (!ptr_sp)
133
+ lldb::addr_t frame_ptr_addr =
134
+ GetCoroFramePtrFromHandle (valobj.GetNonSyntheticValue ());
135
+ if (frame_ptr_addr == LLDB_INVALID_ADDRESS)
152
136
return false ;
153
137
154
- if (!ptr_sp-> GetValueAsUnsigned ( 0 ) ) {
138
+ if (frame_ptr_addr == 0 ) {
155
139
stream << " nullptr" ;
156
140
return true ;
157
141
}
158
- if (IsNoopCoroFunction (ExtractResumeFunction (ptr_sp)) &&
159
- IsNoopCoroFunction (ExtractDestroyFunction (ptr_sp))) {
142
+
143
+ lldb::TargetSP target_sp = valobj.GetTargetSP ();
144
+ if (IsNoopCoroFunction (ExtractResumeFunction (target_sp, frame_ptr_addr)) &&
145
+ IsNoopCoroFunction (ExtractDestroyFunction (target_sp, frame_ptr_addr))) {
160
146
stream << " noop_coroutine" ;
161
147
return true ;
162
148
}
163
149
164
- stream.Printf (" coro frame = 0x%" PRIx64, ptr_sp-> GetValueAsUnsigned ( 0 ) );
150
+ stream.Printf (" coro frame = 0x%" PRIx64, frame_ptr_addr );
165
151
return true ;
166
152
}
167
153
@@ -178,39 +164,67 @@ lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEnd::
178
164
179
165
size_t lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEnd::
180
166
CalculateNumChildren () {
181
- if (!m_frame_ptr_sp )
167
+ if (!m_resume_ptr_sp || !m_destroy_ptr_sp )
182
168
return 0 ;
183
169
184
- return m_frame_ptr_sp-> GetNumChildren () ;
170
+ return m_promise_ptr_sp ? 3 : 2 ;
185
171
}
186
172
187
173
lldb::ValueObjectSP lldb_private::formatters::
188
174
StdlibCoroutineHandleSyntheticFrontEnd::GetChildAtIndex (size_t idx) {
189
- if (!m_frame_ptr_sp)
190
- return lldb::ValueObjectSP ();
191
-
192
- return m_frame_ptr_sp->GetChildAtIndex (idx, true );
175
+ switch (idx) {
176
+ case 0 :
177
+ return m_resume_ptr_sp;
178
+ case 1 :
179
+ return m_destroy_ptr_sp;
180
+ case 2 :
181
+ return m_promise_ptr_sp;
182
+ }
183
+ return lldb::ValueObjectSP ();
193
184
}
194
185
195
186
bool lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEnd::
196
187
Update () {
197
- m_frame_ptr_sp.reset ();
188
+ m_resume_ptr_sp.reset ();
189
+ m_destroy_ptr_sp.reset ();
190
+ m_promise_ptr_sp.reset ();
198
191
199
- ValueObjectSP valobj_sp = m_backend.GetSP ();
192
+ ValueObjectSP valobj_sp = m_backend.GetNonSyntheticValue ();
200
193
if (!valobj_sp)
201
194
return false ;
202
195
203
- ValueObjectSP ptr_sp ( GetCoroFramePtrFromHandle (m_backend) );
204
- if (!ptr_sp )
196
+ lldb:: addr_t frame_ptr_addr = GetCoroFramePtrFromHandle (valobj_sp );
197
+ if (frame_ptr_addr == 0 || frame_ptr_addr == LLDB_INVALID_ADDRESS )
205
198
return false ;
206
199
207
- Function *resume_func = ExtractResumeFunction (ptr_sp);
208
- Function *destroy_func = ExtractDestroyFunction (ptr_sp);
200
+ lldb::TargetSP target_sp = m_backend.GetTargetSP ();
201
+ Function *resume_func = ExtractResumeFunction (target_sp, frame_ptr_addr);
202
+ Function *destroy_func = ExtractDestroyFunction (target_sp, frame_ptr_addr);
209
203
210
- if ( IsNoopCoroFunction (resume_func) && IsNoopCoroFunction (destroy_func)) {
211
- // For `std::noop_coroutine()`, we don't want to display any child nodes.
204
+ // For `std::noop_coroutine()`, we don't want to display any child nodes.
205
+ if ( IsNoopCoroFunction (resume_func) && IsNoopCoroFunction (destroy_func))
212
206
return false ;
213
- }
207
+
208
+ auto ts = valobj_sp->GetCompilerType ().GetTypeSystem ();
209
+ auto ast_ctx = ts.dyn_cast_or_null <TypeSystemClang>();
210
+ if (!ast_ctx)
211
+ return {};
212
+
213
+ // Create the `resume` and `destroy` children
214
+ auto &exe_ctx = m_backend.GetExecutionContextRef ();
215
+ lldb::ProcessSP process_sp = target_sp->GetProcessSP ();
216
+ auto ptr_size = process_sp->GetAddressByteSize ();
217
+ CompilerType void_type = ast_ctx->GetBasicType (lldb::eBasicTypeVoid);
218
+ CompilerType coro_func_type = ast_ctx->CreateFunctionType (
219
+ /* result_type=*/ void_type, /* args=*/ &void_type, /* num_args=*/ 1 ,
220
+ /* is_variadic=*/ false , /* qualifiers=*/ 0 );
221
+ CompilerType coro_func_ptr_type = coro_func_type.GetPointerType ();
222
+ m_resume_ptr_sp = CreateValueObjectFromAddress (
223
+ " resume" , frame_ptr_addr + 0 * ptr_size, exe_ctx, coro_func_ptr_type);
224
+ lldbassert (m_resume_ptr_sp);
225
+ m_destroy_ptr_sp = CreateValueObjectFromAddress (
226
+ " destroy" , frame_ptr_addr + 1 * ptr_size, exe_ctx, coro_func_ptr_type);
227
+ lldbassert (m_destroy_ptr_sp);
214
228
215
229
// Get the `promise_type` from the template argument
216
230
CompilerType promise_type (
@@ -219,21 +233,23 @@ bool lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEnd::
219
233
return false ;
220
234
221
235
// Try to infer the promise_type if it was type-erased
222
- auto ts = valobj_sp->GetCompilerType ().GetTypeSystem ();
223
- auto ast_ctx = ts.dyn_cast_or_null <TypeSystemClang>();
224
- if (!ast_ctx)
225
- return false ;
226
236
if (promise_type.IsVoidType () && destroy_func) {
227
237
if (CompilerType inferred_type = InferPromiseType (*destroy_func)) {
228
238
// Copy the type over to the correct `TypeSystemClang` instance
229
239
promise_type = m_ast_importer->CopyType (*ast_ctx, inferred_type);
230
240
}
231
241
}
232
242
233
- // Build the coroutine frame type
234
- CompilerType coro_frame_type = GetCoroutineFrameType (*ast_ctx, promise_type);
235
-
236
- m_frame_ptr_sp = ptr_sp->Cast (coro_frame_type.GetPointerType ());
243
+ // Add the `promise` member. We intentionally add `promise` as a pointer type
244
+ // instead of a value type, and don't automatically dereference this pointer.
245
+ // We do so to avoid potential very deep recursion in case there is a cycle in
246
+ // formed between `std::coroutine_handle`s and their promises.
247
+ lldb::ValueObjectSP promise = CreateValueObjectFromAddress (
248
+ " promise" , frame_ptr_addr + 2 * ptr_size, exe_ctx, promise_type);
249
+ Status error;
250
+ lldb::ValueObjectSP promisePtr = promise->AddressOf (error);
251
+ if (error.Success ())
252
+ m_promise_ptr_sp = promisePtr->Clone (ConstString (" promise" ));
237
253
238
254
return false ;
239
255
}
@@ -245,10 +261,17 @@ bool lldb_private::formatters::StdlibCoroutineHandleSyntheticFrontEnd::
245
261
246
262
size_t StdlibCoroutineHandleSyntheticFrontEnd::GetIndexOfChildWithName (
247
263
ConstString name) {
248
- if (!m_frame_ptr_sp )
264
+ if (!m_resume_ptr_sp || !m_destroy_ptr_sp )
249
265
return UINT32_MAX;
250
266
251
- return m_frame_ptr_sp->GetIndexOfChildWithName (name);
267
+ if (name == ConstString (" resume" ))
268
+ return 0 ;
269
+ if (name == ConstString (" destroy" ))
270
+ return 1 ;
271
+ if (name == ConstString (" promise_ptr" ) && m_promise_ptr_sp)
272
+ return 2 ;
273
+
274
+ return UINT32_MAX;
252
275
}
253
276
254
277
SyntheticChildrenFrontEnd *
0 commit comments