@@ -190,7 +190,53 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
190190 "ptr_type={ptr_type}, pointee_type={pointee_type}" ,
191191 ) ;
192192
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+ */
193237 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
194240 ( ty:: Ref ( _, _, ptr_mut) , ty:: Ref ( _, inner_type, ptee_mut) ) => unsafe {
195241 let inner_type_di_node = type_di_node ( cx, * inner_type) ;
196242 let inner_type_di_node = if ptee_mut. is_not ( ) {
@@ -203,28 +249,31 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
203249 inner_type_di_node
204250 } ;
205251
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 (
207255 DIB ( cx) ,
208256 DW_TAG_pointer_type ,
209257 inner_type_di_node,
210258 ) ;
211259
212- let ptr_wrapper = if ptr_mut. is_not ( ) {
260+ let wrapped_ref = if ptr_mut. is_not ( ) {
213261 llvm:: LLVMRustDIBuilderCreateQualifiedType (
214262 DIB ( cx) ,
215263 DW_TAG_const_type ,
216- ptr_wrapper ,
264+ wrapped_ref ,
217265 )
218266 } else {
219- ptr_wrapper
267+ wrapped_ref
220268 } ;
221269
222270 llvm:: LLVMRustDIBuilderCreateReferenceType (
223271 DIB ( cx) ,
224272 DW_TAG_rvalue_reference_type ,
225- ptr_wrapper ,
273+ wrapped_ref ,
226274 )
227275 } ,
276+ // if we have a ref-to-<not a ref>, apply `const` to the inner value as necessary
228277 ( ty:: Ref ( _, _, ptr_mut) , _) => unsafe {
229278 let pointee_type_di_node = if ptr_mut. is_not ( ) {
230279 llvm:: LLVMRustDIBuilderCreateQualifiedType (
@@ -242,6 +291,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
242291 pointee_type_di_node,
243292 )
244293 } ,
294+ // if we have any pointer, apply `const` to the inner value as necessary
245295 ( ty:: RawPtr ( _, ptr_mut) , _) => unsafe {
246296 let pointee_type_di_node = if ptr_mut. is_not ( ) {
247297 llvm:: LLVMRustDIBuilderCreateQualifiedType (
@@ -263,6 +313,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
263313 ptr_type_debuginfo_name. len ( ) ,
264314 )
265315 } ,
316+ // apply no translations to `Box`
266317 ( ty:: Adt ( _, _) , _) => unsafe {
267318 llvm:: LLVMRustDIBuilderCreatePointerType (
268319 DIB ( cx) ,
@@ -277,88 +328,6 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
277328 _ => todo ! ( ) ,
278329 } ;
279330
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-
362331 DINodeCreationResult { di_node, already_stored_in_typemap : false }
363332 }
364333 Some ( wide_pointer_kind) => {
0 commit comments