about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMaulingMonkey <git@maulingmonkey.com>2020-06-24 23:28:00 -0700
committerMaulingMonkey <git@maulingmonkey.com>2020-06-24 23:28:00 -0700
commit24a728a8eb4832568509eb757c2374934a76cb98 (patch)
tree7776184d1e6de400172fce433da3d0bdcd8ee231
parentf8eb81ba4e85b02d90cfc33fcba0a6a7d5cbf810 (diff)
downloadrust-24a728a8eb4832568509eb757c2374934a76cb98.tar.gz
rust-24a728a8eb4832568509eb757c2374934a76cb98.zip
debuginfo: Define int/float types in terms of MSVC-recognized types.
PDB debug information doesn't appear to be emitted for basic types.
By defining u32 as a typedef for unsigned __int32 when targeting MSVC,
we allow CDB and other debuggers to recognize "u32" as a type/expression.

This in turn unblocks rust-lang#70052 "Update hashbrown to 0.8.0" by
allowing $T1 ..= $T3 to resolve, which would otherwise fail to resolve
when builtin types fail to parse.
-rw-r--r--src/librustc_codegen_llvm/debuginfo/metadata.rs72
-rw-r--r--src/librustc_codegen_llvm/llvm/ffi.rs10
-rw-r--r--src/rustllvm/RustWrapper.cpp8
3 files changed, 89 insertions, 1 deletions
diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs
index 8a957a729fb..ac8f28e1609 100644
--- a/src/librustc_codegen_llvm/debuginfo/metadata.rs
+++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs
@@ -19,6 +19,7 @@ use crate::llvm::debuginfo::{
 use crate::value::Value;
 
 use log::debug;
+use rustc_ast::ast;
 use rustc_codegen_ssa::traits::*;
 use rustc_data_structures::const_cstr;
 use rustc_data_structures::fingerprint::Fingerprint;
@@ -824,14 +825,60 @@ fn file_metadata_raw(
     }
 }
 
+trait MsvcBasicName {
+    fn msvc_basic_name(self) -> &'static str;
+}
+
+impl MsvcBasicName for ast::IntTy {
+    fn msvc_basic_name(self) -> &'static str {
+        match self {
+            ast::IntTy::Isize => "ptrdiff_t",
+            ast::IntTy::I8 => "__int8",
+            ast::IntTy::I16 => "__int16",
+            ast::IntTy::I32 => "__int32",
+            ast::IntTy::I64 => "__int64",
+            ast::IntTy::I128 => "__int128",
+        }
+    }
+}
+
+impl MsvcBasicName for ast::UintTy {
+    fn msvc_basic_name(self) -> &'static str {
+        match self {
+            ast::UintTy::Usize => "size_t",
+            ast::UintTy::U8 => "unsigned __int8",
+            ast::UintTy::U16 => "unsigned __int16",
+            ast::UintTy::U32 => "unsigned __int32",
+            ast::UintTy::U64 => "unsigned __int64",
+            ast::UintTy::U128 => "unsigned __int128",
+        }
+    }
+}
+
+impl MsvcBasicName for ast::FloatTy {
+    fn msvc_basic_name(self) -> &'static str {
+        match self {
+            ast::FloatTy::F32 => "float",
+            ast::FloatTy::F64 => "double",
+        }
+    }
+}
+
 fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
     debug!("basic_type_metadata: {:?}", t);
 
+    // When targeting MSVC, emit MSVC style type names for compatibility with
+    // .natvis visualizers (and perhaps other existing native debuggers?)
+    let msvc_like_names = cx.tcx.sess.target.target.options.is_like_msvc;
+
     let (name, encoding) = match t.kind {
         ty::Never => ("!", DW_ATE_unsigned),
         ty::Tuple(ref elements) if elements.is_empty() => ("()", DW_ATE_unsigned),
         ty::Bool => ("bool", DW_ATE_boolean),
         ty::Char => ("char", DW_ATE_unsigned_char),
+        ty::Int(int_ty) if msvc_like_names => (int_ty.msvc_basic_name(), DW_ATE_signed),
+        ty::Uint(uint_ty) if msvc_like_names => (uint_ty.msvc_basic_name(), DW_ATE_unsigned),
+        ty::Float(float_ty) if msvc_like_names => (float_ty.msvc_basic_name(), DW_ATE_float),
         ty::Int(int_ty) => (int_ty.name_str(), DW_ATE_signed),
         ty::Uint(uint_ty) => (uint_ty.name_str(), DW_ATE_unsigned),
         ty::Float(float_ty) => (float_ty.name_str(), DW_ATE_float),
@@ -848,7 +895,30 @@ fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
         )
     };
 
-    ty_metadata
+    if !msvc_like_names {
+        return ty_metadata;
+    }
+
+    let typedef_name = match t.kind {
+        ty::Int(int_ty) => int_ty.name_str(),
+        ty::Uint(uint_ty) => uint_ty.name_str(),
+        ty::Float(float_ty) => float_ty.name_str(),
+        _ => return ty_metadata,
+    };
+
+    let typedef_metadata = unsafe {
+        llvm::LLVMRustDIBuilderCreateTypedef(
+            DIB(cx),
+            ty_metadata,
+            typedef_name.as_ptr().cast(),
+            typedef_name.len(),
+            unknown_file_metadata(cx),
+            0,
+            None,
+        )
+    };
+
+    typedef_metadata
 }
 
 fn foreign_type_metadata(
diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs
index 8063d97aa73..61b1cae698d 100644
--- a/src/librustc_codegen_llvm/llvm/ffi.rs
+++ b/src/librustc_codegen_llvm/llvm/ffi.rs
@@ -1699,6 +1699,16 @@ extern "C" {
         Encoding: c_uint,
     ) -> &'a DIBasicType;
 
+    pub fn LLVMRustDIBuilderCreateTypedef(
+        Builder: &DIBuilder<'a>,
+        Type: &'a DIBasicType,
+        Name: *const c_char,
+        NameLen: size_t,
+        File: &'a DIFile,
+        LineNo: c_uint,
+        Scope: Option<&'a DIScope>,
+    ) -> &'a DIDerivedType;
+
     pub fn LLVMRustDIBuilderCreatePointerType(
         Builder: &DIBuilder<'a>,
         PointeeTy: &'a DIType,
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index cdb3a157eab..d78fb63fd4e 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -759,6 +759,14 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType(
   return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
 }
 
+extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTypedef(
+    LLVMRustDIBuilderRef Builder, LLVMMetadataRef Type, const char *Name, size_t NameLen,
+    LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Scope) {
+  return wrap(Builder->createTypedef(
+    unwrap<DIType>(Type), StringRef(Name, NameLen), unwrap<DIFile>(File),
+    LineNo, unwrap<DIScope>(Scope)));
+}
+
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
     LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
     uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,