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