Importing rustc-1.48.0

Bug: 173721343
Change-Id: Ie8184d9a685086ca8a77266d6c608843f40dc9e1
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
new file mode 100644
index 0000000..7f47b61
--- /dev/null
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
@@ -0,0 +1,95 @@
+use super::metadata::{file_metadata, UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER};
+use super::utils::DIB;
+use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext};
+use rustc_codegen_ssa::traits::*;
+
+use crate::common::CodegenCx;
+use crate::llvm;
+use crate::llvm::debuginfo::{DIScope, DISubprogram};
+use rustc_middle::mir::{Body, SourceScope};
+use rustc_session::config::DebugInfo;
+
+use rustc_index::bit_set::BitSet;
+use rustc_index::vec::Idx;
+
+/// Produces DIScope DIEs for each MIR Scope which has variables defined in it.
+pub fn compute_mir_scopes(
+    cx: &CodegenCx<'ll, '_>,
+    mir: &Body<'_>,
+    fn_metadata: &'ll DISubprogram,
+    debug_context: &mut FunctionDebugContext<&'ll DIScope>,
+) {
+    // Find all the scopes with variables defined in them.
+    let mut has_variables = BitSet::new_empty(mir.source_scopes.len());
+
+    // Only consider variables when they're going to be emitted.
+    // FIXME(eddyb) don't even allocate `has_variables` otherwise.
+    if cx.sess().opts.debuginfo == DebugInfo::Full {
+        // FIXME(eddyb) take into account that arguments always have debuginfo,
+        // irrespective of their name (assuming full debuginfo is enabled).
+        // NOTE(eddyb) actually, on second thought, those are always in the
+        // function scope, which always exists.
+        for var_debug_info in &mir.var_debug_info {
+            has_variables.insert(var_debug_info.source_info.scope);
+        }
+    }
+
+    // Instantiate all scopes.
+    for idx in 0..mir.source_scopes.len() {
+        let scope = SourceScope::new(idx);
+        make_mir_scope(cx, &mir, fn_metadata, &has_variables, debug_context, scope);
+    }
+}
+
+fn make_mir_scope(
+    cx: &CodegenCx<'ll, '_>,
+    mir: &Body<'_>,
+    fn_metadata: &'ll DISubprogram,
+    has_variables: &BitSet<SourceScope>,
+    debug_context: &mut FunctionDebugContext<&'ll DISubprogram>,
+    scope: SourceScope,
+) {
+    if debug_context.scopes[scope].is_valid() {
+        return;
+    }
+
+    let scope_data = &mir.source_scopes[scope];
+    let parent_scope = if let Some(parent) = scope_data.parent_scope {
+        make_mir_scope(cx, mir, fn_metadata, has_variables, debug_context, parent);
+        debug_context.scopes[parent]
+    } else {
+        // The root is the function itself.
+        let loc = cx.lookup_debug_loc(mir.span.lo());
+        debug_context.scopes[scope] = DebugScope {
+            scope_metadata: Some(fn_metadata),
+            file_start_pos: loc.file.start_pos,
+            file_end_pos: loc.file.end_pos,
+        };
+        return;
+    };
+
+    if !has_variables.contains(scope) {
+        // Do not create a DIScope if there are no variables
+        // defined in this MIR Scope, to avoid debuginfo bloat.
+        debug_context.scopes[scope] = parent_scope;
+        return;
+    }
+
+    let loc = cx.lookup_debug_loc(scope_data.span.lo());
+    let file_metadata = file_metadata(cx, &loc.file, debug_context.defining_crate);
+
+    let scope_metadata = unsafe {
+        Some(llvm::LLVMRustDIBuilderCreateLexicalBlock(
+            DIB(cx),
+            parent_scope.scope_metadata.unwrap(),
+            file_metadata,
+            loc.line.unwrap_or(UNKNOWN_LINE_NUMBER),
+            loc.col.unwrap_or(UNKNOWN_COLUMN_NUMBER),
+        ))
+    };
+    debug_context.scopes[scope] = DebugScope {
+        scope_metadata,
+        file_start_pos: loc.file.start_pos,
+        file_end_pos: loc.file.end_pos,
+    };
+}
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/doc.rs b/compiler/rustc_codegen_llvm/src/debuginfo/doc.rs
new file mode 100644
index 0000000..b3a8fa2
--- /dev/null
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/doc.rs
@@ -0,0 +1,179 @@
+//! # Debug Info Module
+//!
+//! This module serves the purpose of generating debug symbols. We use LLVM's
+//! [source level debugging](https://llvm.org/docs/SourceLevelDebugging.html)
+//! features for generating the debug information. The general principle is
+//! this:
+//!
+//! Given the right metadata in the LLVM IR, the LLVM code generator is able to
+//! create DWARF debug symbols for the given code. The
+//! [metadata](https://llvm.org/docs/LangRef.html#metadata-type) is structured
+//! much like DWARF *debugging information entries* (DIE), representing type
+//! information such as datatype layout, function signatures, block layout,
+//! variable location and scope information, etc. It is the purpose of this
+//! module to generate correct metadata and insert it into the LLVM IR.
+//!
+//! As the exact format of metadata trees may change between different LLVM
+//! versions, we now use LLVM
+//! [DIBuilder](https://llvm.org/docs/doxygen/html/classllvm_1_1DIBuilder.html)
+//! to create metadata where possible. This will hopefully ease the adaption of
+//! this module to future LLVM versions.
+//!
+//! The public API of the module is a set of functions that will insert the
+//! correct metadata into the LLVM IR when called with the right parameters.
+//! The module is thus driven from an outside client with functions like
+//! `debuginfo::create_local_var_metadata(bx: block, local: &ast::local)`.
+//!
+//! Internally the module will try to reuse already created metadata by
+//! utilizing a cache. The way to get a shared metadata node when needed is
+//! thus to just call the corresponding function in this module:
+//!
+//!     let file_metadata = file_metadata(crate_context, path);
+//!
+//! The function will take care of probing the cache for an existing node for
+//! that exact file path.
+//!
+//! All private state used by the module is stored within either the
+//! CrateDebugContext struct (owned by the CodegenCx) or the
+//! FunctionDebugContext (owned by the FunctionCx).
+//!
+//! This file consists of three conceptual sections:
+//! 1. The public interface of the module
+//! 2. Module-internal metadata creation functions
+//! 3. Minor utility functions
+//!
+//!
+//! ## Recursive Types
+//!
+//! Some kinds of types, such as structs and enums can be recursive. That means
+//! that the type definition of some type X refers to some other type which in
+//! turn (transitively) refers to X. This introduces cycles into the type
+//! referral graph. A naive algorithm doing an on-demand, depth-first traversal
+//! of this graph when describing types, can get trapped in an endless loop
+//! when it reaches such a cycle.
+//!
+//! For example, the following simple type for a singly-linked list...
+//!
+//! ```
+//! struct List {
+//!     value: i32,
+//!     tail: Option<Box<List>>,
+//! }
+//! ```
+//!
+//! will generate the following callstack with a naive DFS algorithm:
+//!
+//! ```
+//! describe(t = List)
+//!   describe(t = i32)
+//!   describe(t = Option<Box<List>>)
+//!     describe(t = Box<List>)
+//!       describe(t = List) // at the beginning again...
+//!       ...
+//! ```
+//!
+//! To break cycles like these, we use "forward declarations". That is, when
+//! the algorithm encounters a possibly recursive type (any struct or enum), it
+//! immediately creates a type description node and inserts it into the cache
+//! *before* describing the members of the type. This type description is just
+//! a stub (as type members are not described and added to it yet) but it
+//! allows the algorithm to already refer to the type. After the stub is
+//! inserted into the cache, the algorithm continues as before. If it now
+//! encounters a recursive reference, it will hit the cache and does not try to
+//! describe the type anew.
+//!
+//! This behavior is encapsulated in the 'RecursiveTypeDescription' enum,
+//! which represents a kind of continuation, storing all state needed to
+//! continue traversal at the type members after the type has been registered
+//! with the cache. (This implementation approach might be a tad over-
+//! engineered and may change in the future)
+//!
+//!
+//! ## Source Locations and Line Information
+//!
+//! In addition to data type descriptions the debugging information must also
+//! allow to map machine code locations back to source code locations in order
+//! to be useful. This functionality is also handled in this module. The
+//! following functions allow to control source mappings:
+//!
+//! + set_source_location()
+//! + clear_source_location()
+//! + start_emitting_source_locations()
+//!
+//! `set_source_location()` allows to set the current source location. All IR
+//! instructions created after a call to this function will be linked to the
+//! given source location, until another location is specified with
+//! `set_source_location()` or the source location is cleared with
+//! `clear_source_location()`. In the later case, subsequent IR instruction
+//! will not be linked to any source location. As you can see, this is a
+//! stateful API (mimicking the one in LLVM), so be careful with source
+//! locations set by previous calls. It's probably best to not rely on any
+//! specific state being present at a given point in code.
+//!
+//! One topic that deserves some extra attention is *function prologues*. At
+//! the beginning of a function's machine code there are typically a few
+//! instructions for loading argument values into allocas and checking if
+//! there's enough stack space for the function to execute. This *prologue* is
+//! not visible in the source code and LLVM puts a special PROLOGUE END marker
+//! into the line table at the first non-prologue instruction of the function.
+//! In order to find out where the prologue ends, LLVM looks for the first
+//! instruction in the function body that is linked to a source location. So,
+//! when generating prologue instructions we have to make sure that we don't
+//! emit source location information until the 'real' function body begins. For
+//! this reason, source location emission is disabled by default for any new
+//! function being codegened and is only activated after a call to the third
+//! function from the list above, `start_emitting_source_locations()`. This
+//! function should be called right before regularly starting to codegen the
+//! top-level block of the given function.
+//!
+//! There is one exception to the above rule: `llvm.dbg.declare` instruction
+//! must be linked to the source location of the variable being declared. For
+//! function parameters these `llvm.dbg.declare` instructions typically occur
+//! in the middle of the prologue, however, they are ignored by LLVM's prologue
+//! detection. The `create_argument_metadata()` and related functions take care
+//! of linking the `llvm.dbg.declare` instructions to the correct source
+//! locations even while source location emission is still disabled, so there
+//! is no need to do anything special with source location handling here.
+//!
+//! ## Unique Type Identification
+//!
+//! In order for link-time optimization to work properly, LLVM needs a unique
+//! type identifier that tells it across compilation units which types are the
+//! same as others. This type identifier is created by
+//! `TypeMap::get_unique_type_id_of_type()` using the following algorithm:
+//!
+//! (1) Primitive types have their name as ID
+//! (2) Structs, enums and traits have a multipart identifier
+//!
+//!     (1) The first part is the SVH (strict version hash) of the crate they
+//!          were originally defined in
+//!
+//!     (2) The second part is the ast::NodeId of the definition in their
+//!          original crate
+//!
+//!     (3) The final part is a concatenation of the type IDs of their concrete
+//!          type arguments if they are generic types.
+//!
+//! (3) Tuple-, pointer and function types are structurally identified, which
+//!     means that they are equivalent if their component types are equivalent
+//!     (i.e., (i32, i32) is the same regardless in which crate it is used).
+//!
+//! This algorithm also provides a stable ID for types that are defined in one
+//! crate but instantiated from metadata within another crate. We just have to
+//! take care to always map crate and `NodeId`s back to the original crate
+//! context.
+//!
+//! As a side-effect these unique type IDs also help to solve a problem arising
+//! from lifetime parameters. Since lifetime parameters are completely omitted
+//! in debuginfo, more than one `Ty` instance may map to the same debuginfo
+//! type metadata, that is, some struct `Struct<'a>` may have N instantiations
+//! with different concrete substitutions for `'a`, and thus there will be N
+//! `Ty` instances for the type `Struct<'a>` even though it is not generic
+//! otherwise. Unfortunately this means that we cannot use `ty::type_id()` as
+//! cheap identifier for type metadata -- we have done this in the past, but it
+//! led to unnecessary metadata duplication in the best case and LLVM
+//! assertions in the worst. However, the unique type ID as described above
+//! *can* be used as identifier. Since it is comparatively expensive to
+//! construct, though, `ty::type_id()` is still used additionally as an
+//! optimization for cases where the exact same type has been seen before
+//! (which is most of the time).
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
new file mode 100644
index 0000000..29edd660
--- /dev/null
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
@@ -0,0 +1,71 @@
+// .debug_gdb_scripts binary section.
+
+use crate::llvm;
+
+use crate::builder::Builder;
+use crate::common::CodegenCx;
+use crate::value::Value;
+use rustc_codegen_ssa::traits::*;
+use rustc_middle::bug;
+use rustc_session::config::DebugInfo;
+
+use rustc_span::symbol::sym;
+
+/// Inserts a side-effect free instruction sequence that makes sure that the
+/// .debug_gdb_scripts global is referenced, so it isn't removed by the linker.
+pub fn insert_reference_to_gdb_debug_scripts_section_global(bx: &mut Builder<'_, '_, '_>) {
+    if needs_gdb_debug_scripts_section(bx) {
+        let gdb_debug_scripts_section = get_or_insert_gdb_debug_scripts_section_global(bx);
+        // Load just the first byte as that's all that's necessary to force
+        // LLVM to keep around the reference to the global.
+        let indices = [bx.const_i32(0), bx.const_i32(0)];
+        let element = bx.inbounds_gep(gdb_debug_scripts_section, &indices);
+        let volative_load_instruction = bx.volatile_load(element);
+        unsafe {
+            llvm::LLVMSetAlignment(volative_load_instruction, 1);
+        }
+    }
+}
+
+/// Allocates the global variable responsible for the .debug_gdb_scripts binary
+/// section.
+pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx<'ll, '_>) -> &'ll Value {
+    let c_section_var_name = "__rustc_debug_gdb_scripts_section__\0";
+    let section_var_name = &c_section_var_name[..c_section_var_name.len() - 1];
+
+    let section_var =
+        unsafe { llvm::LLVMGetNamedGlobal(cx.llmod, c_section_var_name.as_ptr().cast()) };
+
+    section_var.unwrap_or_else(|| {
+        let section_name = b".debug_gdb_scripts\0";
+        let section_contents = b"\x01gdb_load_rust_pretty_printers.py\0";
+
+        unsafe {
+            let llvm_type = cx.type_array(cx.type_i8(), section_contents.len() as u64);
+
+            let section_var = cx
+                .define_global(section_var_name, llvm_type)
+                .unwrap_or_else(|| bug!("symbol `{}` is already defined", section_var_name));
+            llvm::LLVMSetSection(section_var, section_name.as_ptr().cast());
+            llvm::LLVMSetInitializer(section_var, cx.const_bytes(section_contents));
+            llvm::LLVMSetGlobalConstant(section_var, llvm::True);
+            llvm::LLVMSetUnnamedAddress(section_var, llvm::UnnamedAddr::Global);
+            llvm::LLVMRustSetLinkage(section_var, llvm::Linkage::LinkOnceODRLinkage);
+            // This should make sure that the whole section is not larger than
+            // the string it contains. Otherwise we get a warning from GDB.
+            llvm::LLVMSetAlignment(section_var, 1);
+            section_var
+        }
+    })
+}
+
+pub fn needs_gdb_debug_scripts_section(cx: &CodegenCx<'_, '_>) -> bool {
+    let omit_gdb_pretty_printer_section = cx
+        .tcx
+        .sess
+        .contains_name(&cx.tcx.hir().krate_attrs(), sym::omit_gdb_pretty_printer_section);
+
+    !omit_gdb_pretty_printer_section
+        && cx.sess().opts.debuginfo != DebugInfo::None
+        && cx.sess().target.target.options.emit_debug_gdb_scripts
+}
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
new file mode 100644
index 0000000..987149c
--- /dev/null
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -0,0 +1,2584 @@
+use self::EnumTagInfo::*;
+use self::MemberDescriptionFactory::*;
+use self::RecursiveTypeDescription::*;
+
+use super::namespace::mangled_name_of_instance;
+use super::type_names::compute_debuginfo_type_name;
+use super::utils::{
+    create_DIArray, debug_context, get_namespace_for_item, is_node_local_to_unit, DIB,
+};
+use super::CrateDebugContext;
+
+use crate::abi;
+use crate::common::CodegenCx;
+use crate::llvm;
+use crate::llvm::debuginfo::{
+    DIArray, DICompositeType, DIDescriptor, DIFile, DIFlags, DILexicalBlock, DIScope, DIType,
+    DebugEmissionKind,
+};
+use crate::value::Value;
+
+use rustc_ast as ast;
+use rustc_codegen_ssa::traits::*;
+use rustc_data_structures::const_cstr;
+use rustc_data_structures::fingerprint::Fingerprint;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_fs_util::path_to_c_string;
+use rustc_hir::def::CtorKind;
+use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc_index::vec::{Idx, IndexVec};
+use rustc_middle::ich::NodeIdHashingMode;
+use rustc_middle::mir::interpret::truncate;
+use rustc_middle::mir::{self, Field, GeneratorLayout};
+use rustc_middle::ty::layout::{self, IntegerExt, PrimitiveExt, TyAndLayout};
+use rustc_middle::ty::subst::GenericArgKind;
+use rustc_middle::ty::Instance;
+use rustc_middle::ty::{self, AdtKind, GeneratorSubsts, ParamEnv, Ty, TyCtxt};
+use rustc_middle::{bug, span_bug};
+use rustc_session::config::{self, DebugInfo};
+use rustc_span::symbol::{Interner, Symbol};
+use rustc_span::{self, SourceFile, SourceFileHash, Span};
+use rustc_target::abi::{Abi, Align, HasDataLayout, Integer, LayoutOf, TagEncoding};
+use rustc_target::abi::{Int, Pointer, F32, F64};
+use rustc_target::abi::{Primitive, Size, VariantIdx, Variants};
+use tracing::debug;
+
+use libc::{c_longlong, c_uint};
+use std::collections::hash_map::Entry;
+use std::fmt::{self, Write};
+use std::hash::{Hash, Hasher};
+use std::iter;
+use std::path::{Path, PathBuf};
+use std::ptr;
+
+impl PartialEq for llvm::Metadata {
+    fn eq(&self, other: &Self) -> bool {
+        ptr::eq(self, other)
+    }
+}
+
+impl Eq for llvm::Metadata {}
+
+impl Hash for llvm::Metadata {
+    fn hash<H: Hasher>(&self, hasher: &mut H) {
+        (self as *const Self).hash(hasher);
+    }
+}
+
+impl fmt::Debug for llvm::Metadata {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        (self as *const Self).fmt(f)
+    }
+}
+
+// From DWARF 5.
+// See http://www.dwarfstd.org/ShowIssue.php?issue=140129.1.
+const DW_LANG_RUST: c_uint = 0x1c;
+#[allow(non_upper_case_globals)]
+const DW_ATE_boolean: c_uint = 0x02;
+#[allow(non_upper_case_globals)]
+const DW_ATE_float: c_uint = 0x04;
+#[allow(non_upper_case_globals)]
+const DW_ATE_signed: c_uint = 0x05;
+#[allow(non_upper_case_globals)]
+const DW_ATE_unsigned: c_uint = 0x07;
+#[allow(non_upper_case_globals)]
+const DW_ATE_unsigned_char: c_uint = 0x08;
+
+pub const UNKNOWN_LINE_NUMBER: c_uint = 0;
+pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0;
+
+pub const NO_SCOPE_METADATA: Option<&DIScope> = None;
+
+#[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)]
+pub struct UniqueTypeId(Symbol);
+
+/// The `TypeMap` is where the `CrateDebugContext` holds the type metadata nodes
+/// created so far. The metadata nodes are indexed by `UniqueTypeId`, and, for
+/// faster lookup, also by `Ty`. The `TypeMap` is responsible for creating
+/// `UniqueTypeId`s.
+#[derive(Default)]
+pub struct TypeMap<'ll, 'tcx> {
+    /// The `UniqueTypeId`s created so far.
+    unique_id_interner: Interner,
+    /// A map from `UniqueTypeId` to debuginfo metadata for that type. This is a 1:1 mapping.
+    unique_id_to_metadata: FxHashMap<UniqueTypeId, &'ll DIType>,
+    /// A map from types to debuginfo metadata. This is an N:1 mapping.
+    type_to_metadata: FxHashMap<Ty<'tcx>, &'ll DIType>,
+    /// A map from types to `UniqueTypeId`. This is an N:1 mapping.
+    type_to_unique_id: FxHashMap<Ty<'tcx>, UniqueTypeId>,
+}
+
+impl TypeMap<'ll, 'tcx> {
+    /// Adds a Ty to metadata mapping to the TypeMap. The method will fail if
+    /// the mapping already exists.
+    fn register_type_with_metadata(&mut self, type_: Ty<'tcx>, metadata: &'ll DIType) {
+        if self.type_to_metadata.insert(type_, metadata).is_some() {
+            bug!("type metadata for `Ty` '{}' is already in the `TypeMap`!", type_);
+        }
+    }
+
+    /// Removes a `Ty`-to-metadata mapping.
+    /// This is useful when computing the metadata for a potentially
+    /// recursive type (e.g., a function pointer of the form:
+    ///
+    ///     fn foo() -> impl Copy { foo }
+    ///
+    /// This kind of type cannot be properly represented
+    /// via LLVM debuginfo. As a workaround,
+    /// we register a temporary Ty to metadata mapping
+    /// for the function before we compute its actual metadata.
+    /// If the metadata computation ends up recursing back to the
+    /// original function, it will use the temporary mapping
+    /// for the inner self-reference, preventing us from
+    /// recursing forever.
+    ///
+    /// This function is used to remove the temporary metadata
+    /// mapping after we've computed the actual metadata.
+    fn remove_type(&mut self, type_: Ty<'tcx>) {
+        if self.type_to_metadata.remove(type_).is_none() {
+            bug!("type metadata `Ty` '{}' is not in the `TypeMap`!", type_);
+        }
+    }
+
+    /// Adds a `UniqueTypeId` to metadata mapping to the `TypeMap`. The method will
+    /// fail if the mapping already exists.
+    fn register_unique_id_with_metadata(
+        &mut self,
+        unique_type_id: UniqueTypeId,
+        metadata: &'ll DIType,
+    ) {
+        if self.unique_id_to_metadata.insert(unique_type_id, metadata).is_some() {
+            bug!(
+                "type metadata for unique ID '{}' is already in the `TypeMap`!",
+                self.get_unique_type_id_as_string(unique_type_id)
+            );
+        }
+    }
+
+    fn find_metadata_for_type(&self, type_: Ty<'tcx>) -> Option<&'ll DIType> {
+        self.type_to_metadata.get(&type_).cloned()
+    }
+
+    fn find_metadata_for_unique_id(&self, unique_type_id: UniqueTypeId) -> Option<&'ll DIType> {
+        self.unique_id_to_metadata.get(&unique_type_id).cloned()
+    }
+
+    /// Gets the string representation of a `UniqueTypeId`. This method will fail if
+    /// the ID is unknown.
+    fn get_unique_type_id_as_string(&self, unique_type_id: UniqueTypeId) -> &str {
+        let UniqueTypeId(interner_key) = unique_type_id;
+        self.unique_id_interner.get(interner_key)
+    }
+
+    /// Gets the `UniqueTypeId` for the given type. If the `UniqueTypeId` for the given
+    /// type has been requested before, this is just a table lookup. Otherwise, an
+    /// ID will be generated and stored for later lookup.
+    fn get_unique_type_id_of_type<'a>(
+        &mut self,
+        cx: &CodegenCx<'a, 'tcx>,
+        type_: Ty<'tcx>,
+    ) -> UniqueTypeId {
+        // Let's see if we already have something in the cache.
+        if let Some(unique_type_id) = self.type_to_unique_id.get(&type_).cloned() {
+            return unique_type_id;
+        }
+        // If not, generate one.
+
+        // The hasher we are using to generate the UniqueTypeId. We want
+        // something that provides more than the 64 bits of the DefaultHasher.
+        let mut hasher = StableHasher::new();
+        let mut hcx = cx.tcx.create_stable_hashing_context();
+        let type_ = cx.tcx.erase_regions(&type_);
+        hcx.while_hashing_spans(false, |hcx| {
+            hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
+                type_.hash_stable(hcx, &mut hasher);
+            });
+        });
+        let unique_type_id = hasher.finish::<Fingerprint>().to_hex();
+
+        let key = self.unique_id_interner.intern(&unique_type_id);
+        self.type_to_unique_id.insert(type_, UniqueTypeId(key));
+
+        UniqueTypeId(key)
+    }
+
+    /// Gets the `UniqueTypeId` for an enum variant. Enum variants are not really
+    /// types of their own, so they need special handling. We still need a
+    /// `UniqueTypeId` for them, since to debuginfo they *are* real types.
+    fn get_unique_type_id_of_enum_variant<'a>(
+        &mut self,
+        cx: &CodegenCx<'a, 'tcx>,
+        enum_type: Ty<'tcx>,
+        variant_name: &str,
+    ) -> UniqueTypeId {
+        let enum_type_id = self.get_unique_type_id_of_type(cx, enum_type);
+        let enum_variant_type_id =
+            format!("{}::{}", self.get_unique_type_id_as_string(enum_type_id), variant_name);
+        let interner_key = self.unique_id_interner.intern(&enum_variant_type_id);
+        UniqueTypeId(interner_key)
+    }
+
+    /// Gets the unique type ID string for an enum variant part.
+    /// Variant parts are not types and shouldn't really have their own ID,
+    /// but it makes `set_members_of_composite_type()` simpler.
+    fn get_unique_type_id_str_of_enum_variant_part(
+        &mut self,
+        enum_type_id: UniqueTypeId,
+    ) -> String {
+        format!("{}_variant_part", self.get_unique_type_id_as_string(enum_type_id))
+    }
+}
+
+/// A description of some recursive type. It can either be already finished (as
+/// with `FinalMetadata`) or it is not yet finished, but contains all information
+/// needed to generate the missing parts of the description. See the
+/// documentation section on Recursive Types at the top of this file for more
+/// information.
+enum RecursiveTypeDescription<'ll, 'tcx> {
+    UnfinishedMetadata {
+        unfinished_type: Ty<'tcx>,
+        unique_type_id: UniqueTypeId,
+        metadata_stub: &'ll DICompositeType,
+        member_holding_stub: &'ll DICompositeType,
+        member_description_factory: MemberDescriptionFactory<'ll, 'tcx>,
+    },
+    FinalMetadata(&'ll DICompositeType),
+}
+
+fn create_and_register_recursive_type_forward_declaration(
+    cx: &CodegenCx<'ll, 'tcx>,
+    unfinished_type: Ty<'tcx>,
+    unique_type_id: UniqueTypeId,
+    metadata_stub: &'ll DICompositeType,
+    member_holding_stub: &'ll DICompositeType,
+    member_description_factory: MemberDescriptionFactory<'ll, 'tcx>,
+) -> RecursiveTypeDescription<'ll, 'tcx> {
+    // Insert the stub into the `TypeMap` in order to allow for recursive references.
+    let mut type_map = debug_context(cx).type_map.borrow_mut();
+    type_map.register_unique_id_with_metadata(unique_type_id, metadata_stub);
+    type_map.register_type_with_metadata(unfinished_type, metadata_stub);
+
+    UnfinishedMetadata {
+        unfinished_type,
+        unique_type_id,
+        metadata_stub,
+        member_holding_stub,
+        member_description_factory,
+    }
+}
+
+impl RecursiveTypeDescription<'ll, 'tcx> {
+    /// Finishes up the description of the type in question (mostly by providing
+    /// descriptions of the fields of the given type) and returns the final type
+    /// metadata.
+    fn finalize(&self, cx: &CodegenCx<'ll, 'tcx>) -> MetadataCreationResult<'ll> {
+        match *self {
+            FinalMetadata(metadata) => MetadataCreationResult::new(metadata, false),
+            UnfinishedMetadata {
+                unfinished_type,
+                unique_type_id,
+                metadata_stub,
+                member_holding_stub,
+                ref member_description_factory,
+            } => {
+                // Make sure that we have a forward declaration of the type in
+                // the TypeMap so that recursive references are possible. This
+                // will always be the case if the RecursiveTypeDescription has
+                // been properly created through the
+                // `create_and_register_recursive_type_forward_declaration()`
+                // function.
+                {
+                    let type_map = debug_context(cx).type_map.borrow();
+                    if type_map.find_metadata_for_unique_id(unique_type_id).is_none()
+                        || type_map.find_metadata_for_type(unfinished_type).is_none()
+                    {
+                        bug!(
+                            "Forward declaration of potentially recursive type \
+                              '{:?}' was not found in TypeMap!",
+                            unfinished_type
+                        );
+                    }
+                }
+
+                // ... then create the member descriptions ...
+                let member_descriptions = member_description_factory.create_member_descriptions(cx);
+
+                // ... and attach them to the stub to complete it.
+                set_members_of_composite_type(
+                    cx,
+                    unfinished_type,
+                    member_holding_stub,
+                    member_descriptions,
+                );
+                MetadataCreationResult::new(metadata_stub, true)
+            }
+        }
+    }
+}
+
+/// Returns from the enclosing function if the type metadata with the given
+/// unique ID can be found in the type map.
+macro_rules! return_if_metadata_created_in_meantime {
+    ($cx: expr, $unique_type_id: expr) => {
+        if let Some(metadata) =
+            debug_context($cx).type_map.borrow().find_metadata_for_unique_id($unique_type_id)
+        {
+            return MetadataCreationResult::new(metadata, true);
+        }
+    };
+}
+
+fn fixed_vec_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    unique_type_id: UniqueTypeId,
+    array_or_slice_type: Ty<'tcx>,
+    element_type: Ty<'tcx>,
+    span: Span,
+) -> MetadataCreationResult<'ll> {
+    let element_type_metadata = type_metadata(cx, element_type, span);
+
+    return_if_metadata_created_in_meantime!(cx, unique_type_id);
+
+    let (size, align) = cx.size_and_align_of(array_or_slice_type);
+
+    let upper_bound = match array_or_slice_type.kind() {
+        ty::Array(_, len) => len.eval_usize(cx.tcx, ty::ParamEnv::reveal_all()) as c_longlong,
+        _ => -1,
+    };
+
+    let subrange =
+        unsafe { Some(llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)) };
+
+    let subscripts = create_DIArray(DIB(cx), &[subrange]);
+    let metadata = unsafe {
+        llvm::LLVMRustDIBuilderCreateArrayType(
+            DIB(cx),
+            size.bits(),
+            align.bits() as u32,
+            element_type_metadata,
+            subscripts,
+        )
+    };
+
+    MetadataCreationResult::new(metadata, false)
+}
+
+fn vec_slice_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    slice_ptr_type: Ty<'tcx>,
+    element_type: Ty<'tcx>,
+    unique_type_id: UniqueTypeId,
+    span: Span,
+) -> MetadataCreationResult<'ll> {
+    let data_ptr_type = cx.tcx.mk_imm_ptr(element_type);
+
+    let data_ptr_metadata = type_metadata(cx, data_ptr_type, span);
+
+    return_if_metadata_created_in_meantime!(cx, unique_type_id);
+
+    let slice_type_name = compute_debuginfo_type_name(cx.tcx, slice_ptr_type, true);
+
+    let (pointer_size, pointer_align) = cx.size_and_align_of(data_ptr_type);
+    let (usize_size, usize_align) = cx.size_and_align_of(cx.tcx.types.usize);
+
+    let member_descriptions = vec![
+        MemberDescription {
+            name: "data_ptr".to_owned(),
+            type_metadata: data_ptr_metadata,
+            offset: Size::ZERO,
+            size: pointer_size,
+            align: pointer_align,
+            flags: DIFlags::FlagZero,
+            discriminant: None,
+            source_info: None,
+        },
+        MemberDescription {
+            name: "length".to_owned(),
+            type_metadata: type_metadata(cx, cx.tcx.types.usize, span),
+            offset: pointer_size,
+            size: usize_size,
+            align: usize_align,
+            flags: DIFlags::FlagZero,
+            discriminant: None,
+            source_info: None,
+        },
+    ];
+
+    let file_metadata = unknown_file_metadata(cx);
+
+    let metadata = composite_type_metadata(
+        cx,
+        slice_ptr_type,
+        &slice_type_name[..],
+        unique_type_id,
+        member_descriptions,
+        NO_SCOPE_METADATA,
+        file_metadata,
+        span,
+    );
+    MetadataCreationResult::new(metadata, false)
+}
+
+fn subroutine_type_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    unique_type_id: UniqueTypeId,
+    signature: ty::PolyFnSig<'tcx>,
+    span: Span,
+) -> MetadataCreationResult<'ll> {
+    let signature =
+        cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &signature);
+
+    let signature_metadata: Vec<_> = iter::once(
+        // return type
+        match signature.output().kind() {
+            ty::Tuple(ref tys) if tys.is_empty() => None,
+            _ => Some(type_metadata(cx, signature.output(), span)),
+        },
+    )
+    .chain(
+        // regular arguments
+        signature.inputs().iter().map(|argument_type| Some(type_metadata(cx, argument_type, span))),
+    )
+    .collect();
+
+    return_if_metadata_created_in_meantime!(cx, unique_type_id);
+
+    MetadataCreationResult::new(
+        unsafe {
+            llvm::LLVMRustDIBuilderCreateSubroutineType(
+                DIB(cx),
+                create_DIArray(DIB(cx), &signature_metadata[..]),
+            )
+        },
+        false,
+    )
+}
+
+// FIXME(1563): This is all a bit of a hack because 'trait pointer' is an ill-
+// defined concept. For the case of an actual trait pointer (i.e., `Box<Trait>`,
+// `&Trait`), `trait_object_type` should be the whole thing (e.g, `Box<Trait>`) and
+// `trait_type` should be the actual trait (e.g., `Trait`). Where the trait is part
+// of a DST struct, there is no `trait_object_type` and the results of this
+// function will be a little bit weird.
+fn trait_pointer_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    trait_type: Ty<'tcx>,
+    trait_object_type: Option<Ty<'tcx>>,
+    unique_type_id: UniqueTypeId,
+) -> &'ll DIType {
+    // The implementation provided here is a stub. It makes sure that the trait
+    // type is assigned the correct name, size, namespace, and source location.
+    // However, it does not describe the trait's methods.
+
+    let containing_scope = match trait_type.kind() {
+        ty::Dynamic(ref data, ..) => {
+            data.principal_def_id().map(|did| get_namespace_for_item(cx, did))
+        }
+        _ => {
+            bug!(
+                "debuginfo: unexpected trait-object type in \
+                  trait_pointer_metadata(): {:?}",
+                trait_type
+            );
+        }
+    };
+
+    let trait_object_type = trait_object_type.unwrap_or(trait_type);
+    let trait_type_name = compute_debuginfo_type_name(cx.tcx, trait_object_type, false);
+
+    let file_metadata = unknown_file_metadata(cx);
+
+    let layout = cx.layout_of(cx.tcx.mk_mut_ptr(trait_type));
+
+    assert_eq!(abi::FAT_PTR_ADDR, 0);
+    assert_eq!(abi::FAT_PTR_EXTRA, 1);
+
+    let data_ptr_field = layout.field(cx, 0);
+    let vtable_field = layout.field(cx, 1);
+    let member_descriptions = vec![
+        MemberDescription {
+            name: "pointer".to_owned(),
+            type_metadata: type_metadata(
+                cx,
+                cx.tcx.mk_mut_ptr(cx.tcx.types.u8),
+                rustc_span::DUMMY_SP,
+            ),
+            offset: layout.fields.offset(0),
+            size: data_ptr_field.size,
+            align: data_ptr_field.align.abi,
+            flags: DIFlags::FlagArtificial,
+            discriminant: None,
+            source_info: None,
+        },
+        MemberDescription {
+            name: "vtable".to_owned(),
+            type_metadata: type_metadata(cx, vtable_field.ty, rustc_span::DUMMY_SP),
+            offset: layout.fields.offset(1),
+            size: vtable_field.size,
+            align: vtable_field.align.abi,
+            flags: DIFlags::FlagArtificial,
+            discriminant: None,
+            source_info: None,
+        },
+    ];
+
+    composite_type_metadata(
+        cx,
+        trait_object_type,
+        &trait_type_name[..],
+        unique_type_id,
+        member_descriptions,
+        containing_scope,
+        file_metadata,
+        rustc_span::DUMMY_SP,
+    )
+}
+
+pub fn type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>, usage_site_span: Span) -> &'ll DIType {
+    // Get the unique type ID of this type.
+    let unique_type_id = {
+        let mut type_map = debug_context(cx).type_map.borrow_mut();
+        // First, try to find the type in `TypeMap`. If we have seen it before, we
+        // can exit early here.
+        match type_map.find_metadata_for_type(t) {
+            Some(metadata) => {
+                return metadata;
+            }
+            None => {
+                // The Ty is not in the `TypeMap` but maybe we have already seen
+                // an equivalent type (e.g., only differing in region arguments).
+                // In order to find out, generate the unique type ID and look
+                // that up.
+                let unique_type_id = type_map.get_unique_type_id_of_type(cx, t);
+                match type_map.find_metadata_for_unique_id(unique_type_id) {
+                    Some(metadata) => {
+                        // There is already an equivalent type in the TypeMap.
+                        // Register this Ty as an alias in the cache and
+                        // return the cached metadata.
+                        type_map.register_type_with_metadata(t, metadata);
+                        return metadata;
+                    }
+                    None => {
+                        // There really is no type metadata for this type, so
+                        // proceed by creating it.
+                        unique_type_id
+                    }
+                }
+            }
+        }
+    };
+
+    debug!("type_metadata: {:?}", t);
+
+    let ptr_metadata = |ty: Ty<'tcx>| match *ty.kind() {
+        ty::Slice(typ) => Ok(vec_slice_metadata(cx, t, typ, unique_type_id, usage_site_span)),
+        ty::Str => Ok(vec_slice_metadata(cx, t, cx.tcx.types.u8, unique_type_id, usage_site_span)),
+        ty::Dynamic(..) => Ok(MetadataCreationResult::new(
+            trait_pointer_metadata(cx, ty, Some(t), unique_type_id),
+            false,
+        )),
+        _ => {
+            let pointee_metadata = type_metadata(cx, ty, usage_site_span);
+
+            if let Some(metadata) =
+                debug_context(cx).type_map.borrow().find_metadata_for_unique_id(unique_type_id)
+            {
+                return Err(metadata);
+            }
+
+            Ok(MetadataCreationResult::new(pointer_type_metadata(cx, t, pointee_metadata), false))
+        }
+    };
+
+    let MetadataCreationResult { metadata, already_stored_in_typemap } = match *t.kind() {
+        ty::Never | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) => {
+            MetadataCreationResult::new(basic_type_metadata(cx, t), false)
+        }
+        ty::Tuple(ref elements) if elements.is_empty() => {
+            MetadataCreationResult::new(basic_type_metadata(cx, t), false)
+        }
+        ty::Array(typ, _) | ty::Slice(typ) => {
+            fixed_vec_metadata(cx, unique_type_id, t, typ, usage_site_span)
+        }
+        ty::Str => fixed_vec_metadata(cx, unique_type_id, t, cx.tcx.types.i8, usage_site_span),
+        ty::Dynamic(..) => {
+            MetadataCreationResult::new(trait_pointer_metadata(cx, t, None, unique_type_id), false)
+        }
+        ty::Foreign(..) => {
+            MetadataCreationResult::new(foreign_type_metadata(cx, t, unique_type_id), false)
+        }
+        ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _) => match ptr_metadata(ty) {
+            Ok(res) => res,
+            Err(metadata) => return metadata,
+        },
+        ty::Adt(def, _) if def.is_box() => match ptr_metadata(t.boxed_ty()) {
+            Ok(res) => res,
+            Err(metadata) => return metadata,
+        },
+        ty::FnDef(..) | ty::FnPtr(_) => {
+            if let Some(metadata) =
+                debug_context(cx).type_map.borrow().find_metadata_for_unique_id(unique_type_id)
+            {
+                return metadata;
+            }
+
+            // It's possible to create a self-referential
+            // type in Rust by using 'impl trait':
+            //
+            // fn foo() -> impl Copy { foo }
+            //
+            // See `TypeMap::remove_type` for more detals
+            // about the workaround.
+
+            let temp_type = {
+                unsafe {
+                    // The choice of type here is pretty arbitrary -
+                    // anything reading the debuginfo for a recursive
+                    // type is going to see *something* weird - the only
+                    // question is what exactly it will see.
+                    let name = "<recur_type>";
+                    llvm::LLVMRustDIBuilderCreateBasicType(
+                        DIB(cx),
+                        name.as_ptr().cast(),
+                        name.len(),
+                        cx.size_of(t).bits(),
+                        DW_ATE_unsigned,
+                    )
+                }
+            };
+
+            let type_map = &debug_context(cx).type_map;
+            type_map.borrow_mut().register_type_with_metadata(t, temp_type);
+
+            let fn_metadata =
+                subroutine_type_metadata(cx, unique_type_id, t.fn_sig(cx.tcx), usage_site_span)
+                    .metadata;
+
+            type_map.borrow_mut().remove_type(t);
+
+            // This is actually a function pointer, so wrap it in pointer DI.
+            MetadataCreationResult::new(pointer_type_metadata(cx, t, fn_metadata), false)
+        }
+        ty::Closure(def_id, substs) => {
+            let upvar_tys: Vec<_> = substs.as_closure().upvar_tys().collect();
+            let containing_scope = get_namespace_for_item(cx, def_id);
+            prepare_tuple_metadata(
+                cx,
+                t,
+                &upvar_tys,
+                unique_type_id,
+                usage_site_span,
+                Some(containing_scope),
+            )
+            .finalize(cx)
+        }
+        ty::Generator(def_id, substs, _) => {
+            let upvar_tys: Vec<_> = substs
+                .as_generator()
+                .prefix_tys()
+                .map(|t| cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t))
+                .collect();
+            prepare_enum_metadata(cx, t, def_id, unique_type_id, usage_site_span, upvar_tys)
+                .finalize(cx)
+        }
+        ty::Adt(def, ..) => match def.adt_kind() {
+            AdtKind::Struct => {
+                prepare_struct_metadata(cx, t, unique_type_id, usage_site_span).finalize(cx)
+            }
+            AdtKind::Union => {
+                prepare_union_metadata(cx, t, unique_type_id, usage_site_span).finalize(cx)
+            }
+            AdtKind::Enum => {
+                prepare_enum_metadata(cx, t, def.did, unique_type_id, usage_site_span, vec![])
+                    .finalize(cx)
+            }
+        },
+        ty::Tuple(ref elements) => {
+            let tys: Vec<_> = elements.iter().map(|k| k.expect_ty()).collect();
+            prepare_tuple_metadata(cx, t, &tys, unique_type_id, usage_site_span, NO_SCOPE_METADATA)
+                .finalize(cx)
+        }
+        // Type parameters from polymorphized functions.
+        ty::Param(_) => MetadataCreationResult::new(param_type_metadata(cx, t), false),
+        _ => bug!("debuginfo: unexpected type in type_metadata: {:?}", t),
+    };
+
+    {
+        let mut type_map = debug_context(cx).type_map.borrow_mut();
+
+        if already_stored_in_typemap {
+            // Also make sure that we already have a `TypeMap` entry for the unique type ID.
+            let metadata_for_uid = match type_map.find_metadata_for_unique_id(unique_type_id) {
+                Some(metadata) => metadata,
+                None => {
+                    span_bug!(
+                        usage_site_span,
+                        "expected type metadata for unique \
+                               type ID '{}' to already be in \
+                               the `debuginfo::TypeMap` but it \
+                               was not. (Ty = {})",
+                        type_map.get_unique_type_id_as_string(unique_type_id),
+                        t
+                    );
+                }
+            };
+
+            match type_map.find_metadata_for_type(t) {
+                Some(metadata) => {
+                    if metadata != metadata_for_uid {
+                        span_bug!(
+                            usage_site_span,
+                            "mismatch between `Ty` and \
+                                   `UniqueTypeId` maps in \
+                                   `debuginfo::TypeMap`. \
+                                   UniqueTypeId={}, Ty={}",
+                            type_map.get_unique_type_id_as_string(unique_type_id),
+                            t
+                        );
+                    }
+                }
+                None => {
+                    type_map.register_type_with_metadata(t, metadata);
+                }
+            }
+        } else {
+            type_map.register_type_with_metadata(t, metadata);
+            type_map.register_unique_id_with_metadata(unique_type_id, metadata);
+        }
+    }
+
+    metadata
+}
+
+fn hex_encode(data: &[u8]) -> String {
+    let mut hex_string = String::with_capacity(data.len() * 2);
+    for byte in data.iter() {
+        write!(&mut hex_string, "{:02x}", byte).unwrap();
+    }
+    hex_string
+}
+
+pub fn file_metadata(
+    cx: &CodegenCx<'ll, '_>,
+    source_file: &SourceFile,
+    defining_crate: CrateNum,
+) -> &'ll DIFile {
+    debug!("file_metadata: file_name: {}, defining_crate: {}", source_file.name, defining_crate);
+
+    let hash = Some(&source_file.src_hash);
+    let file_name = Some(source_file.name.to_string());
+    let directory = if defining_crate == LOCAL_CRATE {
+        Some(cx.sess().working_dir.0.to_string_lossy().to_string())
+    } else {
+        // If the path comes from an upstream crate we assume it has been made
+        // independent of the compiler's working directory one way or another.
+        None
+    };
+    file_metadata_raw(cx, file_name, directory, hash)
+}
+
+pub fn unknown_file_metadata(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile {
+    file_metadata_raw(cx, None, None, None)
+}
+
+fn file_metadata_raw(
+    cx: &CodegenCx<'ll, '_>,
+    file_name: Option<String>,
+    directory: Option<String>,
+    hash: Option<&SourceFileHash>,
+) -> &'ll DIFile {
+    let key = (file_name, directory);
+
+    match debug_context(cx).created_files.borrow_mut().entry(key) {
+        Entry::Occupied(o) => o.get(),
+        Entry::Vacant(v) => {
+            let (file_name, directory) = v.key();
+            debug!("file_metadata: file_name: {:?}, directory: {:?}", file_name, directory);
+
+            let file_name = file_name.as_deref().unwrap_or("<unknown>");
+            let directory = directory.as_deref().unwrap_or("");
+
+            let (hash_kind, hash_value) = match hash {
+                Some(hash) => {
+                    let kind = match hash.kind {
+                        rustc_span::SourceFileHashAlgorithm::Md5 => llvm::ChecksumKind::MD5,
+                        rustc_span::SourceFileHashAlgorithm::Sha1 => llvm::ChecksumKind::SHA1,
+                    };
+                    (kind, hex_encode(hash.hash_bytes()))
+                }
+                None => (llvm::ChecksumKind::None, String::new()),
+            };
+
+            let file_metadata = unsafe {
+                llvm::LLVMRustDIBuilderCreateFile(
+                    DIB(cx),
+                    file_name.as_ptr().cast(),
+                    file_name.len(),
+                    directory.as_ptr().cast(),
+                    directory.len(),
+                    hash_kind,
+                    hash_value.as_ptr().cast(),
+                    hash_value.len(),
+                )
+            };
+
+            v.insert(file_metadata);
+            file_metadata
+        }
+    }
+}
+
+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),
+        _ => bug!("debuginfo::basic_type_metadata - `t` is invalid type"),
+    };
+
+    let ty_metadata = unsafe {
+        llvm::LLVMRustDIBuilderCreateBasicType(
+            DIB(cx),
+            name.as_ptr().cast(),
+            name.len(),
+            cx.size_of(t).bits(),
+            encoding,
+        )
+    };
+
+    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(
+    cx: &CodegenCx<'ll, 'tcx>,
+    t: Ty<'tcx>,
+    unique_type_id: UniqueTypeId,
+) -> &'ll DIType {
+    debug!("foreign_type_metadata: {:?}", t);
+
+    let name = compute_debuginfo_type_name(cx.tcx, t, false);
+    create_struct_stub(cx, t, &name, unique_type_id, NO_SCOPE_METADATA, DIFlags::FlagZero)
+}
+
+fn pointer_type_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    pointer_type: Ty<'tcx>,
+    pointee_type_metadata: &'ll DIType,
+) -> &'ll DIType {
+    let (pointer_size, pointer_align) = cx.size_and_align_of(pointer_type);
+    let name = compute_debuginfo_type_name(cx.tcx, pointer_type, false);
+    unsafe {
+        llvm::LLVMRustDIBuilderCreatePointerType(
+            DIB(cx),
+            pointee_type_metadata,
+            pointer_size.bits(),
+            pointer_align.bits() as u32,
+            0, // Ignore DWARF address space.
+            name.as_ptr().cast(),
+            name.len(),
+        )
+    }
+}
+
+fn param_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
+    debug!("param_type_metadata: {:?}", t);
+    let name = format!("{:?}", t);
+    unsafe {
+        llvm::LLVMRustDIBuilderCreateBasicType(
+            DIB(cx),
+            name.as_ptr().cast(),
+            name.len(),
+            Size::ZERO.bits(),
+            DW_ATE_unsigned,
+        )
+    }
+}
+
+pub fn compile_unit_metadata(
+    tcx: TyCtxt<'_>,
+    codegen_unit_name: &str,
+    debug_context: &CrateDebugContext<'ll, '_>,
+) -> &'ll DIDescriptor {
+    let mut name_in_debuginfo = match tcx.sess.local_crate_source_file {
+        Some(ref path) => path.clone(),
+        None => PathBuf::from(&*tcx.crate_name(LOCAL_CRATE).as_str()),
+    };
+
+    // The OSX linker has an idiosyncrasy where it will ignore some debuginfo
+    // if multiple object files with the same `DW_AT_name` are linked together.
+    // As a workaround we generate unique names for each object file. Those do
+    // not correspond to an actual source file but that should be harmless.
+    if tcx.sess.target.target.options.is_like_osx {
+        name_in_debuginfo.push("@");
+        name_in_debuginfo.push(codegen_unit_name);
+    }
+
+    debug!("compile_unit_metadata: {:?}", name_in_debuginfo);
+    let rustc_producer =
+        format!("rustc version {}", option_env!("CFG_VERSION").expect("CFG_VERSION"),);
+    // FIXME(#41252) Remove "clang LLVM" if we can get GDB and LLVM to play nice.
+    let producer = format!("clang LLVM ({})", rustc_producer);
+
+    let name_in_debuginfo = name_in_debuginfo.to_string_lossy();
+    let work_dir = tcx.sess.working_dir.0.to_string_lossy();
+    let flags = "\0";
+    let split_name = "";
+
+    // FIXME(#60020):
+    //
+    //    This should actually be
+    //
+    //        let kind = DebugEmissionKind::from_generic(tcx.sess.opts.debuginfo);
+    //
+    //    That is, we should set LLVM's emission kind to `LineTablesOnly` if
+    //    we are compiling with "limited" debuginfo. However, some of the
+    //    existing tools relied on slightly more debuginfo being generated than
+    //    would be the case with `LineTablesOnly`, and we did not want to break
+    //    these tools in a "drive-by fix", without a good idea or plan about
+    //    what limited debuginfo should exactly look like. So for now we keep
+    //    the emission kind as `FullDebug`.
+    //
+    //    See https://github.com/rust-lang/rust/issues/60020 for details.
+    let kind = DebugEmissionKind::FullDebug;
+    assert!(tcx.sess.opts.debuginfo != DebugInfo::None);
+
+    unsafe {
+        let file_metadata = llvm::LLVMRustDIBuilderCreateFile(
+            debug_context.builder,
+            name_in_debuginfo.as_ptr().cast(),
+            name_in_debuginfo.len(),
+            work_dir.as_ptr().cast(),
+            work_dir.len(),
+            llvm::ChecksumKind::None,
+            ptr::null(),
+            0,
+        );
+
+        let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit(
+            debug_context.builder,
+            DW_LANG_RUST,
+            file_metadata,
+            producer.as_ptr().cast(),
+            producer.len(),
+            tcx.sess.opts.optimize != config::OptLevel::No,
+            flags.as_ptr().cast(),
+            0,
+            split_name.as_ptr().cast(),
+            split_name.len(),
+            kind,
+        );
+
+        if tcx.sess.opts.debugging_opts.profile {
+            let cu_desc_metadata =
+                llvm::LLVMRustMetadataAsValue(debug_context.llcontext, unit_metadata);
+            let default_gcda_path = &tcx.output_filenames(LOCAL_CRATE).with_extension("gcda");
+            let gcda_path =
+                tcx.sess.opts.debugging_opts.profile_emit.as_ref().unwrap_or(default_gcda_path);
+
+            let gcov_cu_info = [
+                path_to_mdstring(
+                    debug_context.llcontext,
+                    &tcx.output_filenames(LOCAL_CRATE).with_extension("gcno"),
+                ),
+                path_to_mdstring(debug_context.llcontext, &gcda_path),
+                cu_desc_metadata,
+            ];
+            let gcov_metadata = llvm::LLVMMDNodeInContext(
+                debug_context.llcontext,
+                gcov_cu_info.as_ptr(),
+                gcov_cu_info.len() as c_uint,
+            );
+
+            let llvm_gcov_ident = const_cstr!("llvm.gcov");
+            llvm::LLVMAddNamedMetadataOperand(
+                debug_context.llmod,
+                llvm_gcov_ident.as_ptr(),
+                gcov_metadata,
+            );
+        }
+
+        // Insert `llvm.ident` metadata on the wasm32 targets since that will
+        // get hooked up to the "producer" sections `processed-by` information.
+        if tcx.sess.opts.target_triple.triple().starts_with("wasm32") {
+            let name_metadata = llvm::LLVMMDStringInContext(
+                debug_context.llcontext,
+                rustc_producer.as_ptr().cast(),
+                rustc_producer.as_bytes().len() as c_uint,
+            );
+            llvm::LLVMAddNamedMetadataOperand(
+                debug_context.llmod,
+                const_cstr!("llvm.ident").as_ptr(),
+                llvm::LLVMMDNodeInContext(debug_context.llcontext, &name_metadata, 1),
+            );
+        }
+
+        return unit_metadata;
+    };
+
+    fn path_to_mdstring(llcx: &'ll llvm::Context, path: &Path) -> &'ll Value {
+        let path_str = path_to_c_string(path);
+        unsafe {
+            llvm::LLVMMDStringInContext(
+                llcx,
+                path_str.as_ptr(),
+                path_str.as_bytes().len() as c_uint,
+            )
+        }
+    }
+}
+
+struct MetadataCreationResult<'ll> {
+    metadata: &'ll DIType,
+    already_stored_in_typemap: bool,
+}
+
+impl MetadataCreationResult<'ll> {
+    fn new(metadata: &'ll DIType, already_stored_in_typemap: bool) -> Self {
+        MetadataCreationResult { metadata, already_stored_in_typemap }
+    }
+}
+
+#[derive(Debug)]
+struct SourceInfo<'ll> {
+    file: &'ll DIFile,
+    line: u32,
+}
+
+/// Description of a type member, which can either be a regular field (as in
+/// structs or tuples) or an enum variant.
+#[derive(Debug)]
+struct MemberDescription<'ll> {
+    name: String,
+    type_metadata: &'ll DIType,
+    offset: Size,
+    size: Size,
+    align: Align,
+    flags: DIFlags,
+    discriminant: Option<u64>,
+    source_info: Option<SourceInfo<'ll>>,
+}
+
+impl<'ll> MemberDescription<'ll> {
+    fn into_metadata(
+        self,
+        cx: &CodegenCx<'ll, '_>,
+        composite_type_metadata: &'ll DIScope,
+    ) -> &'ll DIType {
+        let (file, line) = self
+            .source_info
+            .map(|info| (info.file, info.line))
+            .unwrap_or_else(|| (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER));
+        unsafe {
+            llvm::LLVMRustDIBuilderCreateVariantMemberType(
+                DIB(cx),
+                composite_type_metadata,
+                self.name.as_ptr().cast(),
+                self.name.len(),
+                file,
+                line,
+                self.size.bits(),
+                self.align.bits() as u32,
+                self.offset.bits(),
+                match self.discriminant {
+                    None => None,
+                    Some(value) => Some(cx.const_u64(value)),
+                },
+                self.flags,
+                self.type_metadata,
+            )
+        }
+    }
+}
+
+/// A factory for `MemberDescription`s. It produces a list of member descriptions
+/// for some record-like type. `MemberDescriptionFactory`s are used to defer the
+/// creation of type member descriptions in order to break cycles arising from
+/// recursive type definitions.
+enum MemberDescriptionFactory<'ll, 'tcx> {
+    StructMDF(StructMemberDescriptionFactory<'tcx>),
+    TupleMDF(TupleMemberDescriptionFactory<'tcx>),
+    EnumMDF(EnumMemberDescriptionFactory<'ll, 'tcx>),
+    UnionMDF(UnionMemberDescriptionFactory<'tcx>),
+    VariantMDF(VariantMemberDescriptionFactory<'ll, 'tcx>),
+}
+
+impl MemberDescriptionFactory<'ll, 'tcx> {
+    fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDescription<'ll>> {
+        match *self {
+            StructMDF(ref this) => this.create_member_descriptions(cx),
+            TupleMDF(ref this) => this.create_member_descriptions(cx),
+            EnumMDF(ref this) => this.create_member_descriptions(cx),
+            UnionMDF(ref this) => this.create_member_descriptions(cx),
+            VariantMDF(ref this) => this.create_member_descriptions(cx),
+        }
+    }
+}
+
+//=-----------------------------------------------------------------------------
+// Structs
+//=-----------------------------------------------------------------------------
+
+/// Creates `MemberDescription`s for the fields of a struct.
+struct StructMemberDescriptionFactory<'tcx> {
+    ty: Ty<'tcx>,
+    variant: &'tcx ty::VariantDef,
+    span: Span,
+}
+
+impl<'tcx> StructMemberDescriptionFactory<'tcx> {
+    fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDescription<'ll>> {
+        let layout = cx.layout_of(self.ty);
+        self.variant
+            .fields
+            .iter()
+            .enumerate()
+            .map(|(i, f)| {
+                let name = if self.variant.ctor_kind == CtorKind::Fn {
+                    format!("__{}", i)
+                } else {
+                    f.ident.to_string()
+                };
+                let field = layout.field(cx, i);
+                MemberDescription {
+                    name,
+                    type_metadata: type_metadata(cx, field.ty, self.span),
+                    offset: layout.fields.offset(i),
+                    size: field.size,
+                    align: field.align.abi,
+                    flags: DIFlags::FlagZero,
+                    discriminant: None,
+                    source_info: None,
+                }
+            })
+            .collect()
+    }
+}
+
+fn prepare_struct_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    struct_type: Ty<'tcx>,
+    unique_type_id: UniqueTypeId,
+    span: Span,
+) -> RecursiveTypeDescription<'ll, 'tcx> {
+    let struct_name = compute_debuginfo_type_name(cx.tcx, struct_type, false);
+
+    let (struct_def_id, variant) = match struct_type.kind() {
+        ty::Adt(def, _) => (def.did, def.non_enum_variant()),
+        _ => bug!("prepare_struct_metadata on a non-ADT"),
+    };
+
+    let containing_scope = get_namespace_for_item(cx, struct_def_id);
+
+    let struct_metadata_stub = create_struct_stub(
+        cx,
+        struct_type,
+        &struct_name,
+        unique_type_id,
+        Some(containing_scope),
+        DIFlags::FlagZero,
+    );
+
+    create_and_register_recursive_type_forward_declaration(
+        cx,
+        struct_type,
+        unique_type_id,
+        struct_metadata_stub,
+        struct_metadata_stub,
+        StructMDF(StructMemberDescriptionFactory { ty: struct_type, variant, span }),
+    )
+}
+
+//=-----------------------------------------------------------------------------
+// Tuples
+//=-----------------------------------------------------------------------------
+
+/// Creates `MemberDescription`s for the fields of a tuple.
+struct TupleMemberDescriptionFactory<'tcx> {
+    ty: Ty<'tcx>,
+    component_types: Vec<Ty<'tcx>>,
+    span: Span,
+}
+
+impl<'tcx> TupleMemberDescriptionFactory<'tcx> {
+    fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDescription<'ll>> {
+        let layout = cx.layout_of(self.ty);
+        self.component_types
+            .iter()
+            .enumerate()
+            .map(|(i, &component_type)| {
+                let (size, align) = cx.size_and_align_of(component_type);
+                MemberDescription {
+                    name: format!("__{}", i),
+                    type_metadata: type_metadata(cx, component_type, self.span),
+                    offset: layout.fields.offset(i),
+                    size,
+                    align,
+                    flags: DIFlags::FlagZero,
+                    discriminant: None,
+                    source_info: None,
+                }
+            })
+            .collect()
+    }
+}
+
+fn prepare_tuple_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    tuple_type: Ty<'tcx>,
+    component_types: &[Ty<'tcx>],
+    unique_type_id: UniqueTypeId,
+    span: Span,
+    containing_scope: Option<&'ll DIScope>,
+) -> RecursiveTypeDescription<'ll, 'tcx> {
+    let tuple_name = compute_debuginfo_type_name(cx.tcx, tuple_type, false);
+
+    let struct_stub = create_struct_stub(
+        cx,
+        tuple_type,
+        &tuple_name[..],
+        unique_type_id,
+        containing_scope,
+        DIFlags::FlagZero,
+    );
+
+    create_and_register_recursive_type_forward_declaration(
+        cx,
+        tuple_type,
+        unique_type_id,
+        struct_stub,
+        struct_stub,
+        TupleMDF(TupleMemberDescriptionFactory {
+            ty: tuple_type,
+            component_types: component_types.to_vec(),
+            span,
+        }),
+    )
+}
+
+//=-----------------------------------------------------------------------------
+// Unions
+//=-----------------------------------------------------------------------------
+
+struct UnionMemberDescriptionFactory<'tcx> {
+    layout: TyAndLayout<'tcx>,
+    variant: &'tcx ty::VariantDef,
+    span: Span,
+}
+
+impl<'tcx> UnionMemberDescriptionFactory<'tcx> {
+    fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDescription<'ll>> {
+        self.variant
+            .fields
+            .iter()
+            .enumerate()
+            .map(|(i, f)| {
+                let field = self.layout.field(cx, i);
+                MemberDescription {
+                    name: f.ident.to_string(),
+                    type_metadata: type_metadata(cx, field.ty, self.span),
+                    offset: Size::ZERO,
+                    size: field.size,
+                    align: field.align.abi,
+                    flags: DIFlags::FlagZero,
+                    discriminant: None,
+                    source_info: None,
+                }
+            })
+            .collect()
+    }
+}
+
+fn prepare_union_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    union_type: Ty<'tcx>,
+    unique_type_id: UniqueTypeId,
+    span: Span,
+) -> RecursiveTypeDescription<'ll, 'tcx> {
+    let union_name = compute_debuginfo_type_name(cx.tcx, union_type, false);
+
+    let (union_def_id, variant) = match union_type.kind() {
+        ty::Adt(def, _) => (def.did, def.non_enum_variant()),
+        _ => bug!("prepare_union_metadata on a non-ADT"),
+    };
+
+    let containing_scope = get_namespace_for_item(cx, union_def_id);
+
+    let union_metadata_stub =
+        create_union_stub(cx, union_type, &union_name, unique_type_id, containing_scope);
+
+    create_and_register_recursive_type_forward_declaration(
+        cx,
+        union_type,
+        unique_type_id,
+        union_metadata_stub,
+        union_metadata_stub,
+        UnionMDF(UnionMemberDescriptionFactory { layout: cx.layout_of(union_type), variant, span }),
+    )
+}
+
+//=-----------------------------------------------------------------------------
+// Enums
+//=-----------------------------------------------------------------------------
+
+/// DWARF variant support is only available starting in LLVM 8, but
+/// on MSVC we have to use the fallback mode, because LLVM doesn't
+/// lower variant parts to PDB.
+fn use_enum_fallback(cx: &CodegenCx<'_, '_>) -> bool {
+    cx.sess().target.target.options.is_like_msvc
+}
+
+// FIXME(eddyb) maybe precompute this? Right now it's computed once
+// per generator monomorphization, but it doesn't depend on substs.
+fn generator_layout_and_saved_local_names(
+    tcx: TyCtxt<'tcx>,
+    def_id: DefId,
+) -> (&'tcx GeneratorLayout<'tcx>, IndexVec<mir::GeneratorSavedLocal, Option<Symbol>>) {
+    let body = tcx.optimized_mir(def_id);
+    let generator_layout = body.generator_layout.as_ref().unwrap();
+    let mut generator_saved_local_names = IndexVec::from_elem(None, &generator_layout.field_tys);
+
+    let state_arg = mir::Local::new(1);
+    for var in &body.var_debug_info {
+        if var.place.local != state_arg {
+            continue;
+        }
+        match var.place.projection[..] {
+            [
+                // Deref of the `Pin<&mut Self>` state argument.
+                mir::ProjectionElem::Field(..),
+                mir::ProjectionElem::Deref,
+
+                // Field of a variant of the state.
+                mir::ProjectionElem::Downcast(_, variant),
+                mir::ProjectionElem::Field(field, _),
+            ] => {
+                let name = &mut generator_saved_local_names[
+                    generator_layout.variant_fields[variant][field]
+                ];
+                if name.is_none() {
+                    name.replace(var.name);
+                }
+            }
+            _ => {}
+        }
+    }
+    (generator_layout, generator_saved_local_names)
+}
+
+/// Describes the members of an enum value; an enum is described as a union of
+/// structs in DWARF. This `MemberDescriptionFactory` provides the description for
+/// the members of this union; so for every variant of the given enum, this
+/// factory will produce one `MemberDescription` (all with no name and a fixed
+/// offset of zero bytes).
+struct EnumMemberDescriptionFactory<'ll, 'tcx> {
+    enum_type: Ty<'tcx>,
+    layout: TyAndLayout<'tcx>,
+    tag_type_metadata: Option<&'ll DIType>,
+    containing_scope: &'ll DIScope,
+    span: Span,
+}
+
+impl EnumMemberDescriptionFactory<'ll, 'tcx> {
+    fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDescription<'ll>> {
+        let generator_variant_info_data = match *self.enum_type.kind() {
+            ty::Generator(def_id, ..) => {
+                Some(generator_layout_and_saved_local_names(cx.tcx, def_id))
+            }
+            _ => None,
+        };
+
+        let variant_info_for = |index: VariantIdx| match *self.enum_type.kind() {
+            ty::Adt(adt, _) => VariantInfo::Adt(&adt.variants[index]),
+            ty::Generator(def_id, _, _) => {
+                let (generator_layout, generator_saved_local_names) =
+                    generator_variant_info_data.as_ref().unwrap();
+                VariantInfo::Generator {
+                    def_id,
+                    generator_layout: *generator_layout,
+                    generator_saved_local_names,
+                    variant_index: index,
+                }
+            }
+            _ => bug!(),
+        };
+
+        // This will always find the metadata in the type map.
+        let fallback = use_enum_fallback(cx);
+        let self_metadata = if fallback {
+            self.containing_scope
+        } else {
+            type_metadata(cx, self.enum_type, self.span)
+        };
+        let flags = match self.enum_type.kind() {
+            ty::Generator(..) => DIFlags::FlagArtificial,
+            _ => DIFlags::FlagZero,
+        };
+
+        match self.layout.variants {
+            Variants::Single { index } => {
+                if let ty::Adt(adt, _) = self.enum_type.kind() {
+                    if adt.variants.is_empty() {
+                        return vec![];
+                    }
+                }
+
+                let variant_info = variant_info_for(index);
+                let (variant_type_metadata, member_description_factory) = describe_enum_variant(
+                    cx,
+                    self.layout,
+                    variant_info,
+                    NoTag,
+                    self_metadata,
+                    self.span,
+                );
+
+                let member_descriptions = member_description_factory.create_member_descriptions(cx);
+
+                set_members_of_composite_type(
+                    cx,
+                    self.enum_type,
+                    variant_type_metadata,
+                    member_descriptions,
+                );
+                vec![MemberDescription {
+                    name: if fallback { String::new() } else { variant_info.variant_name() },
+                    type_metadata: variant_type_metadata,
+                    offset: Size::ZERO,
+                    size: self.layout.size,
+                    align: self.layout.align.abi,
+                    flags,
+                    discriminant: None,
+                    source_info: variant_info.source_info(cx),
+                }]
+            }
+            Variants::Multiple {
+                tag_encoding: TagEncoding::Direct,
+                tag_field,
+                ref variants,
+                ..
+            } => {
+                let tag_info = if fallback {
+                    RegularTag {
+                        tag_field: Field::from(tag_field),
+                        tag_type_metadata: self.tag_type_metadata.unwrap(),
+                    }
+                } else {
+                    // This doesn't matter in this case.
+                    NoTag
+                };
+                variants
+                    .iter_enumerated()
+                    .map(|(i, _)| {
+                        let variant = self.layout.for_variant(cx, i);
+                        let variant_info = variant_info_for(i);
+                        let (variant_type_metadata, member_desc_factory) = describe_enum_variant(
+                            cx,
+                            variant,
+                            variant_info,
+                            tag_info,
+                            self_metadata,
+                            self.span,
+                        );
+
+                        let member_descriptions =
+                            member_desc_factory.create_member_descriptions(cx);
+
+                        set_members_of_composite_type(
+                            cx,
+                            self.enum_type,
+                            variant_type_metadata,
+                            member_descriptions,
+                        );
+
+                        MemberDescription {
+                            name: if fallback {
+                                String::new()
+                            } else {
+                                variant_info.variant_name()
+                            },
+                            type_metadata: variant_type_metadata,
+                            offset: Size::ZERO,
+                            size: self.layout.size,
+                            align: self.layout.align.abi,
+                            flags,
+                            discriminant: Some(
+                                self.layout.ty.discriminant_for_variant(cx.tcx, i).unwrap().val
+                                    as u64,
+                            ),
+                            source_info: variant_info.source_info(cx),
+                        }
+                    })
+                    .collect()
+            }
+            Variants::Multiple {
+                tag_encoding:
+                    TagEncoding::Niche { ref niche_variants, niche_start, dataful_variant },
+                ref tag,
+                ref variants,
+                tag_field,
+            } => {
+                if fallback {
+                    let variant = self.layout.for_variant(cx, dataful_variant);
+                    // Create a description of the non-null variant.
+                    let (variant_type_metadata, member_description_factory) = describe_enum_variant(
+                        cx,
+                        variant,
+                        variant_info_for(dataful_variant),
+                        OptimizedTag,
+                        self.containing_scope,
+                        self.span,
+                    );
+
+                    let variant_member_descriptions =
+                        member_description_factory.create_member_descriptions(cx);
+
+                    set_members_of_composite_type(
+                        cx,
+                        self.enum_type,
+                        variant_type_metadata,
+                        variant_member_descriptions,
+                    );
+
+                    // Encode the information about the null variant in the union
+                    // member's name.
+                    let mut name = String::from("RUST$ENCODED$ENUM$");
+                    // Right now it's not even going to work for `niche_start > 0`,
+                    // and for multiple niche variants it only supports the first.
+                    fn compute_field_path<'a, 'tcx>(
+                        cx: &CodegenCx<'a, 'tcx>,
+                        name: &mut String,
+                        layout: TyAndLayout<'tcx>,
+                        offset: Size,
+                        size: Size,
+                    ) {
+                        for i in 0..layout.fields.count() {
+                            let field_offset = layout.fields.offset(i);
+                            if field_offset > offset {
+                                continue;
+                            }
+                            let inner_offset = offset - field_offset;
+                            let field = layout.field(cx, i);
+                            if inner_offset + size <= field.size {
+                                write!(name, "{}$", i).unwrap();
+                                compute_field_path(cx, name, field, inner_offset, size);
+                            }
+                        }
+                    }
+                    compute_field_path(
+                        cx,
+                        &mut name,
+                        self.layout,
+                        self.layout.fields.offset(tag_field),
+                        self.layout.field(cx, tag_field).size,
+                    );
+                    let variant_info = variant_info_for(*niche_variants.start());
+                    variant_info.map_struct_name(|variant_name| {
+                        name.push_str(variant_name);
+                    });
+
+                    // Create the (singleton) list of descriptions of union members.
+                    vec![MemberDescription {
+                        name,
+                        type_metadata: variant_type_metadata,
+                        offset: Size::ZERO,
+                        size: variant.size,
+                        align: variant.align.abi,
+                        flags,
+                        discriminant: None,
+                        source_info: variant_info.source_info(cx),
+                    }]
+                } else {
+                    variants
+                        .iter_enumerated()
+                        .map(|(i, _)| {
+                            let variant = self.layout.for_variant(cx, i);
+                            let variant_info = variant_info_for(i);
+                            let (variant_type_metadata, member_desc_factory) =
+                                describe_enum_variant(
+                                    cx,
+                                    variant,
+                                    variant_info,
+                                    OptimizedTag,
+                                    self_metadata,
+                                    self.span,
+                                );
+
+                            let member_descriptions =
+                                member_desc_factory.create_member_descriptions(cx);
+
+                            set_members_of_composite_type(
+                                cx,
+                                self.enum_type,
+                                variant_type_metadata,
+                                member_descriptions,
+                            );
+
+                            let niche_value = if i == dataful_variant {
+                                None
+                            } else {
+                                let value = (i.as_u32() as u128)
+                                    .wrapping_sub(niche_variants.start().as_u32() as u128)
+                                    .wrapping_add(niche_start);
+                                let value = truncate(value, tag.value.size(cx));
+                                // NOTE(eddyb) do *NOT* remove this assert, until
+                                // we pass the full 128-bit value to LLVM, otherwise
+                                // truncation will be silent and remain undetected.
+                                assert_eq!(value as u64 as u128, value);
+                                Some(value as u64)
+                            };
+
+                            MemberDescription {
+                                name: variant_info.variant_name(),
+                                type_metadata: variant_type_metadata,
+                                offset: Size::ZERO,
+                                size: self.layout.size,
+                                align: self.layout.align.abi,
+                                flags,
+                                discriminant: niche_value,
+                                source_info: variant_info.source_info(cx),
+                            }
+                        })
+                        .collect()
+                }
+            }
+        }
+    }
+}
+
+// Creates `MemberDescription`s for the fields of a single enum variant.
+struct VariantMemberDescriptionFactory<'ll, 'tcx> {
+    /// Cloned from the `layout::Struct` describing the variant.
+    offsets: Vec<Size>,
+    args: Vec<(String, Ty<'tcx>)>,
+    tag_type_metadata: Option<&'ll DIType>,
+    span: Span,
+}
+
+impl VariantMemberDescriptionFactory<'ll, 'tcx> {
+    fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDescription<'ll>> {
+        self.args
+            .iter()
+            .enumerate()
+            .map(|(i, &(ref name, ty))| {
+                // Discriminant is always the first field of our variant
+                // when using the enum fallback.
+                let is_artificial_discr = use_enum_fallback(cx) && i == 0;
+                let (size, align) = cx.size_and_align_of(ty);
+                MemberDescription {
+                    name: name.to_string(),
+                    type_metadata: if is_artificial_discr {
+                        self.tag_type_metadata.unwrap_or_else(|| type_metadata(cx, ty, self.span))
+                    } else {
+                        type_metadata(cx, ty, self.span)
+                    },
+                    offset: self.offsets[i],
+                    size,
+                    align,
+                    flags: if is_artificial_discr {
+                        DIFlags::FlagArtificial
+                    } else {
+                        DIFlags::FlagZero
+                    },
+                    discriminant: None,
+                    source_info: None,
+                }
+            })
+            .collect()
+    }
+}
+
+// FIXME: terminology here should be aligned with `abi::TagEncoding`.
+// `OptimizedTag` is `TagEncoding::Niche`, `RegularTag` is `TagEncoding::Direct`.
+// `NoTag` should be removed; users should use `Option<EnumTagInfo>` instead.
+#[derive(Copy, Clone)]
+enum EnumTagInfo<'ll> {
+    RegularTag { tag_field: Field, tag_type_metadata: &'ll DIType },
+    OptimizedTag,
+    NoTag,
+}
+
+#[derive(Copy, Clone)]
+enum VariantInfo<'a, 'tcx> {
+    Adt(&'tcx ty::VariantDef),
+    Generator {
+        def_id: DefId,
+        generator_layout: &'tcx GeneratorLayout<'tcx>,
+        generator_saved_local_names: &'a IndexVec<mir::GeneratorSavedLocal, Option<Symbol>>,
+        variant_index: VariantIdx,
+    },
+}
+
+impl<'tcx> VariantInfo<'_, 'tcx> {
+    fn map_struct_name<R>(&self, f: impl FnOnce(&str) -> R) -> R {
+        match self {
+            VariantInfo::Adt(variant) => f(&variant.ident.as_str()),
+            VariantInfo::Generator { variant_index, .. } => {
+                f(&GeneratorSubsts::variant_name(*variant_index))
+            }
+        }
+    }
+
+    fn variant_name(&self) -> String {
+        match self {
+            VariantInfo::Adt(variant) => variant.ident.to_string(),
+            VariantInfo::Generator { variant_index, .. } => {
+                // Since GDB currently prints out the raw discriminant along
+                // with every variant, make each variant name be just the value
+                // of the discriminant. The struct name for the variant includes
+                // the actual variant description.
+                format!("{}", variant_index.as_usize())
+            }
+        }
+    }
+
+    fn field_name(&self, i: usize) -> String {
+        let field_name = match *self {
+            VariantInfo::Adt(variant) if variant.ctor_kind != CtorKind::Fn => {
+                Some(variant.fields[i].ident.name)
+            }
+            VariantInfo::Generator {
+                generator_layout,
+                generator_saved_local_names,
+                variant_index,
+                ..
+            } => {
+                generator_saved_local_names
+                    [generator_layout.variant_fields[variant_index][i.into()]]
+            }
+            _ => None,
+        };
+        field_name.map(|name| name.to_string()).unwrap_or_else(|| format!("__{}", i))
+    }
+
+    fn source_info(&self, cx: &CodegenCx<'ll, 'tcx>) -> Option<SourceInfo<'ll>> {
+        match self {
+            VariantInfo::Generator { def_id, variant_index, .. } => {
+                let span =
+                    cx.tcx.generator_layout(*def_id).variant_source_info[*variant_index].span;
+                if !span.is_dummy() {
+                    let loc = cx.lookup_debug_loc(span.lo());
+                    return Some(SourceInfo {
+                        file: file_metadata(cx, &loc.file, def_id.krate),
+                        line: loc.line.unwrap_or(UNKNOWN_LINE_NUMBER),
+                    });
+                }
+            }
+            _ => {}
+        }
+        None
+    }
+
+    fn is_artificial(&self) -> bool {
+        match self {
+            VariantInfo::Generator { .. } => true,
+            VariantInfo::Adt(..) => false,
+        }
+    }
+}
+
+/// Returns a tuple of (1) `type_metadata_stub` of the variant, (2) a
+/// `MemberDescriptionFactory` for producing the descriptions of the
+/// fields of the variant. This is a rudimentary version of a full
+/// `RecursiveTypeDescription`.
+fn describe_enum_variant(
+    cx: &CodegenCx<'ll, 'tcx>,
+    layout: layout::TyAndLayout<'tcx>,
+    variant: VariantInfo<'_, 'tcx>,
+    discriminant_info: EnumTagInfo<'ll>,
+    containing_scope: &'ll DIScope,
+    span: Span,
+) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) {
+    let metadata_stub = variant.map_struct_name(|variant_name| {
+        let unique_type_id = debug_context(cx)
+            .type_map
+            .borrow_mut()
+            .get_unique_type_id_of_enum_variant(cx, layout.ty, &variant_name);
+        create_struct_stub(
+            cx,
+            layout.ty,
+            &variant_name,
+            unique_type_id,
+            Some(containing_scope),
+            // FIXME(tmandry): This doesn't seem to have any effect.
+            if variant.is_artificial() { DIFlags::FlagArtificial } else { DIFlags::FlagZero },
+        )
+    });
+
+    // Build an array of (field name, field type) pairs to be captured in the factory closure.
+    let (offsets, args) = if use_enum_fallback(cx) {
+        // If this is not a univariant enum, there is also the discriminant field.
+        let (discr_offset, discr_arg) = match discriminant_info {
+            RegularTag { tag_field, .. } => {
+                // We have the layout of an enum variant, we need the layout of the outer enum
+                let enum_layout = cx.layout_of(layout.ty);
+                let offset = enum_layout.fields.offset(tag_field.as_usize());
+                let args =
+                    ("RUST$ENUM$DISR".to_owned(), enum_layout.field(cx, tag_field.as_usize()).ty);
+                (Some(offset), Some(args))
+            }
+            _ => (None, None),
+        };
+        (
+            discr_offset
+                .into_iter()
+                .chain((0..layout.fields.count()).map(|i| layout.fields.offset(i)))
+                .collect(),
+            discr_arg
+                .into_iter()
+                .chain(
+                    (0..layout.fields.count())
+                        .map(|i| (variant.field_name(i), layout.field(cx, i).ty)),
+                )
+                .collect(),
+        )
+    } else {
+        (
+            (0..layout.fields.count()).map(|i| layout.fields.offset(i)).collect(),
+            (0..layout.fields.count())
+                .map(|i| (variant.field_name(i), layout.field(cx, i).ty))
+                .collect(),
+        )
+    };
+
+    let member_description_factory = VariantMDF(VariantMemberDescriptionFactory {
+        offsets,
+        args,
+        tag_type_metadata: match discriminant_info {
+            RegularTag { tag_type_metadata, .. } => Some(tag_type_metadata),
+            _ => None,
+        },
+        span,
+    });
+
+    (metadata_stub, member_description_factory)
+}
+
+fn prepare_enum_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    enum_type: Ty<'tcx>,
+    enum_def_id: DefId,
+    unique_type_id: UniqueTypeId,
+    span: Span,
+    outer_field_tys: Vec<Ty<'tcx>>,
+) -> RecursiveTypeDescription<'ll, 'tcx> {
+    let tcx = cx.tcx;
+    let enum_name = compute_debuginfo_type_name(tcx, enum_type, false);
+    // FIXME(tmandry): This doesn't seem to have any effect.
+    let enum_flags = match enum_type.kind() {
+        ty::Generator(..) => DIFlags::FlagArtificial,
+        _ => DIFlags::FlagZero,
+    };
+
+    let containing_scope = get_namespace_for_item(cx, enum_def_id);
+    // FIXME: This should emit actual file metadata for the enum, but we
+    // currently can't get the necessary information when it comes to types
+    // imported from other crates. Formerly we violated the ODR when performing
+    // LTO because we emitted debuginfo for the same type with varying file
+    // metadata, so as a workaround we pretend that the type comes from
+    // <unknown>
+    let file_metadata = unknown_file_metadata(cx);
+
+    let discriminant_type_metadata = |discr: Primitive| {
+        let enumerators_metadata: Vec<_> = match enum_type.kind() {
+            ty::Adt(def, _) => def
+                .discriminants(tcx)
+                .zip(&def.variants)
+                .map(|((_, discr), v)| {
+                    let name = v.ident.as_str();
+                    let is_unsigned = match discr.ty.kind() {
+                        ty::Int(_) => false,
+                        ty::Uint(_) => true,
+                        _ => bug!("non integer discriminant"),
+                    };
+                    unsafe {
+                        Some(llvm::LLVMRustDIBuilderCreateEnumerator(
+                            DIB(cx),
+                            name.as_ptr().cast(),
+                            name.len(),
+                            // FIXME: what if enumeration has i128 discriminant?
+                            discr.val as i64,
+                            is_unsigned,
+                        ))
+                    }
+                })
+                .collect(),
+            ty::Generator(_, substs, _) => substs
+                .as_generator()
+                .variant_range(enum_def_id, tcx)
+                .map(|variant_index| {
+                    debug_assert_eq!(tcx.types.u32, substs.as_generator().discr_ty(tcx));
+                    let name = GeneratorSubsts::variant_name(variant_index);
+                    unsafe {
+                        Some(llvm::LLVMRustDIBuilderCreateEnumerator(
+                            DIB(cx),
+                            name.as_ptr().cast(),
+                            name.len(),
+                            // Generators use u32 as discriminant type, verified above.
+                            variant_index.as_u32().into(),
+                            true, // IsUnsigned
+                        ))
+                    }
+                })
+                .collect(),
+            _ => bug!(),
+        };
+
+        let disr_type_key = (enum_def_id, discr);
+        let cached_discriminant_type_metadata =
+            debug_context(cx).created_enum_disr_types.borrow().get(&disr_type_key).cloned();
+        match cached_discriminant_type_metadata {
+            Some(discriminant_type_metadata) => discriminant_type_metadata,
+            None => {
+                let (discriminant_size, discriminant_align) = (discr.size(cx), discr.align(cx));
+                let discriminant_base_type_metadata =
+                    type_metadata(cx, discr.to_ty(tcx), rustc_span::DUMMY_SP);
+
+                let item_name;
+                let discriminant_name = match enum_type.kind() {
+                    ty::Adt(..) => {
+                        item_name = tcx.item_name(enum_def_id).as_str();
+                        &*item_name
+                    }
+                    ty::Generator(..) => enum_name.as_str(),
+                    _ => bug!(),
+                };
+
+                let discriminant_type_metadata = unsafe {
+                    llvm::LLVMRustDIBuilderCreateEnumerationType(
+                        DIB(cx),
+                        containing_scope,
+                        discriminant_name.as_ptr().cast(),
+                        discriminant_name.len(),
+                        file_metadata,
+                        UNKNOWN_LINE_NUMBER,
+                        discriminant_size.bits(),
+                        discriminant_align.abi.bits() as u32,
+                        create_DIArray(DIB(cx), &enumerators_metadata),
+                        discriminant_base_type_metadata,
+                        true,
+                    )
+                };
+
+                debug_context(cx)
+                    .created_enum_disr_types
+                    .borrow_mut()
+                    .insert(disr_type_key, discriminant_type_metadata);
+
+                discriminant_type_metadata
+            }
+        }
+    };
+
+    let layout = cx.layout_of(enum_type);
+
+    if let (
+        &Abi::Scalar(_),
+        &Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, .. },
+    ) = (&layout.abi, &layout.variants)
+    {
+        return FinalMetadata(discriminant_type_metadata(tag.value));
+    }
+
+    if use_enum_fallback(cx) {
+        let discriminant_type_metadata = match layout.variants {
+            Variants::Single { .. }
+            | Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, .. } => None,
+            Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, .. } => {
+                Some(discriminant_type_metadata(tag.value))
+            }
+        };
+
+        let enum_metadata = {
+            let type_map = debug_context(cx).type_map.borrow();
+            let unique_type_id_str = type_map.get_unique_type_id_as_string(unique_type_id);
+
+            unsafe {
+                llvm::LLVMRustDIBuilderCreateUnionType(
+                    DIB(cx),
+                    containing_scope,
+                    enum_name.as_ptr().cast(),
+                    enum_name.len(),
+                    file_metadata,
+                    UNKNOWN_LINE_NUMBER,
+                    layout.size.bits(),
+                    layout.align.abi.bits() as u32,
+                    enum_flags,
+                    None,
+                    0, // RuntimeLang
+                    unique_type_id_str.as_ptr().cast(),
+                    unique_type_id_str.len(),
+                )
+            }
+        };
+
+        return create_and_register_recursive_type_forward_declaration(
+            cx,
+            enum_type,
+            unique_type_id,
+            enum_metadata,
+            enum_metadata,
+            EnumMDF(EnumMemberDescriptionFactory {
+                enum_type,
+                layout,
+                tag_type_metadata: discriminant_type_metadata,
+                containing_scope,
+                span,
+            }),
+        );
+    }
+
+    let discriminator_name = match enum_type.kind() {
+        ty::Generator(..) => "__state",
+        _ => "",
+    };
+    let discriminator_metadata = match layout.variants {
+        // A single-variant enum has no discriminant.
+        Variants::Single { .. } => None,
+
+        Variants::Multiple {
+            tag_encoding: TagEncoding::Niche { .. }, ref tag, tag_field, ..
+        } => {
+            // Find the integer type of the correct size.
+            let size = tag.value.size(cx);
+            let align = tag.value.align(cx);
+
+            let tag_type = match tag.value {
+                Int(t, _) => t,
+                F32 => Integer::I32,
+                F64 => Integer::I64,
+                Pointer => cx.data_layout().ptr_sized_integer(),
+            }
+            .to_ty(cx.tcx, false);
+
+            let tag_metadata = basic_type_metadata(cx, tag_type);
+            unsafe {
+                Some(llvm::LLVMRustDIBuilderCreateMemberType(
+                    DIB(cx),
+                    containing_scope,
+                    discriminator_name.as_ptr().cast(),
+                    discriminator_name.len(),
+                    file_metadata,
+                    UNKNOWN_LINE_NUMBER,
+                    size.bits(),
+                    align.abi.bits() as u32,
+                    layout.fields.offset(tag_field).bits(),
+                    DIFlags::FlagArtificial,
+                    tag_metadata,
+                ))
+            }
+        }
+
+        Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, tag_field, .. } => {
+            let discr_type = tag.value.to_ty(cx.tcx);
+            let (size, align) = cx.size_and_align_of(discr_type);
+
+            let discr_metadata = basic_type_metadata(cx, discr_type);
+            unsafe {
+                Some(llvm::LLVMRustDIBuilderCreateMemberType(
+                    DIB(cx),
+                    containing_scope,
+                    discriminator_name.as_ptr().cast(),
+                    discriminator_name.len(),
+                    file_metadata,
+                    UNKNOWN_LINE_NUMBER,
+                    size.bits(),
+                    align.bits() as u32,
+                    layout.fields.offset(tag_field).bits(),
+                    DIFlags::FlagArtificial,
+                    discr_metadata,
+                ))
+            }
+        }
+    };
+
+    let mut outer_fields = match layout.variants {
+        Variants::Single { .. } => vec![],
+        Variants::Multiple { .. } => {
+            let tuple_mdf = TupleMemberDescriptionFactory {
+                ty: enum_type,
+                component_types: outer_field_tys,
+                span,
+            };
+            tuple_mdf
+                .create_member_descriptions(cx)
+                .into_iter()
+                .map(|desc| Some(desc.into_metadata(cx, containing_scope)))
+                .collect()
+        }
+    };
+
+    let variant_part_unique_type_id_str = debug_context(cx)
+        .type_map
+        .borrow_mut()
+        .get_unique_type_id_str_of_enum_variant_part(unique_type_id);
+    let empty_array = create_DIArray(DIB(cx), &[]);
+    let name = "";
+    let variant_part = unsafe {
+        llvm::LLVMRustDIBuilderCreateVariantPart(
+            DIB(cx),
+            containing_scope,
+            name.as_ptr().cast(),
+            name.len(),
+            file_metadata,
+            UNKNOWN_LINE_NUMBER,
+            layout.size.bits(),
+            layout.align.abi.bits() as u32,
+            enum_flags,
+            discriminator_metadata,
+            empty_array,
+            variant_part_unique_type_id_str.as_ptr().cast(),
+            variant_part_unique_type_id_str.len(),
+        )
+    };
+    outer_fields.push(Some(variant_part));
+
+    let struct_wrapper = {
+        // The variant part must be wrapped in a struct according to DWARF.
+        let type_array = create_DIArray(DIB(cx), &outer_fields);
+
+        let type_map = debug_context(cx).type_map.borrow();
+        let unique_type_id_str = type_map.get_unique_type_id_as_string(unique_type_id);
+
+        unsafe {
+            llvm::LLVMRustDIBuilderCreateStructType(
+                DIB(cx),
+                Some(containing_scope),
+                enum_name.as_ptr().cast(),
+                enum_name.len(),
+                file_metadata,
+                UNKNOWN_LINE_NUMBER,
+                layout.size.bits(),
+                layout.align.abi.bits() as u32,
+                enum_flags,
+                None,
+                type_array,
+                0,
+                None,
+                unique_type_id_str.as_ptr().cast(),
+                unique_type_id_str.len(),
+            )
+        }
+    };
+
+    create_and_register_recursive_type_forward_declaration(
+        cx,
+        enum_type,
+        unique_type_id,
+        struct_wrapper,
+        variant_part,
+        EnumMDF(EnumMemberDescriptionFactory {
+            enum_type,
+            layout,
+            tag_type_metadata: None,
+            containing_scope,
+            span,
+        }),
+    )
+}
+
+/// Creates debug information for a composite type, that is, anything that
+/// results in a LLVM struct.
+///
+/// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums.
+fn composite_type_metadata(
+    cx: &CodegenCx<'ll, 'tcx>,
+    composite_type: Ty<'tcx>,
+    composite_type_name: &str,
+    composite_type_unique_id: UniqueTypeId,
+    member_descriptions: Vec<MemberDescription<'ll>>,
+    containing_scope: Option<&'ll DIScope>,
+
+    // Ignore source location information as long as it
+    // can't be reconstructed for non-local crates.
+    _file_metadata: &'ll DIFile,
+    _definition_span: Span,
+) -> &'ll DICompositeType {
+    // Create the (empty) struct metadata node ...
+    let composite_type_metadata = create_struct_stub(
+        cx,
+        composite_type,
+        composite_type_name,
+        composite_type_unique_id,
+        containing_scope,
+        DIFlags::FlagZero,
+    );
+    // ... and immediately create and add the member descriptions.
+    set_members_of_composite_type(cx, composite_type, composite_type_metadata, member_descriptions);
+
+    composite_type_metadata
+}
+
+fn set_members_of_composite_type(
+    cx: &CodegenCx<'ll, 'tcx>,
+    composite_type: Ty<'tcx>,
+    composite_type_metadata: &'ll DICompositeType,
+    member_descriptions: Vec<MemberDescription<'ll>>,
+) {
+    // In some rare cases LLVM metadata uniquing would lead to an existing type
+    // description being used instead of a new one created in
+    // create_struct_stub. This would cause a hard to trace assertion in
+    // DICompositeType::SetTypeArray(). The following check makes sure that we
+    // get a better error message if this should happen again due to some
+    // regression.
+    {
+        let mut composite_types_completed =
+            debug_context(cx).composite_types_completed.borrow_mut();
+        if !composite_types_completed.insert(&composite_type_metadata) {
+            bug!(
+                "debuginfo::set_members_of_composite_type() - \
+                  Already completed forward declaration re-encountered."
+            );
+        }
+    }
+
+    let member_metadata: Vec<_> = member_descriptions
+        .into_iter()
+        .map(|desc| Some(desc.into_metadata(cx, composite_type_metadata)))
+        .collect();
+
+    let type_params = compute_type_parameters(cx, composite_type);
+    unsafe {
+        let type_array = create_DIArray(DIB(cx), &member_metadata[..]);
+        llvm::LLVMRustDICompositeTypeReplaceArrays(
+            DIB(cx),
+            composite_type_metadata,
+            Some(type_array),
+            type_params,
+        );
+    }
+}
+
+/// Computes the type parameters for a type, if any, for the given metadata.
+fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> Option<&'ll DIArray> {
+    if let ty::Adt(def, substs) = *ty.kind() {
+        if substs.types().next().is_some() {
+            let generics = cx.tcx.generics_of(def.did);
+            let names = get_parameter_names(cx, generics);
+            let template_params: Vec<_> = substs
+                .iter()
+                .zip(names)
+                .filter_map(|(kind, name)| {
+                    if let GenericArgKind::Type(ty) = kind.unpack() {
+                        let actual_type =
+                            cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
+                        let actual_type_metadata =
+                            type_metadata(cx, actual_type, rustc_span::DUMMY_SP);
+                        let name = &name.as_str();
+                        Some(unsafe {
+                            Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
+                                DIB(cx),
+                                None,
+                                name.as_ptr().cast(),
+                                name.len(),
+                                actual_type_metadata,
+                            ))
+                        })
+                    } else {
+                        None
+                    }
+                })
+                .collect();
+
+            return Some(create_DIArray(DIB(cx), &template_params[..]));
+        }
+    }
+    return Some(create_DIArray(DIB(cx), &[]));
+
+    fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec<Symbol> {
+        let mut names = generics
+            .parent
+            .map_or(vec![], |def_id| get_parameter_names(cx, cx.tcx.generics_of(def_id)));
+        names.extend(generics.params.iter().map(|param| param.name));
+        names
+    }
+}
+
+/// A convenience wrapper around `LLVMRustDIBuilderCreateStructType()`. Does not do
+/// any caching, does not add any fields to the struct. This can be done later
+/// with `set_members_of_composite_type()`.
+fn create_struct_stub(
+    cx: &CodegenCx<'ll, 'tcx>,
+    struct_type: Ty<'tcx>,
+    struct_type_name: &str,
+    unique_type_id: UniqueTypeId,
+    containing_scope: Option<&'ll DIScope>,
+    flags: DIFlags,
+) -> &'ll DICompositeType {
+    let (struct_size, struct_align) = cx.size_and_align_of(struct_type);
+
+    let type_map = debug_context(cx).type_map.borrow();
+    let unique_type_id = type_map.get_unique_type_id_as_string(unique_type_id);
+
+    let metadata_stub = unsafe {
+        // `LLVMRustDIBuilderCreateStructType()` wants an empty array. A null
+        // pointer will lead to hard to trace and debug LLVM assertions
+        // later on in `llvm/lib/IR/Value.cpp`.
+        let empty_array = create_DIArray(DIB(cx), &[]);
+
+        llvm::LLVMRustDIBuilderCreateStructType(
+            DIB(cx),
+            containing_scope,
+            struct_type_name.as_ptr().cast(),
+            struct_type_name.len(),
+            unknown_file_metadata(cx),
+            UNKNOWN_LINE_NUMBER,
+            struct_size.bits(),
+            struct_align.bits() as u32,
+            flags,
+            None,
+            empty_array,
+            0,
+            None,
+            unique_type_id.as_ptr().cast(),
+            unique_type_id.len(),
+        )
+    };
+
+    metadata_stub
+}
+
+fn create_union_stub(
+    cx: &CodegenCx<'ll, 'tcx>,
+    union_type: Ty<'tcx>,
+    union_type_name: &str,
+    unique_type_id: UniqueTypeId,
+    containing_scope: &'ll DIScope,
+) -> &'ll DICompositeType {
+    let (union_size, union_align) = cx.size_and_align_of(union_type);
+
+    let type_map = debug_context(cx).type_map.borrow();
+    let unique_type_id = type_map.get_unique_type_id_as_string(unique_type_id);
+
+    let metadata_stub = unsafe {
+        // `LLVMRustDIBuilderCreateUnionType()` wants an empty array. A null
+        // pointer will lead to hard to trace and debug LLVM assertions
+        // later on in `llvm/lib/IR/Value.cpp`.
+        let empty_array = create_DIArray(DIB(cx), &[]);
+
+        llvm::LLVMRustDIBuilderCreateUnionType(
+            DIB(cx),
+            containing_scope,
+            union_type_name.as_ptr().cast(),
+            union_type_name.len(),
+            unknown_file_metadata(cx),
+            UNKNOWN_LINE_NUMBER,
+            union_size.bits(),
+            union_align.bits() as u32,
+            DIFlags::FlagZero,
+            Some(empty_array),
+            0, // RuntimeLang
+            unique_type_id.as_ptr().cast(),
+            unique_type_id.len(),
+        )
+    };
+
+    metadata_stub
+}
+
+/// Creates debug information for the given global variable.
+///
+/// Adds the created metadata nodes directly to the crate's IR.
+pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global: &'ll Value) {
+    if cx.dbg_cx.is_none() {
+        return;
+    }
+
+    // Only create type information if full debuginfo is enabled
+    if cx.sess().opts.debuginfo != DebugInfo::Full {
+        return;
+    }
+
+    let tcx = cx.tcx;
+
+    // We may want to remove the namespace scope if we're in an extern block (see
+    // https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952).
+    let var_scope = get_namespace_for_item(cx, def_id);
+    let span = tcx.def_span(def_id);
+
+    let (file_metadata, line_number) = if !span.is_dummy() {
+        let loc = cx.lookup_debug_loc(span.lo());
+        (file_metadata(cx, &loc.file, LOCAL_CRATE), loc.line)
+    } else {
+        (unknown_file_metadata(cx), None)
+    };
+
+    let is_local_to_unit = is_node_local_to_unit(cx, def_id);
+    let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx, ty::ParamEnv::reveal_all());
+    let type_metadata = type_metadata(cx, variable_type, span);
+    let var_name = tcx.item_name(def_id).as_str();
+    let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id)).name;
+    // When empty, linkage_name field is omitted,
+    // which is what we want for no_mangle statics
+    let linkage_name = if var_name == linkage_name { "" } else { linkage_name };
+
+    let global_align = cx.align_of(variable_type);
+
+    unsafe {
+        llvm::LLVMRustDIBuilderCreateStaticVariable(
+            DIB(cx),
+            Some(var_scope),
+            var_name.as_ptr().cast(),
+            var_name.len(),
+            linkage_name.as_ptr().cast(),
+            linkage_name.len(),
+            file_metadata,
+            line_number.unwrap_or(UNKNOWN_LINE_NUMBER),
+            type_metadata,
+            is_local_to_unit,
+            global,
+            None,
+            global_align.bytes() as u32,
+        );
+    }
+}
+
+/// Creates debug information for the given vtable, which is for the
+/// given type.
+///
+/// Adds the created metadata nodes directly to the crate's IR.
+pub fn create_vtable_metadata(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, vtable: &'ll Value) {
+    if cx.dbg_cx.is_none() {
+        return;
+    }
+
+    // Only create type information if full debuginfo is enabled
+    if cx.sess().opts.debuginfo != DebugInfo::Full {
+        return;
+    }
+
+    let type_metadata = type_metadata(cx, ty, rustc_span::DUMMY_SP);
+
+    unsafe {
+        // `LLVMRustDIBuilderCreateStructType()` wants an empty array. A null
+        // pointer will lead to hard to trace and debug LLVM assertions
+        // later on in `llvm/lib/IR/Value.cpp`.
+        let empty_array = create_DIArray(DIB(cx), &[]);
+        let name = "vtable";
+
+        // Create a new one each time. We don't want metadata caching
+        // here, because each vtable will refer to a unique containing
+        // type.
+        let vtable_type = llvm::LLVMRustDIBuilderCreateStructType(
+            DIB(cx),
+            NO_SCOPE_METADATA,
+            name.as_ptr().cast(),
+            name.len(),
+            unknown_file_metadata(cx),
+            UNKNOWN_LINE_NUMBER,
+            Size::ZERO.bits(),
+            cx.tcx.data_layout.pointer_align.abi.bits() as u32,
+            DIFlags::FlagArtificial,
+            None,
+            empty_array,
+            0,
+            Some(type_metadata),
+            name.as_ptr().cast(),
+            name.len(),
+        );
+
+        let linkage_name = "";
+        llvm::LLVMRustDIBuilderCreateStaticVariable(
+            DIB(cx),
+            NO_SCOPE_METADATA,
+            name.as_ptr().cast(),
+            name.len(),
+            linkage_name.as_ptr().cast(),
+            linkage_name.len(),
+            unknown_file_metadata(cx),
+            UNKNOWN_LINE_NUMBER,
+            vtable_type,
+            true,
+            vtable,
+            None,
+            0,
+        );
+    }
+}
+
+/// Creates an "extension" of an existing `DIScope` into another file.
+pub fn extend_scope_to_file(
+    cx: &CodegenCx<'ll, '_>,
+    scope_metadata: &'ll DIScope,
+    file: &rustc_span::SourceFile,
+    defining_crate: CrateNum,
+) -> &'ll DILexicalBlock {
+    let file_metadata = file_metadata(cx, &file, defining_crate);
+    unsafe { llvm::LLVMRustDIBuilderCreateLexicalBlockFile(DIB(cx), scope_metadata, file_metadata) }
+}
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
new file mode 100644
index 0000000..7cdd366
--- /dev/null
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -0,0 +1,563 @@
+// See doc.rs for documentation.
+mod doc;
+
+use rustc_codegen_ssa::mir::debuginfo::VariableKind::*;
+
+use self::metadata::{file_metadata, type_metadata, TypeMap, UNKNOWN_LINE_NUMBER};
+use self::namespace::mangled_name_of_instance;
+use self::type_names::compute_debuginfo_type_name;
+use self::utils::{create_DIArray, is_node_local_to_unit, DIB};
+
+use crate::abi::FnAbi;
+use crate::builder::Builder;
+use crate::common::CodegenCx;
+use crate::llvm;
+use crate::llvm::debuginfo::{
+    DIArray, DIBuilder, DIFile, DIFlags, DILexicalBlock, DISPFlags, DIScope, DIType, DIVariable,
+};
+use crate::value::Value;
+
+use rustc_codegen_ssa::debuginfo::type_names;
+use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind};
+use rustc_codegen_ssa::traits::*;
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE};
+use rustc_index::vec::IndexVec;
+use rustc_middle::mir;
+use rustc_middle::ty::layout::HasTyCtxt;
+use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
+use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeFoldable};
+use rustc_session::config::{self, DebugInfo};
+use rustc_span::symbol::Symbol;
+use rustc_span::{self, BytePos, Span};
+use rustc_target::abi::{LayoutOf, Primitive, Size};
+
+use libc::c_uint;
+use smallvec::SmallVec;
+use std::cell::RefCell;
+use tracing::debug;
+
+mod create_scope_map;
+pub mod gdb;
+pub mod metadata;
+mod namespace;
+mod source_loc;
+mod utils;
+
+pub use self::create_scope_map::compute_mir_scopes;
+pub use self::metadata::create_global_var_metadata;
+pub use self::metadata::extend_scope_to_file;
+
+#[allow(non_upper_case_globals)]
+const DW_TAG_auto_variable: c_uint = 0x100;
+#[allow(non_upper_case_globals)]
+const DW_TAG_arg_variable: c_uint = 0x101;
+
+/// A context object for maintaining all state needed by the debuginfo module.
+pub struct CrateDebugContext<'a, 'tcx> {
+    llcontext: &'a llvm::Context,
+    llmod: &'a llvm::Module,
+    builder: &'a mut DIBuilder<'a>,
+    created_files: RefCell<FxHashMap<(Option<String>, Option<String>), &'a DIFile>>,
+    created_enum_disr_types: RefCell<FxHashMap<(DefId, Primitive), &'a DIType>>,
+
+    type_map: RefCell<TypeMap<'a, 'tcx>>,
+    namespace_map: RefCell<DefIdMap<&'a DIScope>>,
+
+    // This collection is used to assert that composite types (structs, enums,
+    // ...) have their members only set once:
+    composite_types_completed: RefCell<FxHashSet<&'a DIType>>,
+}
+
+impl Drop for CrateDebugContext<'a, 'tcx> {
+    fn drop(&mut self) {
+        unsafe {
+            llvm::LLVMRustDIBuilderDispose(&mut *(self.builder as *mut _));
+        }
+    }
+}
+
+impl<'a, 'tcx> CrateDebugContext<'a, 'tcx> {
+    pub fn new(llmod: &'a llvm::Module) -> Self {
+        debug!("CrateDebugContext::new");
+        let builder = unsafe { llvm::LLVMRustDIBuilderCreate(llmod) };
+        // DIBuilder inherits context from the module, so we'd better use the same one
+        let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
+        CrateDebugContext {
+            llcontext,
+            llmod,
+            builder,
+            created_files: Default::default(),
+            created_enum_disr_types: Default::default(),
+            type_map: Default::default(),
+            namespace_map: RefCell::new(Default::default()),
+            composite_types_completed: Default::default(),
+        }
+    }
+}
+
+/// Creates any deferred debug metadata nodes
+pub fn finalize(cx: &CodegenCx<'_, '_>) {
+    if cx.dbg_cx.is_none() {
+        return;
+    }
+
+    debug!("finalize");
+
+    if gdb::needs_gdb_debug_scripts_section(cx) {
+        // Add a .debug_gdb_scripts section to this compile-unit. This will
+        // cause GDB to try and load the gdb_load_rust_pretty_printers.py file,
+        // which activates the Rust pretty printers for binary this section is
+        // contained in.
+        gdb::get_or_insert_gdb_debug_scripts_section_global(cx);
+    }
+
+    unsafe {
+        llvm::LLVMRustDIBuilderFinalize(DIB(cx));
+        // Debuginfo generation in LLVM by default uses a higher
+        // version of dwarf than macOS currently understands. We can
+        // instruct LLVM to emit an older version of dwarf, however,
+        // for macOS to understand. For more info see #11352
+        // This can be overridden using --llvm-opts -dwarf-version,N.
+        // Android has the same issue (#22398)
+        if cx.sess().target.target.options.is_like_osx
+            || cx.sess().target.target.options.is_like_android
+        {
+            llvm::LLVMRustAddModuleFlag(cx.llmod, "Dwarf Version\0".as_ptr().cast(), 2)
+        }
+
+        // Indicate that we want CodeView debug information on MSVC
+        if cx.sess().target.target.options.is_like_msvc {
+            llvm::LLVMRustAddModuleFlag(cx.llmod, "CodeView\0".as_ptr().cast(), 1)
+        }
+
+        // Prevent bitcode readers from deleting the debug info.
+        let ptr = "Debug Info Version\0".as_ptr();
+        llvm::LLVMRustAddModuleFlag(cx.llmod, ptr.cast(), llvm::LLVMRustDebugMetadataVersion());
+    };
+}
+
+impl DebugInfoBuilderMethods for Builder<'a, 'll, 'tcx> {
+    // FIXME(eddyb) find a common convention for all of the debuginfo-related
+    // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
+    fn dbg_var_addr(
+        &mut self,
+        dbg_var: &'ll DIVariable,
+        scope_metadata: &'ll DIScope,
+        variable_alloca: Self::Value,
+        direct_offset: Size,
+        indirect_offsets: &[Size],
+        span: Span,
+    ) {
+        let cx = self.cx();
+
+        // Convert the direct and indirect offsets to address ops.
+        // FIXME(eddyb) use `const`s instead of getting the values via FFI,
+        // the values should match the ones in the DWARF standard anyway.
+        let op_deref = || unsafe { llvm::LLVMRustDIBuilderCreateOpDeref() };
+        let op_plus_uconst = || unsafe { llvm::LLVMRustDIBuilderCreateOpPlusUconst() };
+        let mut addr_ops = SmallVec::<[_; 8]>::new();
+
+        if direct_offset.bytes() > 0 {
+            addr_ops.push(op_plus_uconst());
+            addr_ops.push(direct_offset.bytes() as i64);
+        }
+        for &offset in indirect_offsets {
+            addr_ops.push(op_deref());
+            if offset.bytes() > 0 {
+                addr_ops.push(op_plus_uconst());
+                addr_ops.push(offset.bytes() as i64);
+            }
+        }
+
+        // FIXME(eddyb) maybe this information could be extracted from `dbg_var`,
+        // to avoid having to pass it down in both places?
+        // NB: `var` doesn't seem to know about the column, so that's a limitation.
+        let dbg_loc = cx.create_debug_loc(scope_metadata, span);
+        unsafe {
+            // FIXME(eddyb) replace `llvm.dbg.declare` with `llvm.dbg.addr`.
+            llvm::LLVMRustDIBuilderInsertDeclareAtEnd(
+                DIB(cx),
+                variable_alloca,
+                dbg_var,
+                addr_ops.as_ptr(),
+                addr_ops.len() as c_uint,
+                dbg_loc,
+                self.llbb(),
+            );
+        }
+    }
+
+    fn set_source_location(&mut self, scope: &'ll DIScope, span: Span) {
+        debug!("set_source_location: {}", self.sess().source_map().span_to_string(span));
+
+        let dbg_loc = self.cx().create_debug_loc(scope, span);
+
+        unsafe {
+            llvm::LLVMSetCurrentDebugLocation(self.llbuilder, dbg_loc);
+        }
+    }
+    fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) {
+        gdb::insert_reference_to_gdb_debug_scripts_section_global(self)
+    }
+
+    fn set_var_name(&mut self, value: &'ll Value, name: &str) {
+        // Avoid wasting time if LLVM value names aren't even enabled.
+        if self.sess().fewer_names() {
+            return;
+        }
+
+        // Only function parameters and instructions are local to a function,
+        // don't change the name of anything else (e.g. globals).
+        let param_or_inst = unsafe {
+            llvm::LLVMIsAArgument(value).is_some() || llvm::LLVMIsAInstruction(value).is_some()
+        };
+        if !param_or_inst {
+            return;
+        }
+
+        // Avoid replacing the name if it already exists.
+        // While we could combine the names somehow, it'd
+        // get noisy quick, and the usefulness is dubious.
+        if llvm::get_value_name(value).is_empty() {
+            llvm::set_value_name(value, name.as_bytes());
+        }
+    }
+}
+
+impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
+    fn create_function_debug_context(
+        &self,
+        instance: Instance<'tcx>,
+        fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
+        llfn: &'ll Value,
+        mir: &mir::Body<'_>,
+    ) -> Option<FunctionDebugContext<&'ll DIScope>> {
+        if self.sess().opts.debuginfo == DebugInfo::None {
+            return None;
+        }
+
+        let span = mir.span;
+
+        // This can be the case for functions inlined from another crate
+        if span.is_dummy() {
+            // FIXME(simulacrum): Probably can't happen; remove.
+            return None;
+        }
+
+        let def_id = instance.def_id();
+        let containing_scope = get_containing_scope(self, instance);
+        let loc = self.lookup_debug_loc(span.lo());
+        let file_metadata = file_metadata(self, &loc.file, def_id.krate);
+
+        let function_type_metadata = unsafe {
+            let fn_signature = get_function_signature(self, fn_abi);
+            llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(self), fn_signature)
+        };
+
+        // Find the enclosing function, in case this is a closure.
+        let def_key = self.tcx().def_key(def_id);
+        let mut name = def_key.disambiguated_data.data.to_string();
+
+        let enclosing_fn_def_id = self.tcx().closure_base_def_id(def_id);
+
+        // Get_template_parameters() will append a `<...>` clause to the function
+        // name if necessary.
+        let generics = self.tcx().generics_of(enclosing_fn_def_id);
+        let substs = instance.substs.truncate_to(self.tcx(), generics);
+        let template_parameters = get_template_parameters(self, &generics, substs, &mut name);
+
+        let linkage_name = &mangled_name_of_instance(self, instance).name;
+        // Omit the linkage_name if it is the same as subprogram name.
+        let linkage_name = if &name == linkage_name { "" } else { linkage_name };
+
+        // FIXME(eddyb) does this need to be separate from `loc.line` for some reason?
+        let scope_line = loc.line;
+
+        let mut flags = DIFlags::FlagPrototyped;
+
+        if fn_abi.ret.layout.abi.is_uninhabited() {
+            flags |= DIFlags::FlagNoReturn;
+        }
+
+        let mut spflags = DISPFlags::SPFlagDefinition;
+        if is_node_local_to_unit(self, def_id) {
+            spflags |= DISPFlags::SPFlagLocalToUnit;
+        }
+        if self.sess().opts.optimize != config::OptLevel::No {
+            spflags |= DISPFlags::SPFlagOptimized;
+        }
+        if let Some((id, _)) = self.tcx.entry_fn(LOCAL_CRATE) {
+            if id.to_def_id() == def_id {
+                spflags |= DISPFlags::SPFlagMainSubprogram;
+            }
+        }
+
+        let fn_metadata = unsafe {
+            llvm::LLVMRustDIBuilderCreateFunction(
+                DIB(self),
+                containing_scope,
+                name.as_ptr().cast(),
+                name.len(),
+                linkage_name.as_ptr().cast(),
+                linkage_name.len(),
+                file_metadata,
+                loc.line.unwrap_or(UNKNOWN_LINE_NUMBER),
+                function_type_metadata,
+                scope_line.unwrap_or(UNKNOWN_LINE_NUMBER),
+                flags,
+                spflags,
+                llfn,
+                template_parameters,
+                None,
+            )
+        };
+
+        // Initialize fn debug context (including scopes).
+        // FIXME(eddyb) figure out a way to not need `Option` for `scope_metadata`.
+        let null_scope = DebugScope {
+            scope_metadata: None,
+            file_start_pos: BytePos(0),
+            file_end_pos: BytePos(0),
+        };
+        let mut fn_debug_context = FunctionDebugContext {
+            scopes: IndexVec::from_elem(null_scope, &mir.source_scopes),
+            defining_crate: def_id.krate,
+        };
+
+        // Fill in all the scopes, with the information from the MIR body.
+        compute_mir_scopes(self, mir, fn_metadata, &mut fn_debug_context);
+
+        return Some(fn_debug_context);
+
+        fn get_function_signature<'ll, 'tcx>(
+            cx: &CodegenCx<'ll, 'tcx>,
+            fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
+        ) -> &'ll DIArray {
+            if cx.sess().opts.debuginfo == DebugInfo::Limited {
+                return create_DIArray(DIB(cx), &[]);
+            }
+
+            let mut signature = Vec::with_capacity(fn_abi.args.len() + 1);
+
+            // Return type -- llvm::DIBuilder wants this at index 0
+            signature.push(if fn_abi.ret.is_ignore() {
+                None
+            } else {
+                Some(type_metadata(cx, fn_abi.ret.layout.ty, rustc_span::DUMMY_SP))
+            });
+
+            // Arguments types
+            if cx.sess().target.target.options.is_like_msvc {
+                // FIXME(#42800):
+                // There is a bug in MSDIA that leads to a crash when it encounters
+                // a fixed-size array of `u8` or something zero-sized in a
+                // function-type (see #40477).
+                // As a workaround, we replace those fixed-size arrays with a
+                // pointer-type. So a function `fn foo(a: u8, b: [u8; 4])` would
+                // appear as `fn foo(a: u8, b: *const u8)` in debuginfo,
+                // and a function `fn bar(x: [(); 7])` as `fn bar(x: *const ())`.
+                // This transformed type is wrong, but these function types are
+                // already inaccurate due to ABI adjustments (see #42800).
+                signature.extend(fn_abi.args.iter().map(|arg| {
+                    let t = arg.layout.ty;
+                    let t = match t.kind() {
+                        ty::Array(ct, _)
+                            if (*ct == cx.tcx.types.u8) || cx.layout_of(ct).is_zst() =>
+                        {
+                            cx.tcx.mk_imm_ptr(ct)
+                        }
+                        _ => t,
+                    };
+                    Some(type_metadata(cx, t, rustc_span::DUMMY_SP))
+                }));
+            } else {
+                signature.extend(
+                    fn_abi
+                        .args
+                        .iter()
+                        .map(|arg| Some(type_metadata(cx, arg.layout.ty, rustc_span::DUMMY_SP))),
+                );
+            }
+
+            create_DIArray(DIB(cx), &signature[..])
+        }
+
+        fn get_template_parameters<'ll, 'tcx>(
+            cx: &CodegenCx<'ll, 'tcx>,
+            generics: &ty::Generics,
+            substs: SubstsRef<'tcx>,
+            name_to_append_suffix_to: &mut String,
+        ) -> &'ll DIArray {
+            if substs.types().next().is_none() {
+                return create_DIArray(DIB(cx), &[]);
+            }
+
+            name_to_append_suffix_to.push('<');
+            for (i, actual_type) in substs.types().enumerate() {
+                if i != 0 {
+                    name_to_append_suffix_to.push_str(",");
+                }
+
+                let actual_type =
+                    cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), actual_type);
+                // Add actual type name to <...> clause of function name
+                let actual_type_name = compute_debuginfo_type_name(cx.tcx(), actual_type, true);
+                name_to_append_suffix_to.push_str(&actual_type_name[..]);
+            }
+            name_to_append_suffix_to.push('>');
+
+            // Again, only create type information if full debuginfo is enabled
+            let template_params: Vec<_> = if cx.sess().opts.debuginfo == DebugInfo::Full {
+                let names = get_parameter_names(cx, generics);
+                substs
+                    .iter()
+                    .zip(names)
+                    .filter_map(|(kind, name)| {
+                        if let GenericArgKind::Type(ty) = kind.unpack() {
+                            let actual_type =
+                                cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
+                            let actual_type_metadata =
+                                type_metadata(cx, actual_type, rustc_span::DUMMY_SP);
+                            let name = name.as_str();
+                            Some(unsafe {
+                                Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
+                                    DIB(cx),
+                                    None,
+                                    name.as_ptr().cast(),
+                                    name.len(),
+                                    actual_type_metadata,
+                                ))
+                            })
+                        } else {
+                            None
+                        }
+                    })
+                    .collect()
+            } else {
+                vec![]
+            };
+
+            create_DIArray(DIB(cx), &template_params[..])
+        }
+
+        fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec<Symbol> {
+            let mut names = generics
+                .parent
+                .map_or(vec![], |def_id| get_parameter_names(cx, cx.tcx.generics_of(def_id)));
+            names.extend(generics.params.iter().map(|param| param.name));
+            names
+        }
+
+        fn get_containing_scope<'ll, 'tcx>(
+            cx: &CodegenCx<'ll, 'tcx>,
+            instance: Instance<'tcx>,
+        ) -> &'ll DIScope {
+            // First, let's see if this is a method within an inherent impl. Because
+            // if yes, we want to make the result subroutine DIE a child of the
+            // subroutine's self-type.
+            let self_type = cx.tcx.impl_of_method(instance.def_id()).and_then(|impl_def_id| {
+                // If the method does *not* belong to a trait, proceed
+                if cx.tcx.trait_id_of_impl(impl_def_id).is_none() {
+                    let impl_self_ty = cx.tcx.subst_and_normalize_erasing_regions(
+                        instance.substs,
+                        ty::ParamEnv::reveal_all(),
+                        &cx.tcx.type_of(impl_def_id),
+                    );
+
+                    // Only "class" methods are generally understood by LLVM,
+                    // so avoid methods on other types (e.g., `<*mut T>::null`).
+                    match impl_self_ty.kind() {
+                        ty::Adt(def, ..) if !def.is_box() => {
+                            // Again, only create type information if full debuginfo is enabled
+                            if cx.sess().opts.debuginfo == DebugInfo::Full
+                                && !impl_self_ty.needs_subst()
+                            {
+                                Some(type_metadata(cx, impl_self_ty, rustc_span::DUMMY_SP))
+                            } else {
+                                Some(namespace::item_namespace(cx, def.did))
+                            }
+                        }
+                        _ => None,
+                    }
+                } else {
+                    // For trait method impls we still use the "parallel namespace"
+                    // strategy
+                    None
+                }
+            });
+
+            self_type.unwrap_or_else(|| {
+                namespace::item_namespace(
+                    cx,
+                    DefId {
+                        krate: instance.def_id().krate,
+                        index: cx
+                            .tcx
+                            .def_key(instance.def_id())
+                            .parent
+                            .expect("get_containing_scope: missing parent?"),
+                    },
+                )
+            })
+        }
+    }
+
+    fn create_vtable_metadata(&self, ty: Ty<'tcx>, vtable: Self::Value) {
+        metadata::create_vtable_metadata(self, ty, vtable)
+    }
+
+    fn extend_scope_to_file(
+        &self,
+        scope_metadata: &'ll DIScope,
+        file: &rustc_span::SourceFile,
+        defining_crate: CrateNum,
+    ) -> &'ll DILexicalBlock {
+        metadata::extend_scope_to_file(&self, scope_metadata, file, defining_crate)
+    }
+
+    fn debuginfo_finalize(&self) {
+        finalize(self)
+    }
+
+    // FIXME(eddyb) find a common convention for all of the debuginfo-related
+    // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
+    fn create_dbg_var(
+        &self,
+        dbg_context: &FunctionDebugContext<&'ll DIScope>,
+        variable_name: Symbol,
+        variable_type: Ty<'tcx>,
+        scope_metadata: &'ll DIScope,
+        variable_kind: VariableKind,
+        span: Span,
+    ) -> &'ll DIVariable {
+        let loc = self.lookup_debug_loc(span.lo());
+        let file_metadata = file_metadata(self, &loc.file, dbg_context.defining_crate);
+
+        let type_metadata = type_metadata(self, variable_type, span);
+
+        let (argument_index, dwarf_tag) = match variable_kind {
+            ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),
+            LocalVariable => (0, DW_TAG_auto_variable),
+        };
+        let align = self.align_of(variable_type);
+
+        let name = variable_name.as_str();
+        unsafe {
+            llvm::LLVMRustDIBuilderCreateVariable(
+                DIB(self),
+                dwarf_tag,
+                scope_metadata,
+                name.as_ptr().cast(),
+                name.len(),
+                file_metadata,
+                loc.line.unwrap_or(UNKNOWN_LINE_NUMBER),
+                type_metadata,
+                true,
+                DIFlags::FlagZero,
+                argument_index,
+                align.bytes() as u32,
+            )
+        }
+    }
+}
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
new file mode 100644
index 0000000..9945d4f
--- /dev/null
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
@@ -0,0 +1,55 @@
+// Namespace Handling.
+
+use super::utils::{debug_context, DIB};
+use rustc_middle::ty::{self, Instance};
+
+use crate::common::CodegenCx;
+use crate::llvm;
+use crate::llvm::debuginfo::DIScope;
+use rustc_hir::def_id::DefId;
+use rustc_hir::definitions::DefPathData;
+
+pub fn mangled_name_of_instance<'a, 'tcx>(
+    cx: &CodegenCx<'a, 'tcx>,
+    instance: Instance<'tcx>,
+) -> ty::SymbolName<'tcx> {
+    let tcx = cx.tcx;
+    tcx.symbol_name(instance)
+}
+
+pub fn item_namespace(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope {
+    if let Some(&scope) = debug_context(cx).namespace_map.borrow().get(&def_id) {
+        return scope;
+    }
+
+    let def_key = cx.tcx.def_key(def_id);
+    let parent_scope = def_key
+        .parent
+        .map(|parent| item_namespace(cx, DefId { krate: def_id.krate, index: parent }));
+
+    let crate_name_as_str;
+    let name_to_string;
+    let namespace_name = match def_key.disambiguated_data.data {
+        DefPathData::CrateRoot => {
+            crate_name_as_str = cx.tcx.crate_name(def_id.krate).as_str();
+            &*crate_name_as_str
+        }
+        data => {
+            name_to_string = data.to_string();
+            &*name_to_string
+        }
+    };
+
+    let scope = unsafe {
+        llvm::LLVMRustDIBuilderCreateNameSpace(
+            DIB(cx),
+            parent_scope,
+            namespace_name.as_ptr().cast(),
+            namespace_name.len(),
+            false, // ExportSymbols (only relevant for C++ anonymous namespaces)
+        )
+    };
+
+    debug_context(cx).namespace_map.borrow_mut().insert(def_id, scope);
+    scope
+}
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/source_loc.rs b/compiler/rustc_codegen_llvm/src/debuginfo/source_loc.rs
new file mode 100644
index 0000000..66ae9d7
--- /dev/null
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/source_loc.rs
@@ -0,0 +1,61 @@
+use super::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER};
+use super::utils::debug_context;
+
+use crate::common::CodegenCx;
+use crate::llvm::debuginfo::DIScope;
+use crate::llvm::{self, Value};
+use rustc_codegen_ssa::traits::*;
+
+use rustc_data_structures::sync::Lrc;
+use rustc_span::{BytePos, Pos, SourceFile, SourceFileAndLine, Span};
+
+/// A source code location used to generate debug information.
+pub struct DebugLoc {
+    /// Information about the original source file.
+    pub file: Lrc<SourceFile>,
+    /// The (1-based) line number.
+    pub line: Option<u32>,
+    /// The (1-based) column number.
+    pub col: Option<u32>,
+}
+
+impl CodegenCx<'ll, '_> {
+    /// Looks up debug source information about a `BytePos`.
+    pub fn lookup_debug_loc(&self, pos: BytePos) -> DebugLoc {
+        let (file, line, col) = match self.sess().source_map().lookup_line(pos) {
+            Ok(SourceFileAndLine { sf: file, line }) => {
+                let line_pos = file.line_begin_pos(pos);
+
+                // Use 1-based indexing.
+                let line = (line + 1) as u32;
+                let col = (pos - line_pos).to_u32() + 1;
+
+                (file, Some(line), Some(col))
+            }
+            Err(file) => (file, None, None),
+        };
+
+        // For MSVC, omit the column number.
+        // Otherwise, emit it. This mimics clang behaviour.
+        // See discussion in https://github.com/rust-lang/rust/issues/42921
+        if self.sess().target.target.options.is_like_msvc {
+            DebugLoc { file, line, col: None }
+        } else {
+            DebugLoc { file, line, col }
+        }
+    }
+
+    pub fn create_debug_loc(&self, scope: &'ll DIScope, span: Span) -> &'ll Value {
+        let DebugLoc { line, col, .. } = self.lookup_debug_loc(span.lo());
+
+        unsafe {
+            llvm::LLVMRustDIBuilderCreateDebugLocation(
+                debug_context(self).llcontext,
+                line.unwrap_or(UNKNOWN_LINE_NUMBER),
+                col.unwrap_or(UNKNOWN_COLUMN_NUMBER),
+                scope,
+                None,
+            )
+        }
+    }
+}
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
new file mode 100644
index 0000000..ee188e6
--- /dev/null
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/utils.rs
@@ -0,0 +1,43 @@
+// Utility Functions.
+
+use super::namespace::item_namespace;
+use super::CrateDebugContext;
+
+use rustc_hir::def_id::DefId;
+use rustc_middle::ty::DefIdTree;
+
+use crate::common::CodegenCx;
+use crate::llvm;
+use crate::llvm::debuginfo::{DIArray, DIBuilder, DIDescriptor, DIScope};
+
+pub fn is_node_local_to_unit(cx: &CodegenCx<'_, '_>, def_id: DefId) -> bool {
+    // The is_local_to_unit flag indicates whether a function is local to the
+    // current compilation unit (i.e., if it is *static* in the C-sense). The
+    // *reachable* set should provide a good approximation of this, as it
+    // contains everything that might leak out of the current crate (by being
+    // externally visible or by being inlined into something externally
+    // visible). It might better to use the `exported_items` set from
+    // `driver::CrateAnalysis` in the future, but (atm) this set is not
+    // available in the codegen pass.
+    !cx.tcx.is_reachable_non_generic(def_id)
+}
+
+#[allow(non_snake_case)]
+pub fn create_DIArray(builder: &DIBuilder<'ll>, arr: &[Option<&'ll DIDescriptor>]) -> &'ll DIArray {
+    unsafe { llvm::LLVMRustDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32) }
+}
+
+#[inline]
+pub fn debug_context(cx: &'a CodegenCx<'ll, 'tcx>) -> &'a CrateDebugContext<'ll, 'tcx> {
+    cx.dbg_cx.as_ref().unwrap()
+}
+
+#[inline]
+#[allow(non_snake_case)]
+pub fn DIB(cx: &'a CodegenCx<'ll, '_>) -> &'a DIBuilder<'ll> {
+    cx.dbg_cx.as_ref().unwrap().builder
+}
+
+pub fn get_namespace_for_item(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope {
+    item_namespace(cx, cx.tcx.parent(def_id).expect("get_namespace_for_item: missing parent?"))
+}