@@ -190,7 +190,53 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
190
190
"ptr_type={ptr_type}, pointee_type={pointee_type}" ,
191
191
) ;
192
192
193
+ /*
194
+ This block differentiates between mutable/immutable AND ref/ptr.
195
+
196
+ References to references (&&T) are invalid constructs in C/C++, and we are piggybacking off
197
+ of their type system when using LLDB (`TypeSystemClang`). Ptr-to-ref (*&T) and ref-to-ptr (&*T)
198
+ are valid constructs though. That means we can tell the debugger that ref-to-ref's are actually
199
+ ref-to-ptr's.
200
+
201
+ Additionally, to help debugger visualizers differentiate ref-to-ref's that *look like* ref-to-ptr
202
+ and *actual* ref-to-ptr, we can use the `rvalue_reference` tag. It's a C++ feature that doesn't
203
+ quite have an equivalent in Rust, but *is* represented as `&&` which is perfect! That means
204
+ ref-to-refs (&&T) will look like `T *&&` (i.e. an rvalue_reference to a pointer to T)
205
+ and on the debugger visualizer end, the scripts can "undo" that translation.
206
+
207
+ To handle immutable vs mutable (&/&mut) we use the `const` modifier. The modifier is applied
208
+ with proper C/C++ rules (i.e. pointer-to-constant vs constant pointer). This means that an
209
+ immutable reference applies the const modifier to the *pointee type*. When reversing the
210
+ debuginfo translation, the `const` modifier doesn't describe the value it's applied to, it describes
211
+ the pointer to the value. This is a **very** important distinction.
212
+
213
+ Here are some examples, the Rust representation is on the left and the debuginfo translation on
214
+ the right
215
+
216
+ Cosnt vs Mut:
217
+ *const T -> const T *
218
+ *mut T -> T *
219
+
220
+ *const *const T -> const T *const *
221
+ *mut *mut T -> T **
222
+
223
+ *mut *const T -> const T **
224
+ *const *mut T -> T *const *
225
+
226
+ Nested References:
227
+ &T -> const T &
228
+ &&T -> const T *const &&
229
+ &&&T -> const T &const *const &&
230
+ &&&&T -> const T *const &&const *const &&
231
+
232
+ &mut T -> T &
233
+ &mut &mut T -> T *&&
234
+ &mut &mut &mut T -> T &*&&
235
+ &mut &mut &mut &mut T -> T *&&*&&
236
+ */
193
237
let di_node = match ( ptr_type. kind ( ) , pointee_type. kind ( ) ) {
238
+ // if we have a ref-to-ref, convert the inner ref to a ptr and the outter ref to an rvalue ref
239
+ // and apply `const` to the inner ref's value and the inner ref itself as necessary
194
240
( ty:: Ref ( _, _, ptr_mut) , ty:: Ref ( _, inner_type, ptee_mut) ) => unsafe {
195
241
let inner_type_di_node = type_di_node ( cx, * inner_type) ;
196
242
let inner_type_di_node = if ptee_mut. is_not ( ) {
@@ -203,28 +249,31 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
203
249
inner_type_di_node
204
250
} ;
205
251
206
- let ptr_wrapper = llvm:: LLVMRustDIBuilderCreateReferenceType (
252
+ // creating a reference node with the pointer tag outputs a regular pointer as far as LLDB
253
+ // is concerned
254
+ let wrapped_ref = llvm:: LLVMRustDIBuilderCreateReferenceType (
207
255
DIB ( cx) ,
208
256
DW_TAG_pointer_type ,
209
257
inner_type_di_node,
210
258
) ;
211
259
212
- let ptr_wrapper = if ptr_mut. is_not ( ) {
260
+ let wrapped_ref = if ptr_mut. is_not ( ) {
213
261
llvm:: LLVMRustDIBuilderCreateQualifiedType (
214
262
DIB ( cx) ,
215
263
DW_TAG_const_type ,
216
- ptr_wrapper ,
264
+ wrapped_ref ,
217
265
)
218
266
} else {
219
- ptr_wrapper
267
+ wrapped_ref
220
268
} ;
221
269
222
270
llvm:: LLVMRustDIBuilderCreateReferenceType (
223
271
DIB ( cx) ,
224
272
DW_TAG_rvalue_reference_type ,
225
- ptr_wrapper ,
273
+ wrapped_ref ,
226
274
)
227
275
} ,
276
+ // if we have a ref-to-<not a ref>, apply `const` to the inner value as necessary
228
277
( ty:: Ref ( _, _, ptr_mut) , _) => unsafe {
229
278
let pointee_type_di_node = if ptr_mut. is_not ( ) {
230
279
llvm:: LLVMRustDIBuilderCreateQualifiedType (
@@ -242,6 +291,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
242
291
pointee_type_di_node,
243
292
)
244
293
} ,
294
+ // if we have any pointer, apply `const` to the inner value as necessary
245
295
( ty:: RawPtr ( _, ptr_mut) , _) => unsafe {
246
296
let pointee_type_di_node = if ptr_mut. is_not ( ) {
247
297
llvm:: LLVMRustDIBuilderCreateQualifiedType (
@@ -263,6 +313,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
263
313
ptr_type_debuginfo_name. len ( ) ,
264
314
)
265
315
} ,
316
+ // apply no translations to `Box`
266
317
( ty:: Adt ( _, _) , _) => unsafe {
267
318
llvm:: LLVMRustDIBuilderCreatePointerType (
268
319
DIB ( cx) ,
@@ -277,88 +328,6 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
277
328
_ => todo ! ( ) ,
278
329
} ;
279
330
280
- // Immutable pointers/references will mark the data as `const`. For example:
281
- // unsigned char & => &mut u8
282
- // const unsigned char & => &u8
283
- // unsigned char * => *mut u8
284
- // const unsigned char * => *const u8
285
- // let di_node = match ptr_type.kind() {
286
- // ty::Ref(_, _, mutability) => unsafe {
287
- // let pointee_type_di_node = if mutability.is_not() {
288
- // llvm::LLVMRustDIBuilderCreateQualifiedType(
289
- // DIB(cx),
290
- // DW_TAG_const_type,
291
- // pointee_type_di_node,
292
- // )
293
- // } else {
294
- // pointee_type_di_node
295
- // };
296
-
297
- // if let ty::Ref(_, pt_e, _) = pointee_type.kind() {
298
- // let pointee_type_di_node = type_di_node(cx, *pt_e);
299
- // let temp = llvm::LLVMRustDIBuilderCreateReferenceType(
300
- // DIB(cx),
301
- // 0xf,
302
- // pointee_type_di_node,
303
- // );
304
-
305
- // let temp = if mutability.is_not() {
306
- // llvm::LLVMRustDIBuilderCreateQualifiedType(
307
- // DIB(cx),
308
- // DW_TAG_const_type,
309
- // temp,
310
- // )
311
- // } else {
312
- // temp
313
- // };
314
-
315
- // llvm::LLVMRustDIBuilderCreateReferenceType(
316
- // DIB(cx),
317
- // DW_TAG_rvalue_reference_type,
318
- // temp,
319
- // )
320
- // } else {
321
- // llvm::LLVMRustDIBuilderCreateReferenceType(
322
- // DIB(cx),
323
- // DW_TAG_reference_type,
324
- // pointee_type_di_node,
325
- // )
326
- // }
327
- // },
328
- // ty::RawPtr(_, mutability) => unsafe {
329
- // let pointee_type_di_node = if mutability.is_not() {
330
- // llvm::LLVMRustDIBuilderCreateQualifiedType(
331
- // DIB(cx),
332
- // DW_TAG_const_type,
333
- // pointee_type_di_node,
334
- // )
335
- // } else {
336
- // pointee_type_di_node
337
- // };
338
- // llvm::LLVMRustDIBuilderCreatePointerType(
339
- // DIB(cx),
340
- // pointee_type_di_node,
341
- // data_layout.pointer_size.bits(),
342
- // data_layout.pointer_align.abi.bits() as u32,
343
- // 0, // Ignore DWARF address space.
344
- // ptr_type_debuginfo_name.as_c_char_ptr(),
345
- // ptr_type_debuginfo_name.len(),
346
- // )
347
- // },
348
- // ty::Adt(_, _) => unsafe {
349
- // llvm::LLVMRustDIBuilderCreatePointerType(
350
- // DIB(cx),
351
- // pointee_type_di_node,
352
- // data_layout.pointer_size.bits(),
353
- // data_layout.pointer_align.abi.bits() as u32,
354
- // 0, // Ignore DWARF address space.
355
- // ptr_type_debuginfo_name.as_c_char_ptr(),
356
- // ptr_type_debuginfo_name.len(),
357
- // )
358
- // },
359
- // _ => unreachable!("Thin pointer not of type ty::RawPtr, ty::Ref, or ty::Adt"),
360
- // };
361
-
362
331
DINodeCreationResult { di_node, already_stored_in_typemap : false }
363
332
}
364
333
Some ( wide_pointer_kind) => {
0 commit comments