metadata.rs 87.1 KB
Newer Older
N
Nick Cameron 已提交
1 2 3 4
use self::RecursiveTypeDescription::*;
use self::MemberDescriptionFactory::*;
use self::EnumDiscriminantInfo::*;

5
use super::utils::{debug_context, DIB, span_start,
6
                   get_namespace_for_item, create_DIArray, is_node_local_to_unit};
7
use super::namespace::mangled_name_of_instance;
8
use super::type_names::compute_debuginfo_type_name;
9
use super::{CrateDebugContext};
T
Taiki Endo 已提交
10 11
use crate::abi;
use crate::value::Value;
12
use rustc_codegen_ssa::traits::*;
N
Nick Cameron 已提交
13

T
Taiki Endo 已提交
14 15
use crate::llvm;
use crate::llvm::debuginfo::{DIArray, DIType, DIFile, DIScope, DIDescriptor,
J
Josh Stone 已提交
16
                      DICompositeType, DILexicalBlock, DIFlags, DebugEmissionKind};
T
Taiki Endo 已提交
17
use crate::llvm_util;
N
Nick Cameron 已提交
18

T
Taiki Endo 已提交
19
use crate::common::CodegenCx;
20
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
I
Irina Popa 已提交
21
use rustc::hir::CodegenFnAttrFlags;
22
use rustc::hir::def::CtorKind;
23
use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
24
use rustc::ich::NodeIdHashingMode;
25
use rustc::mir::Field;
26
use rustc::mir::GeneratorLayout;
M
Marcel Hellwig 已提交
27
use rustc::mir::interpret::truncate;
28
use rustc_data_structures::fingerprint::Fingerprint;
29
use rustc::ty::Instance;
30
use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
31
use rustc::ty::layout::{self, Align, Integer, IntegerExt, LayoutOf,
32
                        PrimitiveExt, Size, TyLayout, VariantIdx};
33
use rustc::ty::subst::UnpackedKind;
34
use rustc::session::config;
35
use rustc::util::nodemap::FxHashMap;
36
use rustc_fs_util::path_to_c_string;
37
use rustc_data_structures::small_c_str::SmallCStr;
38
use rustc_target::abi::HasDataLayout;
N
Nick Cameron 已提交
39 40 41

use libc::{c_uint, c_longlong};
use std::ffi::CString;
42 43
use std::fmt::{self, Write};
use std::hash::{Hash, Hasher};
44
use std::iter;
N
Nick Cameron 已提交
45
use std::ptr;
46
use std::path::{Path, PathBuf};
47
use syntax::ast;
48
use syntax::symbol::{Interner, InternedString, Symbol};
49
use syntax_pos::{self, Span, FileName};
N
Nick Cameron 已提交
50

51 52
impl PartialEq for llvm::Metadata {
    fn eq(&self, other: &Self) -> bool {
53
        ptr::eq(self, other)
54 55 56 57 58 59 60 61 62 63 64 65
    }
}

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 {
66
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 68 69
        (self as *const Self).fmt(f)
    }
}
70

T
Tom Tromey 已提交
71 72 73
// From DWARF 5.
// See http://www.dwarfstd.org/ShowIssue.php?issue=140129.1
const DW_LANG_RUST: c_uint = 0x1c;
N
Nick Cameron 已提交
74 75 76 77 78 79 80 81 82 83 84
#[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;

N
Nick Cameron 已提交
85 86 87
pub const UNKNOWN_LINE_NUMBER: c_uint = 0;
pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0;

88
pub const NO_SCOPE_METADATA: Option<&DIScope> = None;
N
Nick Cameron 已提交
89 90 91 92 93 94 95 96

#[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)]
pub struct UniqueTypeId(ast::Name);

// 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
// UniqueTypeIds.
97
#[derive(Default)]
98
pub struct TypeMap<'ll, 'tcx> {
N
Nick Cameron 已提交
99
    // The UniqueTypeIds created so far
100
    unique_id_interner: Interner,
N
Nick Cameron 已提交
101
    // A map from UniqueTypeId to debuginfo metadata for that type. This is a 1:1 mapping.
102
    unique_id_to_metadata: FxHashMap<UniqueTypeId, &'ll DIType>,
N
Nick Cameron 已提交
103
    // A map from types to debuginfo metadata. This is a N:1 mapping.
104
    type_to_metadata: FxHashMap<Ty<'tcx>, &'ll DIType>,
N
Nick Cameron 已提交
105
    // A map from types to UniqueTypeId. This is a N:1 mapping.
106
    type_to_unique_id: FxHashMap<Ty<'tcx>, UniqueTypeId>
N
Nick Cameron 已提交
107 108
}

109
impl TypeMap<'ll, 'tcx> {
N
Nick Cameron 已提交
110 111
    // Adds a Ty to metadata mapping to the TypeMap. The method will fail if
    // the mapping already exists.
112 113 114 115 116
    fn register_type_with_metadata(
        &mut self,
        type_: Ty<'tcx>,
        metadata: &'ll DIType,
    ) {
N
Nick Cameron 已提交
117
        if self.type_to_metadata.insert(type_, metadata).is_some() {
118
            bug!("Type metadata for Ty '{}' is already in the TypeMap!", type_);
N
Nick Cameron 已提交
119 120 121
        }
    }

122 123 124 125 126 127 128 129 130
    // Removes a Ty to metadata mapping
    // This is useful when computing the metadata for a potentially
    // recursive type (e.g. a function ptr 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
A
Aaron Hill 已提交
131
    // for the function before we compute its actual metadata.
132 133 134 135 136 137
    // 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
A
Aaron Hill 已提交
138
    // mapping after we've computed the actual metadata
139 140 141 142 143 144 145 146 147
    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_);
        }
    }

N
Nick Cameron 已提交
148 149
    // Adds a UniqueTypeId to metadata mapping to the TypeMap. The method will
    // fail if the mapping already exists.
150 151 152 153 154
    fn register_unique_id_with_metadata(
        &mut self,
        unique_type_id: UniqueTypeId,
        metadata: &'ll DIType,
    ) {
N
Nick Cameron 已提交
155
        if self.unique_id_to_metadata.insert(unique_type_id, metadata).is_some() {
156
            bug!("Type metadata for unique id '{}' is already in the TypeMap!",
J
Jeffrey Seyfried 已提交
157
                 self.get_unique_type_id_as_string(unique_type_id));
N
Nick Cameron 已提交
158 159 160
        }
    }

161
    fn find_metadata_for_type(&self, type_: Ty<'tcx>) -> Option<&'ll DIType> {
N
Nick Cameron 已提交
162 163 164
        self.type_to_metadata.get(&type_).cloned()
    }

165
    fn find_metadata_for_unique_id(&self, unique_type_id: UniqueTypeId) -> Option<&'ll DIType> {
N
Nick Cameron 已提交
166 167 168 169 170
        self.unique_id_to_metadata.get(&unique_type_id).cloned()
    }

    // Get the string representation of a UniqueTypeId. This method will fail if
    // the id is unknown.
J
Jeffrey Seyfried 已提交
171
    fn get_unique_type_id_as_string(&self, unique_type_id: UniqueTypeId) -> &str {
N
Nick Cameron 已提交
172 173 174 175 176 177 178
        let UniqueTypeId(interner_key) = unique_type_id;
        self.unique_id_interner.get(interner_key)
    }

    // Get 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.
179
    fn get_unique_type_id_of_type<'a>(&mut self, cx: &CodegenCx<'a, 'tcx>,
N
Nick Cameron 已提交
180
                                      type_: Ty<'tcx>) -> UniqueTypeId {
181
        // Let's see if we already have something in the cache
182
        if let Some(unique_type_id) = self.type_to_unique_id.get(&type_).cloned() {
183
            return unique_type_id;
184 185
        }
        // if not, generate one
N
Nick Cameron 已提交
186

187 188
        // The hasher we are using to generate the UniqueTypeId. We want
        // something that provides more than the 64 bits of the DefaultHasher.
189 190 191 192 193 194 195 196 197
        let mut hasher = StableHasher::<Fingerprint>::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().to_hex();
198

199
        let key = self.unique_id_interner.intern(&unique_type_id);
N
Nick Cameron 已提交
200 201 202 203 204 205 206 207 208
        self.type_to_unique_id.insert(type_, UniqueTypeId(key));

        return UniqueTypeId(key);
    }

    // Get 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,
209
                                              cx: &CodegenCx<'a, 'tcx>,
N
Nick Cameron 已提交
210 211 212 213 214
                                              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!("{}::{}",
J
Jeffrey Seyfried 已提交
215
                                           self.get_unique_type_id_as_string(enum_type_id),
N
Nick Cameron 已提交
216
                                           variant_name);
217
        let interner_key = self.unique_id_interner.intern(&enum_variant_type_id);
N
Nick Cameron 已提交
218 219
        UniqueTypeId(interner_key)
    }
220 221 222 223 224 225 226 227 228 229 230

    // Get 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<'a>(&mut self,
                                                       enum_type_id: UniqueTypeId) -> &str {
        let variant_part_type_id = format!("{}_variant_part",
                                           self.get_unique_type_id_as_string(enum_type_id));
        let interner_key = self.unique_id_interner.intern(&variant_part_type_id);
        self.unique_id_interner.get(interner_key)
    }
N
Nick Cameron 已提交
231 232 233 234 235 236 237
}

// 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.
238
enum RecursiveTypeDescription<'ll, 'tcx> {
N
Nick Cameron 已提交
239 240 241
    UnfinishedMetadata {
        unfinished_type: Ty<'tcx>,
        unique_type_id: UniqueTypeId,
242
        metadata_stub: &'ll DICompositeType,
T
Tom Tromey 已提交
243
        member_holding_stub: &'ll DICompositeType,
244
        member_description_factory: MemberDescriptionFactory<'ll, 'tcx>,
N
Nick Cameron 已提交
245
    },
246
    FinalMetadata(&'ll DICompositeType)
N
Nick Cameron 已提交
247 248
}

249 250
fn create_and_register_recursive_type_forward_declaration(
    cx: &CodegenCx<'ll, 'tcx>,
N
Nick Cameron 已提交
251 252
    unfinished_type: Ty<'tcx>,
    unique_type_id: UniqueTypeId,
253
    metadata_stub: &'ll DICompositeType,
T
Tom Tromey 已提交
254
    member_holding_stub: &'ll DICompositeType,
255 256
    member_description_factory: MemberDescriptionFactory<'ll, 'tcx>,
) -> RecursiveTypeDescription<'ll, 'tcx> {
N
Nick Cameron 已提交
257 258 259

    // Insert the stub into the TypeMap in order to allow for recursive references
    let mut type_map = debug_context(cx).type_map.borrow_mut();
260 261
    type_map.register_unique_id_with_metadata(unique_type_id, metadata_stub);
    type_map.register_type_with_metadata(unfinished_type, metadata_stub);
N
Nick Cameron 已提交
262 263

    UnfinishedMetadata {
264 265 266
        unfinished_type,
        unique_type_id,
        metadata_stub,
T
Tom Tromey 已提交
267
        member_holding_stub,
268
        member_description_factory,
N
Nick Cameron 已提交
269 270 271
    }
}

272
impl RecursiveTypeDescription<'ll, 'tcx> {
N
Nick Cameron 已提交
273 274 275
    // 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.
276
    fn finalize(&self, cx: &CodegenCx<'ll, 'tcx>) -> MetadataCreationResult<'ll> {
N
Nick Cameron 已提交
277 278 279 280 281 282
        match *self {
            FinalMetadata(metadata) => MetadataCreationResult::new(metadata, false),
            UnfinishedMetadata {
                unfinished_type,
                unique_type_id,
                metadata_stub,
T
Tom Tromey 已提交
283
                member_holding_stub,
N
Nick Cameron 已提交
284 285 286 287 288 289 290 291 292 293 294 295
                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() {
296 297 298
                        bug!("Forward declaration of potentially recursive type \
                              '{:?}' was not found in TypeMap!",
                             unfinished_type);
N
Nick Cameron 已提交
299 300 301 302 303 304 305 306 307
                    }
                }

                // ... 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,
308
                                              unfinished_type,
T
Tom Tromey 已提交
309
                                              member_holding_stub,
310
                                              member_descriptions);
N
Nick Cameron 已提交
311 312 313 314 315
                return MetadataCreationResult::new(metadata_stub, true);
            }
        }
    }
}
N
Nick Cameron 已提交
316 317 318 319 320

// 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) => (
321 322 323 324
        if let Some(metadata) = debug_context($cx).type_map
            .borrow()
            .find_metadata_for_unique_id($unique_type_id)
        {
325
            return MetadataCreationResult::new(metadata, true);
F
Florian Hahn 已提交
326
        }
N
Nick Cameron 已提交
327 328 329
    )
}

330 331 332 333 334 335 336
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> {
N
Nick Cameron 已提交
337 338 339 340
    let element_type_metadata = type_metadata(cx, element_type, span);

    return_if_metadata_created_in_meantime!(cx, unique_type_id);

341
    let (size, align) = cx.size_and_align_of(array_or_slice_type);
N
Nick Cameron 已提交
342

343
    let upper_bound = match array_or_slice_type.sty {
V
varkor 已提交
344
        ty::Array(_, len) => {
345
            len.unwrap_usize(cx.tcx) as c_longlong
346 347
        }
        _ => -1
N
Nick Cameron 已提交
348 349 350
    };

    let subrange = unsafe {
351
        Some(llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound))
N
Nick Cameron 已提交
352 353 354 355
    };

    let subscripts = create_DIArray(DIB(cx), &[subrange]);
    let metadata = unsafe {
356
        llvm::LLVMRustDIBuilderCreateArrayType(
N
Nick Cameron 已提交
357
            DIB(cx),
358
            size.bits(),
359
            align.bits() as u32,
N
Nick Cameron 已提交
360 361 362 363 364 365 366
            element_type_metadata,
            subscripts)
    };

    return MetadataCreationResult::new(metadata, false);
}

367 368 369 370 371 372 373
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> {
374
    let data_ptr_type = cx.tcx.mk_imm_ptr(element_type);
N
Nick Cameron 已提交
375

376
    let data_ptr_metadata = type_metadata(cx, data_ptr_type, span);
N
Nick Cameron 已提交
377 378 379

    return_if_metadata_created_in_meantime!(cx, unique_type_id);

380
    let slice_type_name = compute_debuginfo_type_name(cx.tcx, slice_ptr_type, true);
381 382

    let (pointer_size, pointer_align) = cx.size_and_align_of(data_ptr_type);
383
    let (usize_size, usize_align) = cx.size_and_align_of(cx.tcx.types.usize);
N
Nick Cameron 已提交
384

385
    let member_descriptions = vec![
N
Nick Cameron 已提交
386
        MemberDescription {
387
            name: "data_ptr".to_owned(),
388
            type_metadata: data_ptr_metadata,
389
            offset: Size::ZERO,
390 391
            size: pointer_size,
            align: pointer_align,
392
            flags: DIFlags::FlagZero,
T
Tom Tromey 已提交
393
            discriminant: None,
N
Nick Cameron 已提交
394 395
        },
        MemberDescription {
396
            name: "length".to_owned(),
397
            type_metadata: type_metadata(cx, cx.tcx.types.usize, span),
398 399 400
            offset: pointer_size,
            size: usize_size,
            align: usize_align,
401
            flags: DIFlags::FlagZero,
T
Tom Tromey 已提交
402
            discriminant: None,
N
Nick Cameron 已提交
403 404 405
        },
    ];

406
    let file_metadata = unknown_file_metadata(cx);
N
Nick Cameron 已提交
407 408

    let metadata = composite_type_metadata(cx,
409
                                           slice_ptr_type,
N
Nick Cameron 已提交
410 411
                                           &slice_type_name[..],
                                           unique_type_id,
412
                                           member_descriptions,
413
                                           NO_SCOPE_METADATA,
N
Nick Cameron 已提交
414 415
                                           file_metadata,
                                           span);
416
    MetadataCreationResult::new(metadata, false)
N
Nick Cameron 已提交
417 418
}

419 420 421 422 423 424
fn subroutine_type_metadata(
    cx: &CodegenCx<'ll, 'tcx>,
    unique_type_id: UniqueTypeId,
    signature: ty::PolyFnSig<'tcx>,
    span: Span,
) -> MetadataCreationResult<'ll> {
425 426 427 428
    let signature = cx.tcx.normalize_erasing_late_bound_regions(
        ty::ParamEnv::reveal_all(),
        &signature,
    );
N
Nick Cameron 已提交
429

430
    let signature_metadata: Vec<_> = iter::once(
431 432
        // return type
        match signature.output().sty {
V
varkor 已提交
433
            ty::Tuple(ref tys) if tys.is_empty() => None,
434
            _ => Some(type_metadata(cx, signature.output(), span))
435 436 437
        }
    ).chain(
        // regular arguments
438
        signature.inputs().iter().map(|argument_type| {
439
            Some(type_metadata(cx, argument_type, span))
440
        })
441
    ).collect();
N
Nick Cameron 已提交
442 443 444 445 446

    return_if_metadata_created_in_meantime!(cx, unique_type_id);

    return MetadataCreationResult::new(
        unsafe {
447
            llvm::LLVMRustDIBuilderCreateSubroutineType(
N
Nick Cameron 已提交
448
                DIB(cx),
449
                unknown_file_metadata(cx),
N
Nick Cameron 已提交
450 451 452 453 454 455 456 457 458 459 460
                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.
461 462 463 464 465 466
fn trait_pointer_metadata(
    cx: &CodegenCx<'ll, 'tcx>,
    trait_type: Ty<'tcx>,
    trait_object_type: Option<Ty<'tcx>>,
    unique_type_id: UniqueTypeId,
) -> &'ll DIType {
N
Nick Cameron 已提交
467 468 469 470
    // The implementation provided here is a stub. It makes sure that the trait
    // type is assigned the correct name, size, namespace, and source location.
    // But it does not describe the trait's methods.

471
    let containing_scope = match trait_type.sty {
472 473
        ty::Dynamic(ref data, ..) =>
            data.principal_def_id().map(|did| get_namespace_for_item(cx, did)),
N
Nick Cameron 已提交
474
        _ => {
475 476 477
            bug!("debuginfo: Unexpected trait-object type in \
                  trait_pointer_metadata(): {:?}",
                 trait_type);
N
Nick Cameron 已提交
478 479 480 481 482
        }
    };

    let trait_object_type = trait_object_type.unwrap_or(trait_type);
    let trait_type_name =
483
        compute_debuginfo_type_name(cx.tcx, trait_object_type, false);
N
Nick Cameron 已提交
484

485
    let file_metadata = unknown_file_metadata(cx);
N
Nick Cameron 已提交
486

487
    let layout = cx.layout_of(cx.tcx.mk_mut_ptr(trait_type));
488 489 490

    assert_eq!(abi::FAT_PTR_ADDR, 0);
    assert_eq!(abi::FAT_PTR_EXTRA, 1);
491 492 493

    let data_ptr_field = layout.field(cx, 0);
    let vtable_field = layout.field(cx, 1);
494
    let member_descriptions = vec![
495
        MemberDescription {
496
            name: "pointer".to_owned(),
497
            type_metadata: type_metadata(cx,
498
                cx.tcx.mk_mut_ptr(cx.tcx.types.u8),
499
                syntax_pos::DUMMY_SP),
500
            offset: layout.fields.offset(0),
501
            size: data_ptr_field.size,
502
            align: data_ptr_field.align.abi,
503
            flags: DIFlags::FlagArtificial,
T
Tom Tromey 已提交
504
            discriminant: None,
505 506
        },
        MemberDescription {
507
            name: "vtable".to_owned(),
508
            type_metadata: type_metadata(cx, vtable_field.ty, syntax_pos::DUMMY_SP),
509
            offset: layout.fields.offset(1),
510
            size: vtable_field.size,
511
            align: vtable_field.align.abi,
512
            flags: DIFlags::FlagArtificial,
T
Tom Tromey 已提交
513
            discriminant: None,
514 515 516
        },
    ];

N
Nick Cameron 已提交
517
    composite_type_metadata(cx,
518
                            trait_object_type,
N
Nick Cameron 已提交
519 520
                            &trait_type_name[..],
                            unique_type_id,
521
                            member_descriptions,
N
Nick Cameron 已提交
522
                            containing_scope,
523
                            file_metadata,
524
                            syntax_pos::DUMMY_SP)
N
Nick Cameron 已提交
525 526
}

527 528 529 530 531
pub fn type_metadata(
    cx: &CodegenCx<'ll, 'tcx>,
    t: Ty<'tcx>,
    usage_site_span: Span,
) -> &'ll DIType {
N
Nick Cameron 已提交
532 533 534 535 536 537 538 539 540 541 542
    // 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
543
                // an equivalent type (e.g., only differing in region arguments).
N
Nick Cameron 已提交
544 545 546 547 548 549 550 551
                // 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.
552
                        type_map.register_type_with_metadata(t, metadata);
N
Nick Cameron 已提交
553 554 555 556 557 558 559 560 561 562 563 564 565 566
                        return metadata;
                    },
                    None => {
                        // There really is no type metadata for this type, so
                        // proceed by creating it.
                        unique_type_id
                    }
                }
            }
        }
    };

    debug!("type_metadata: {:?}", t);

567 568
    let ptr_metadata = |ty: Ty<'tcx>| {
        match ty.sty {
V
varkor 已提交
569
            ty::Slice(typ) => {
570 571
                Ok(vec_slice_metadata(cx, t, typ, unique_type_id, usage_site_span))
            }
572
            ty::Str => {
573
                Ok(vec_slice_metadata(cx, t, cx.tcx.types.u8, unique_type_id, usage_site_span))
574
            }
V
varkor 已提交
575
            ty::Dynamic(..) => {
576 577 578 579 580 581 582
                Ok(MetadataCreationResult::new(
                    trait_pointer_metadata(cx, ty, Some(t), unique_type_id),
                    false))
            }
            _ => {
                let pointee_metadata = type_metadata(cx, ty, usage_site_span);

583 584 585 586
                if let Some(metadata) = debug_context(cx).type_map
                    .borrow()
                    .find_metadata_for_unique_id(unique_type_id)
                {
587
                    return Err(metadata);
588
                }
589 590 591 592 593 594 595

                Ok(MetadataCreationResult::new(pointer_type_metadata(cx, t, pointee_metadata),
                   false))
            }
        }
    };

596
    let MetadataCreationResult { metadata, already_stored_in_typemap } = match t.sty {
V
varkor 已提交
597
        ty::Never    |
598 599 600 601 602
        ty::Bool     |
        ty::Char     |
        ty::Int(_)   |
        ty::Uint(_)  |
        ty::Float(_) => {
N
Nick Cameron 已提交
603 604
            MetadataCreationResult::new(basic_type_metadata(cx, t), false)
        }
V
varkor 已提交
605
        ty::Tuple(ref elements) if elements.is_empty() => {
N
Nick Cameron 已提交
606 607
            MetadataCreationResult::new(basic_type_metadata(cx, t), false)
        }
V
varkor 已提交
608 609
        ty::Array(typ, _) |
        ty::Slice(typ) => {
610
            fixed_vec_metadata(cx, unique_type_id, t, typ, usage_site_span)
N
Nick Cameron 已提交
611
        }
612
        ty::Str => {
613
            fixed_vec_metadata(cx, unique_type_id, t, cx.tcx.types.i8, usage_site_span)
N
Nick Cameron 已提交
614
        }
V
varkor 已提交
615
        ty::Dynamic(..) => {
N
Nick Cameron 已提交
616
            MetadataCreationResult::new(
617 618
                trait_pointer_metadata(cx, t, None, unique_type_id),
                false)
N
Nick Cameron 已提交
619
        }
V
varkor 已提交
620
        ty::Foreign(..) => {
P
Paul Lietar 已提交
621
            MetadataCreationResult::new(
622
            foreign_type_metadata(cx, t, unique_type_id),
P
Paul Lietar 已提交
623 624
            false)
        }
V
varkor 已提交
625 626
        ty::RawPtr(ty::TypeAndMut{ty, ..}) |
        ty::Ref(_, ty, _) => {
627 628 629 630 631
            match ptr_metadata(ty) {
                Ok(res) => res,
                Err(metadata) => return metadata,
            }
        }
V
varkor 已提交
632
        ty::Adt(def, _) if def.is_box() => {
633 634 635
            match ptr_metadata(t.boxed_ty()) {
                Ok(res) => res,
                Err(metadata) => return metadata,
N
Nick Cameron 已提交
636 637
            }
        }
V
varkor 已提交
638
        ty::FnDef(..) | ty::FnPtr(_) => {
639

640 641 642 643
            if let Some(metadata) = debug_context(cx).type_map
               .borrow()
               .find_metadata_for_unique_id(unique_type_id)
            {
644
                return metadata;
645
            }
646

647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681
            // 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 *somthing* weird - the only
                    // question is what exactly it will see
                    let (size, align) = cx.size_and_align_of(t);
                    llvm::LLVMRustDIBuilderCreateBasicType(
                        DIB(cx),
                        SmallCStr::new("<recur_type>").as_ptr(),
                        size.bits(),
                        align.bits() as u32,
                        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);


682 683 684
            // This is actually a function pointer, so wrap it in pointer DI
            MetadataCreationResult::new(pointer_type_metadata(cx, t, fn_metadata), false)

N
Nick Cameron 已提交
685
        }
V
varkor 已提交
686
        ty::Closure(def_id, substs) => {
687
            let upvar_tys : Vec<_> = substs.upvar_tys(def_id, cx.tcx).collect();
688 689
            prepare_tuple_metadata(cx,
                                   t,
690
                                   &upvar_tys,
691 692
                                   unique_type_id,
                                   usage_site_span).finalize(cx)
N
Nick Cameron 已提交
693
        }
V
varkor 已提交
694
        ty::Generator(def_id, substs,  _) => {
T
Tyler Mandry 已提交
695
            let upvar_tys : Vec<_> = substs.prefix_tys(def_id, cx.tcx).map(|t| {
696
                cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)
J
John Kåre Alsaker 已提交
697
            }).collect();
698 699 700 701 702 703
            prepare_enum_metadata(cx,
                                  t,
                                  def_id,
                                  unique_type_id,
                                  usage_site_span,
                                  upvar_tys).finalize(cx)
J
John Kåre Alsaker 已提交
704
        }
V
varkor 已提交
705
        ty::Adt(def, ..) => match def.adt_kind() {
706 707 708 709 710 711 712 713
            AdtKind::Struct => {
                prepare_struct_metadata(cx,
                                        t,
                                        unique_type_id,
                                        usage_site_span).finalize(cx)
            }
            AdtKind::Union => {
                prepare_union_metadata(cx,
714 715 716
                                       t,
                                       unique_type_id,
                                       usage_site_span).finalize(cx)
717 718 719
            }
            AdtKind::Enum => {
                prepare_enum_metadata(cx,
720 721 722
                                      t,
                                      def.did,
                                      unique_type_id,
723 724
                                      usage_site_span,
                                      vec![]).finalize(cx)
725 726
            }
        },
V
varkor 已提交
727
        ty::Tuple(ref elements) => {
N
Nick Cameron 已提交
728 729 730 731 732 733 734
            prepare_tuple_metadata(cx,
                                   t,
                                   &elements[..],
                                   unique_type_id,
                                   usage_site_span).finalize(cx)
        }
        _ => {
735
            bug!("debuginfo: unexpected type in type_metadata: {:?}", t)
N
Nick Cameron 已提交
736 737 738 739 740 741 742
        }
    };

    {
        let mut type_map = debug_context(cx).type_map.borrow_mut();

        if already_stored_in_typemap {
743
            // Also make sure that we already have a TypeMap entry for the unique type id.
N
Nick Cameron 已提交
744 745 746
            let metadata_for_uid = match type_map.find_metadata_for_unique_id(unique_type_id) {
                Some(metadata) => metadata,
                None => {
747 748 749 750 751
                    span_bug!(usage_site_span,
                              "Expected type metadata for unique \
                               type id '{}' to already be in \
                               the debuginfo::TypeMap but it \
                               was not. (Ty = {})",
J
Jeffrey Seyfried 已提交
752
                              type_map.get_unique_type_id_as_string(unique_type_id),
753
                              t);
N
Nick Cameron 已提交
754 755 756 757 758 759
                }
            };

            match type_map.find_metadata_for_type(t) {
                Some(metadata) => {
                    if metadata != metadata_for_uid {
760 761 762 763 764
                        span_bug!(usage_site_span,
                                  "Mismatch between Ty and \
                                   UniqueTypeId maps in \
                                   debuginfo::TypeMap. \
                                   UniqueTypeId={}, Ty={}",
J
Jeffrey Seyfried 已提交
765
                                  type_map.get_unique_type_id_as_string(unique_type_id),
766
                                  t);
N
Nick Cameron 已提交
767 768 769
                    }
                }
                None => {
770
                    type_map.register_type_with_metadata(t, metadata);
N
Nick Cameron 已提交
771 772 773
                }
            }
        } else {
774 775
            type_map.register_type_with_metadata(t, metadata);
            type_map.register_unique_id_with_metadata(unique_type_id, metadata);
N
Nick Cameron 已提交
776 777 778 779 780 781
        }
    }

    metadata
}

782
pub fn file_metadata(cx: &CodegenCx<'ll, '_>,
783
                     file_name: &FileName,
784
                     defining_crate: CrateNum) -> &'ll DIFile {
785 786 787
    debug!("file_metadata: file_name: {}, defining_crate: {}",
           file_name,
           defining_crate);
N
Nick Cameron 已提交
788

789
    let directory = if defining_crate == LOCAL_CRATE {
790
        &cx.sess().working_dir.0
791 792 793
    } 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.
794
        Path::new("")
795 796
    };

797
    file_metadata_raw(cx, &file_name.to_string(), &directory.to_string_lossy())
798 799
}

800
pub fn unknown_file_metadata(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile {
801
    file_metadata_raw(cx, "<unknown>", "")
802 803
}

804
fn file_metadata_raw(cx: &CodegenCx<'ll, '_>,
805 806
                     file_name: &str,
                     directory: &str)
807
                     -> &'ll DIFile {
808 809 810
    let key = (Symbol::intern(file_name), Symbol::intern(directory));

    if let Some(file_metadata) = debug_context(cx).created_files.borrow().get(&key) {
811
        return *file_metadata;
812 813
    }

814
    debug!("file_metadata: file_name: {}, directory: {}", file_name, directory);
815

816 817
    let file_name = SmallCStr::new(file_name);
    let directory = SmallCStr::new(directory);
818

N
Nick Cameron 已提交
819
    let file_metadata = unsafe {
820 821 822
        llvm::LLVMRustDIBuilderCreateFile(DIB(cx),
                                          file_name.as_ptr(),
                                          directory.as_ptr())
N
Nick Cameron 已提交
823 824 825
    };

    let mut created_files = debug_context(cx).created_files.borrow_mut();
826
    created_files.insert(key, file_metadata);
827
    file_metadata
N
Nick Cameron 已提交
828 829
}

830
fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
N
Nick Cameron 已提交
831 832 833
    debug!("basic_type_metadata: {:?}", t);

    let (name, encoding) = match t.sty {
V
varkor 已提交
834 835
        ty::Never => ("!", DW_ATE_unsigned),
        ty::Tuple(ref elements) if elements.is_empty() =>
836
            ("()", DW_ATE_unsigned),
837 838 839
        ty::Bool => ("bool", DW_ATE_boolean),
        ty::Char => ("char", DW_ATE_unsigned_char),
        ty::Int(int_ty) => {
840
            (int_ty.ty_to_string(), DW_ATE_signed)
N
Nick Cameron 已提交
841
        },
842
        ty::Uint(uint_ty) => {
843
            (uint_ty.ty_to_string(), DW_ATE_unsigned)
N
Nick Cameron 已提交
844
        },
845
        ty::Float(float_ty) => {
846
            (float_ty.ty_to_string(), DW_ATE_float)
N
Nick Cameron 已提交
847
        },
848
        _ => bug!("debuginfo::basic_type_metadata - t is invalid type")
N
Nick Cameron 已提交
849 850
    };

851
    let (size, align) = cx.size_and_align_of(t);
852
    let name = SmallCStr::new(name);
N
Nick Cameron 已提交
853
    let ty_metadata = unsafe {
854
        llvm::LLVMRustDIBuilderCreateBasicType(
N
Nick Cameron 已提交
855 856
            DIB(cx),
            name.as_ptr(),
857
            size.bits(),
858
            align.bits() as u32,
N
Nick Cameron 已提交
859 860 861 862 863 864
            encoding)
    };

    return ty_metadata;
}

865 866 867 868 869
fn foreign_type_metadata(
    cx: &CodegenCx<'ll, 'tcx>,
    t: Ty<'tcx>,
    unique_type_id: UniqueTypeId,
) -> &'ll DIType {
P
Paul Lietar 已提交
870 871
    debug!("foreign_type_metadata: {:?}", t);

872
    let name = compute_debuginfo_type_name(cx.tcx, t, false);
873
    create_struct_stub(cx, t, &name, unique_type_id, NO_SCOPE_METADATA)
P
Paul Lietar 已提交
874 875
}

876 877 878 879 880
fn pointer_type_metadata(
    cx: &CodegenCx<'ll, 'tcx>,
    pointer_type: Ty<'tcx>,
    pointee_type_metadata: &'ll DIType,
) -> &'ll DIType {
881
    let (pointer_size, pointer_align) = cx.size_and_align_of(pointer_type);
882
    let name = compute_debuginfo_type_name(cx.tcx, pointer_type, false);
883
    let name = SmallCStr::new(&name);
884
    unsafe {
885
        llvm::LLVMRustDIBuilderCreatePointerType(
N
Nick Cameron 已提交
886 887
            DIB(cx),
            pointee_type_metadata,
888
            pointer_size.bits(),
889
            pointer_align.bits() as u32,
N
Nick Cameron 已提交
890
            name.as_ptr())
891
    }
N
Nick Cameron 已提交
892 893
}

894
pub fn compile_unit_metadata(tcx: TyCtxt<'_, '_, '_>,
895
                             codegen_unit_name: &str,
896 897
                             debug_context: &CrateDebugContext<'ll, '_>)
                             -> &'ll DIDescriptor {
898
    let mut name_in_debuginfo = match tcx.sess.local_crate_source_file {
899
        Some(ref path) => path.clone(),
900
        None => PathBuf::from(&*tcx.crate_name(LOCAL_CRATE).as_str()),
N
Nick Cameron 已提交
901 902
    };

903 904 905 906
    // 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.
907
    if tcx.sess.target.target.options.is_like_osx {
908 909
        name_in_debuginfo.push("@");
        name_in_debuginfo.push(codegen_unit_name);
910 911 912
    }

    debug!("compile_unit_metadata: {:?}", name_in_debuginfo);
913 914
    // FIXME(#41252) Remove "clang LLVM" if we can get GDB and LLVM to play nice.
    let producer = format!("clang LLVM (rustc version {})",
N
Nick Cameron 已提交
915 916
                           (option_env!("CFG_VERSION")).expect("CFG_VERSION"));

917 918 919
    let name_in_debuginfo = name_in_debuginfo.to_string_lossy();
    let name_in_debuginfo = SmallCStr::new(&name_in_debuginfo);
    let work_dir = SmallCStr::new(&tcx.sess.working_dir.0.to_string_lossy());
M
Matt Ickstadt 已提交
920
    let producer = CString::new(producer).unwrap();
N
Nick Cameron 已提交
921 922
    let flags = "\0";
    let split_name = "\0";
J
Josh Stone 已提交
923
    let kind = DebugEmissionKind::from_generic(tcx.sess.opts.debuginfo);
M
Matt Ickstadt 已提交
924 925 926

    unsafe {
        let file_metadata = llvm::LLVMRustDIBuilderCreateFile(
927
            debug_context.builder, name_in_debuginfo.as_ptr(), work_dir.as_ptr());
M
Matt Ickstadt 已提交
928

929
        let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit(
930
            debug_context.builder,
N
Nick Cameron 已提交
931
            DW_LANG_RUST,
M
Matt Ickstadt 已提交
932
            file_metadata,
M
Matt Ickstadt 已提交
933
            producer.as_ptr(),
934
            tcx.sess.opts.optimize != config::OptLevel::No,
N
Nick Cameron 已提交
935 936
            flags.as_ptr() as *const _,
            0,
J
Josh Stone 已提交
937 938
            split_name.as_ptr() as *const _,
            kind);
939

940
        if tcx.sess.opts.debugging_opts.profile {
941 942 943 944 945
            let cu_desc_metadata = llvm::LLVMRustMetadataAsValue(debug_context.llcontext,
                                                                 unit_metadata);

            let gcov_cu_info = [
                path_to_mdstring(debug_context.llcontext,
946
                                 &tcx.output_filenames(LOCAL_CRATE).with_extension("gcno")),
947
                path_to_mdstring(debug_context.llcontext,
948
                                 &tcx.output_filenames(LOCAL_CRATE).with_extension("gcda")),
949 950 951 952 953 954
                cu_desc_metadata,
            ];
            let gcov_metadata = llvm::LLVMMDNodeInContext(debug_context.llcontext,
                                                          gcov_cu_info.as_ptr(),
                                                          gcov_cu_info.len() as c_uint);

955
            let llvm_gcov_ident = const_cstr!("llvm.gcov");
956 957 958 959
            llvm::LLVMAddNamedMetadataOperand(debug_context.llmod,
                                              llvm_gcov_ident.as_ptr(),
                                              gcov_metadata);
        }
960 961

        return unit_metadata;
N
Nick Cameron 已提交
962 963
    };

964
    fn path_to_mdstring(llcx: &'ll llvm::Context, path: &Path) -> &'ll Value {
965
        let path_str = path_to_c_string(path);
966 967 968 969 970 971
        unsafe {
            llvm::LLVMMDStringInContext(llcx,
                                        path_str.as_ptr(),
                                        path_str.as_bytes().len() as c_uint)
        }
    }
N
Nick Cameron 已提交
972 973
}

974 975
struct MetadataCreationResult<'ll> {
    metadata: &'ll DIType,
N
Nick Cameron 已提交
976 977 978
    already_stored_in_typemap: bool
}

979 980
impl MetadataCreationResult<'ll> {
    fn new(metadata: &'ll DIType, already_stored_in_typemap: bool) -> Self {
N
Nick Cameron 已提交
981
        MetadataCreationResult {
982 983
            metadata,
            already_stored_in_typemap,
N
Nick Cameron 已提交
984 985 986
        }
    }
}
N
Nick Cameron 已提交
987 988 989

// Description of a type member, which can either be a regular field (as in
// structs or tuples) or an enum variant.
N
Nick Cameron 已提交
990
#[derive(Debug)]
991
struct MemberDescription<'ll> {
N
Nick Cameron 已提交
992
    name: String,
993
    type_metadata: &'ll DIType,
994 995
    offset: Size,
    size: Size,
996
    align: Align,
997
    flags: DIFlags,
T
Tom Tromey 已提交
998
    discriminant: Option<u64>,
N
Nick Cameron 已提交
999 1000
}

1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025
impl<'ll> MemberDescription<'ll> {
    fn into_metadata(self,
                     cx: &CodegenCx<'ll, '_>,
                     composite_type_metadata: &'ll DIScope) -> &'ll DIType {
        let member_name = CString::new(self.name).unwrap();
        unsafe {
            llvm::LLVMRustDIBuilderCreateVariantMemberType(
                DIB(cx),
                composite_type_metadata,
                member_name.as_ptr(),
                unknown_file_metadata(cx),
                UNKNOWN_LINE_NUMBER,
                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)
        }
    }
}

N
Nick Cameron 已提交
1026 1027 1028 1029
// A factory for MemberDescriptions. It produces a list of member descriptions
// for some record-like type. MemberDescriptionFactories are used to defer the
// creation of type member descriptions in order to break cycles arising from
// recursive type definitions.
1030
enum MemberDescriptionFactory<'ll, 'tcx> {
N
Nick Cameron 已提交
1031 1032
    StructMDF(StructMemberDescriptionFactory<'tcx>),
    TupleMDF(TupleMemberDescriptionFactory<'tcx>),
1033
    EnumMDF(EnumMemberDescriptionFactory<'ll, 'tcx>),
1034
    UnionMDF(UnionMemberDescriptionFactory<'tcx>),
1035
    VariantMDF(VariantMemberDescriptionFactory<'ll, 'tcx>)
N
Nick Cameron 已提交
1036 1037
}

1038 1039
impl MemberDescriptionFactory<'ll, 'tcx> {
    fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
1040
                                  -> Vec<MemberDescription<'ll>> {
N
Nick Cameron 已提交
1041 1042 1043 1044 1045 1046 1047 1048 1049 1050
        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)
            }
1051 1052 1053
            UnionMDF(ref this) => {
                this.create_member_descriptions(cx)
            }
N
Nick Cameron 已提交
1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066
            VariantMDF(ref this) => {
                this.create_member_descriptions(cx)
            }
        }
    }
}

//=-----------------------------------------------------------------------------
// Structs
//=-----------------------------------------------------------------------------

// Creates MemberDescriptions for the fields of a struct
struct StructMemberDescriptionFactory<'tcx> {
1067
    ty: Ty<'tcx>,
1068
    variant: &'tcx ty::VariantDef,
N
Nick Cameron 已提交
1069 1070 1071 1072
    span: Span,
}

impl<'tcx> StructMemberDescriptionFactory<'tcx> {
1073
    fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
1074
                                  -> Vec<MemberDescription<'ll>> {
1075
        let layout = cx.layout_of(self.ty);
1076
        self.variant.fields.iter().enumerate().map(|(i, f)| {
1077
            let name = if self.variant.ctor_kind == CtorKind::Fn {
N
Nick Cameron 已提交
1078 1079
                format!("__{}", i)
            } else {
1080
                f.ident.to_string()
N
Nick Cameron 已提交
1081
            };
1082
            let field = layout.field(cx, i);
N
Nick Cameron 已提交
1083
            MemberDescription {
1084
                name,
1085
                type_metadata: type_metadata(cx, field.ty, self.span),
1086
                offset: layout.fields.offset(i),
1087
                size: field.size,
1088
                align: field.align.abi,
1089
                flags: DIFlags::FlagZero,
T
Tom Tromey 已提交
1090
                discriminant: None,
N
Nick Cameron 已提交
1091 1092 1093 1094 1095 1096
            }
        }).collect()
    }
}


1097 1098 1099 1100 1101 1102
fn prepare_struct_metadata(
    cx: &CodegenCx<'ll, 'tcx>,
    struct_type: Ty<'tcx>,
    unique_type_id: UniqueTypeId,
    span: Span,
) -> RecursiveTypeDescription<'ll, 'tcx> {
1103
    let struct_name = compute_debuginfo_type_name(cx.tcx, struct_type, false);
N
Nick Cameron 已提交
1104

1105
    let (struct_def_id, variant) = match struct_type.sty {
V
varkor 已提交
1106
        ty::Adt(def, _) => (def.did, def.non_enum_variant()),
1107
        _ => bug!("prepare_struct_metadata on a non-ADT")
1108 1109
    };

1110
    let containing_scope = get_namespace_for_item(cx, struct_def_id);
N
Nick Cameron 已提交
1111 1112

    let struct_metadata_stub = create_struct_stub(cx,
1113
                                                  struct_type,
N
Nick Cameron 已提交
1114
                                                  &struct_name,
N
Nick Cameron 已提交
1115
                                                  unique_type_id,
1116
                                                  Some(containing_scope));
N
Nick Cameron 已提交
1117 1118 1119 1120 1121 1122

    create_and_register_recursive_type_forward_declaration(
        cx,
        struct_type,
        unique_type_id,
        struct_metadata_stub,
T
Tom Tromey 已提交
1123
        struct_metadata_stub,
N
Nick Cameron 已提交
1124
        StructMDF(StructMemberDescriptionFactory {
1125
            ty: struct_type,
1126 1127
            variant,
            span,
N
Nick Cameron 已提交
1128 1129 1130 1131 1132 1133 1134 1135 1136 1137
        })
    )
}

//=-----------------------------------------------------------------------------
// Tuples
//=-----------------------------------------------------------------------------

// Creates MemberDescriptions for the fields of a tuple
struct TupleMemberDescriptionFactory<'tcx> {
1138
    ty: Ty<'tcx>,
N
Nick Cameron 已提交
1139 1140 1141 1142 1143
    component_types: Vec<Ty<'tcx>>,
    span: Span,
}

impl<'tcx> TupleMemberDescriptionFactory<'tcx> {
1144
    fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
1145
                                  -> Vec<MemberDescription<'ll>> {
1146
        let layout = cx.layout_of(self.ty);
1147 1148
        self.component_types.iter().enumerate().map(|(i, &component_type)| {
            let (size, align) = cx.size_and_align_of(component_type);
N
Nick Cameron 已提交
1149 1150 1151
            MemberDescription {
                name: format!("__{}", i),
                type_metadata: type_metadata(cx, component_type, self.span),
1152
                offset: layout.fields.offset(i),
1153 1154
                size,
                align,
1155
                flags: DIFlags::FlagZero,
T
Tom Tromey 已提交
1156
                discriminant: None,
N
Nick Cameron 已提交
1157 1158 1159 1160 1161
            }
        }).collect()
    }
}

1162 1163 1164 1165 1166 1167 1168
fn prepare_tuple_metadata(
    cx: &CodegenCx<'ll, 'tcx>,
    tuple_type: Ty<'tcx>,
    component_types: &[Ty<'tcx>],
    unique_type_id: UniqueTypeId,
    span: Span,
) -> RecursiveTypeDescription<'ll, 'tcx> {
1169
    let tuple_name = compute_debuginfo_type_name(cx.tcx, tuple_type, false);
N
Nick Cameron 已提交
1170

T
Tom Tromey 已提交
1171 1172 1173 1174 1175 1176
    let struct_stub = create_struct_stub(cx,
                                         tuple_type,
                                         &tuple_name[..],
                                         unique_type_id,
                                         NO_SCOPE_METADATA);

N
Nick Cameron 已提交
1177 1178 1179 1180
    create_and_register_recursive_type_forward_declaration(
        cx,
        tuple_type,
        unique_type_id,
T
Tom Tromey 已提交
1181 1182
        struct_stub,
        struct_stub,
N
Nick Cameron 已提交
1183
        TupleMDF(TupleMemberDescriptionFactory {
1184
            ty: tuple_type,
N
Nick Cameron 已提交
1185
            component_types: component_types.to_vec(),
1186
            span,
N
Nick Cameron 已提交
1187 1188 1189 1190
        })
    )
}

1191 1192 1193 1194 1195
//=-----------------------------------------------------------------------------
// Unions
//=-----------------------------------------------------------------------------

struct UnionMemberDescriptionFactory<'tcx> {
1196
    layout: TyLayout<'tcx>,
1197
    variant: &'tcx ty::VariantDef,
1198 1199 1200 1201
    span: Span,
}

impl<'tcx> UnionMemberDescriptionFactory<'tcx> {
1202
    fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
1203
                                  -> Vec<MemberDescription<'ll>> {
1204 1205
        self.variant.fields.iter().enumerate().map(|(i, f)| {
            let field = self.layout.field(cx, i);
1206
            MemberDescription {
1207
                name: f.ident.to_string(),
1208
                type_metadata: type_metadata(cx, field.ty, self.span),
1209
                offset: Size::ZERO,
1210
                size: field.size,
1211
                align: field.align.abi,
1212
                flags: DIFlags::FlagZero,
T
Tom Tromey 已提交
1213
                discriminant: None,
1214 1215 1216 1217 1218
            }
        }).collect()
    }
}

1219 1220 1221 1222 1223 1224
fn prepare_union_metadata(
    cx: &CodegenCx<'ll, 'tcx>,
    union_type: Ty<'tcx>,
    unique_type_id: UniqueTypeId,
    span: Span,
) -> RecursiveTypeDescription<'ll, 'tcx> {
1225
    let union_name = compute_debuginfo_type_name(cx.tcx, union_type, false);
1226

1227
    let (union_def_id, variant) = match union_type.sty {
V
varkor 已提交
1228
        ty::Adt(def, _) => (def.did, def.non_enum_variant()),
1229
        _ => bug!("prepare_union_metadata on a non-ADT")
1230 1231
    };

1232
    let containing_scope = get_namespace_for_item(cx, union_def_id);
1233 1234

    let union_metadata_stub = create_union_stub(cx,
1235
                                                union_type,
1236 1237 1238 1239 1240 1241 1242 1243 1244
                                                &union_name,
                                                unique_type_id,
                                                containing_scope);

    create_and_register_recursive_type_forward_declaration(
        cx,
        union_type,
        unique_type_id,
        union_metadata_stub,
T
Tom Tromey 已提交
1245
        union_metadata_stub,
1246
        UnionMDF(UnionMemberDescriptionFactory {
1247
            layout: cx.layout_of(union_type),
1248 1249
            variant,
            span,
1250 1251 1252
        })
    )
}
N
Nick Cameron 已提交
1253 1254 1255 1256 1257

//=-----------------------------------------------------------------------------
// Enums
//=-----------------------------------------------------------------------------

1258
// DWARF variant support is only available starting in LLVM 8.
T
Tom Tromey 已提交
1259 1260 1261
// Although the earlier enum debug info output did not work properly
// in all situations, it is better for the time being to continue to
// sometimes emit the old style rather than emit something completely
1262 1263 1264 1265
// useless when rust is compiled against LLVM 6 or older. LLVM 7
// contains an early version of the DWARF variant support, and will
// crash when handling the new debug info format. This function
// decides which representation will be emitted.
1266
fn use_enum_fallback(cx: &CodegenCx<'_, '_>) -> bool {
T
Tom Tromey 已提交
1267 1268
    // On MSVC we have to use the fallback mode, because LLVM doesn't
    // lower variant parts to PDB.
1269
    return cx.sess().target.target.options.is_like_msvc
T
Tom Tromey 已提交
1270
        // LLVM version 7 did not release with an important bug fix;
T
Tom Tromey 已提交
1271 1272 1273
        // but the required patch is in the LLVM 8.  Rust LLVM reports
        // 8 as well.
        || llvm_util::get_major_version() < 8;
T
Tom Tromey 已提交
1274 1275
}

N
Nick Cameron 已提交
1276 1277 1278 1279 1280
// 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).
1281
struct EnumMemberDescriptionFactory<'ll, 'tcx> {
N
Nick Cameron 已提交
1282
    enum_type: Ty<'tcx>,
1283
    layout: TyLayout<'tcx>,
1284 1285
    discriminant_type_metadata: Option<&'ll DIType>,
    containing_scope: &'ll DIScope,
N
Nick Cameron 已提交
1286 1287 1288
    span: Span,
}

1289 1290
impl EnumMemberDescriptionFactory<'ll, 'tcx> {
    fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
1291
                                  -> Vec<MemberDescription<'ll>> {
1292 1293 1294
        let variant_info_for = |index: VariantIdx| {
            match &self.enum_type.sty {
                ty::Adt(adt, _) => VariantInfo::Adt(&adt.variants[index]),
1295 1296 1297 1298
                ty::Generator(def_id, substs, _) => {
                    let generator_layout = cx.tcx.generator_layout(*def_id);
                    VariantInfo::Generator(*substs, generator_layout, index)
                }
1299 1300 1301
                _ => bug!(),
            }
        };
T
Tom Tromey 已提交
1302 1303 1304 1305 1306 1307 1308 1309 1310

        // 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)
        };

1311
        match self.layout.variants {
1312
            layout::Variants::Single { index } => {
1313 1314 1315 1316 1317 1318 1319
                if let ty::Adt(adt, _) = &self.enum_type.sty {
                    if adt.variants.is_empty() {
                        return vec![];
                    }
                }

                let variant_info = variant_info_for(index);
1320 1321 1322
                let (variant_type_metadata, member_description_factory) =
                    describe_enum_variant(cx,
                                          self.layout,
1323
                                          variant_info,
1324
                                          NoDiscriminant,
T
Tom Tromey 已提交
1325
                                          self_metadata,
1326
                                          self.span);
N
Nick Cameron 已提交
1327

1328 1329
                let member_descriptions =
                    member_description_factory.create_member_descriptions(cx);
N
Nick Cameron 已提交
1330

1331
                set_members_of_composite_type(cx,
1332
                                              self.enum_type,
1333
                                              variant_type_metadata,
1334
                                              member_descriptions);
1335 1336
                vec![
                    MemberDescription {
T
Tom Tromey 已提交
1337 1338 1339
                        name: if fallback {
                            String::new()
                        } else {
1340
                            variant_info.variant_name()
T
Tom Tromey 已提交
1341
                        },
1342
                        type_metadata: variant_type_metadata,
1343
                        offset: Size::ZERO,
1344
                        size: self.layout.size,
1345
                        align: self.layout.align.abi,
T
Tom Tromey 已提交
1346 1347
                        flags: DIFlags::FlagZero,
                        discriminant: None,
1348 1349
                    }
                ]
N
Nick Cameron 已提交
1350
            }
1351 1352
            layout::Variants::Multiple {
                discr_kind: layout::DiscriminantKind::Tag,
1353
                discr_index,
1354 1355 1356
                ref variants,
                ..
            } => {
T
Tom Tromey 已提交
1357
                let discriminant_info = if fallback {
1358 1359 1360 1361
                    RegularDiscriminant {
                        discr_field: Field::from(discr_index),
                        discr_type_metadata: self.discriminant_type_metadata.unwrap()
                    }
T
Tom Tromey 已提交
1362 1363 1364 1365
                } else {
                    // This doesn't matter in this case.
                    NoDiscriminant
                };
1366
                variants.iter_enumerated().map(|(i, _)| {
1367
                    let variant = self.layout.for_variant(cx, i);
1368
                    let variant_info = variant_info_for(i);
1369 1370 1371
                    let (variant_type_metadata, member_desc_factory) =
                        describe_enum_variant(cx,
                                              variant,
1372
                                              variant_info,
1373
                                              discriminant_info,
T
Tom Tromey 已提交
1374
                                              self_metadata,
1375 1376 1377 1378 1379 1380
                                              self.span);

                    let member_descriptions = member_desc_factory
                        .create_member_descriptions(cx);

                    set_members_of_composite_type(cx,
1381
                                                  self.enum_type,
1382
                                                  variant_type_metadata,
1383
                                                  member_descriptions);
1384

1385
                    MemberDescription {
T
Tom Tromey 已提交
1386 1387 1388
                        name: if fallback {
                            String::new()
                        } else {
1389
                            variant_info.variant_name()
T
Tom Tromey 已提交
1390
                        },
1391
                        type_metadata: variant_type_metadata,
1392
                        offset: Size::ZERO,
T
Tom Tromey 已提交
1393
                        size: self.layout.size,
1394
                        align: self.layout.align.abi,
T
Tom Tromey 已提交
1395
                        flags: DIFlags::FlagZero,
1396 1397 1398
                        discriminant: Some(
                            self.layout.ty.discriminant_for_variant(cx.tcx, i).unwrap().val as u64
                        ),
1399 1400 1401
                    }
                }).collect()
            }
1402 1403 1404 1405 1406 1407 1408
            layout::Variants::Multiple {
                discr_kind: layout::DiscriminantKind::Niche {
                    ref niche_variants,
                    niche_start,
                    dataful_variant,
                },
                ref discr,
T
Tom Tromey 已提交
1409
                ref variants,
1410
                discr_index,
T
Tom Tromey 已提交
1411 1412 1413 1414 1415 1416 1417
            } => {
                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,
1418
                                              variant_info_for(dataful_variant),
T
Tom Tromey 已提交
1419 1420 1421
                                              OptimizedDiscriminant,
                                              self.containing_scope,
                                              self.span);
N
Nick Cameron 已提交
1422

T
Tom Tromey 已提交
1423 1424
                    let variant_member_descriptions =
                        member_description_factory.create_member_descriptions(cx);
N
Nick Cameron 已提交
1425

T
Tom Tromey 已提交
1426
                    set_members_of_composite_type(cx,
1427
                                                  self.enum_type,
T
Tom Tromey 已提交
1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451
                                                  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: TyLayout<'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);
                            }
1452 1453
                        }
                    }
T
Tom Tromey 已提交
1454 1455
                    compute_field_path(cx, &mut name,
                                       self.layout,
1456 1457
                                       self.layout.fields.offset(discr_index),
                                       self.layout.field(cx, discr_index).size);
1458
                    variant_info_for(*niche_variants.start()).map_struct_name(|variant_name| {
1459 1460
                        name.push_str(variant_name);
                    });
T
Tom Tromey 已提交
1461 1462 1463 1464 1465 1466 1467 1468

                    // Create the (singleton) list of descriptions of union members.
                    vec![
                        MemberDescription {
                            name,
                            type_metadata: variant_type_metadata,
                            offset: Size::ZERO,
                            size: variant.size,
1469
                            align: variant.align.abi,
T
Tom Tromey 已提交
1470 1471 1472 1473 1474
                            flags: DIFlags::FlagZero,
                            discriminant: None,
                        }
                    ]
                } else {
1475
                    variants.iter_enumerated().map(|(i, _)| {
T
Tom Tromey 已提交
1476
                        let variant = self.layout.for_variant(cx, i);
1477
                        let variant_info = variant_info_for(i);
T
Tom Tromey 已提交
1478 1479 1480
                        let (variant_type_metadata, member_desc_factory) =
                            describe_enum_variant(cx,
                                                  variant,
1481
                                                  variant_info,
T
Tom Tromey 已提交
1482 1483 1484 1485 1486 1487 1488 1489
                                                  OptimizedDiscriminant,
                                                  self_metadata,
                                                  self.span);

                        let member_descriptions = member_desc_factory
                            .create_member_descriptions(cx);

                        set_members_of_composite_type(cx,
1490
                                                      self.enum_type,
T
Tom Tromey 已提交
1491 1492 1493 1494 1495 1496
                                                      variant_type_metadata,
                                                      member_descriptions);

                        let niche_value = if i == dataful_variant {
                            None
                        } else {
1497 1498
                            let value = (i.as_u32() as u128)
                                .wrapping_sub(niche_variants.start().as_u32() as u128)
1499
                                .wrapping_add(niche_start);
1500 1501 1502 1503 1504
                            let value = truncate(value, discr.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);
1505
                            Some(value as u64)
T
Tom Tromey 已提交
1506 1507 1508
                        };

                        MemberDescription {
1509
                            name: variant_info.variant_name(),
T
Tom Tromey 已提交
1510 1511 1512
                            type_metadata: variant_type_metadata,
                            offset: Size::ZERO,
                            size: self.layout.size,
1513
                            align: self.layout.align.abi,
T
Tom Tromey 已提交
1514 1515 1516 1517
                            flags: DIFlags::FlagZero,
                            discriminant: niche_value,
                        }
                    }).collect()
1518
                }
1519
            }
N
Nick Cameron 已提交
1520 1521 1522 1523 1524
        }
    }
}

// Creates MemberDescriptions for the fields of a single enum variant.
1525
struct VariantMemberDescriptionFactory<'ll, 'tcx> {
1526
    // Cloned from the layout::Struct describing the variant.
1527
    offsets: Vec<layout::Size>,
N
Nick Cameron 已提交
1528
    args: Vec<(String, Ty<'tcx>)>,
1529
    discriminant_type_metadata: Option<&'ll DIType>,
N
Nick Cameron 已提交
1530 1531 1532
    span: Span,
}

1533 1534 1535
impl VariantMemberDescriptionFactory<'ll, 'tcx> {
    fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
                                      -> Vec<MemberDescription<'ll>> {
N
Nick Cameron 已提交
1536
        self.args.iter().enumerate().map(|(i, &(ref name, ty))| {
1537
            let (size, align) = cx.size_and_align_of(ty);
N
Nick Cameron 已提交
1538 1539
            MemberDescription {
                name: name.to_string(),
T
Tom Tromey 已提交
1540 1541
                type_metadata: if use_enum_fallback(cx) {
                    match self.discriminant_type_metadata {
1542 1543
                        // Discriminant is always the first field of our variant
                        // when using the enum fallback.
T
Tom Tromey 已提交
1544 1545 1546 1547 1548
                        Some(metadata) if i == 0 => metadata,
                        _ => type_metadata(cx, ty, self.span)
                    }
                } else {
                    type_metadata(cx, ty, self.span)
N
Nick Cameron 已提交
1549
                },
1550 1551 1552
                offset: self.offsets[i],
                size,
                align,
T
Tom Tromey 已提交
1553 1554
                flags: DIFlags::FlagZero,
                discriminant: None,
N
Nick Cameron 已提交
1555 1556 1557 1558 1559 1560
            }
        }).collect()
    }
}

#[derive(Copy, Clone)]
1561
enum EnumDiscriminantInfo<'ll> {
1562
    RegularDiscriminant{ discr_field: Field, discr_type_metadata: &'ll DIType },
N
Nick Cameron 已提交
1563 1564 1565 1566
    OptimizedDiscriminant,
    NoDiscriminant
}

1567 1568 1569
#[derive(Copy, Clone)]
enum VariantInfo<'tcx> {
    Adt(&'tcx ty::VariantDef),
1570
    Generator(ty::GeneratorSubsts<'tcx>, &'tcx GeneratorLayout<'tcx>, VariantIdx),
1571 1572 1573
}

impl<'tcx> VariantInfo<'tcx> {
1574
    fn map_struct_name<R>(&self, f: impl FnOnce(&str) -> R) -> R {
1575 1576
        match self {
            VariantInfo::Adt(variant) => f(&variant.ident.as_str()),
1577
            VariantInfo::Generator(substs, _, variant_index) =>
T
Tyler Mandry 已提交
1578
                f(&substs.variant_name(*variant_index)),
1579 1580 1581
        }
    }

1582 1583 1584
    fn variant_name(&self) -> String {
        match self {
            VariantInfo::Adt(variant) => variant.ident.to_string(),
1585
            VariantInfo::Generator(_, _, variant_index) => {
1586 1587 1588 1589 1590 1591 1592
                // 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()).to_string()
            }
        }
1593 1594 1595
    }

    fn field_name(&self, i: usize) -> String {
1596
        let field_name = match self {
1597
            VariantInfo::Adt(variant) if variant.ctor_kind != CtorKind::Fn =>
1598 1599
                Some(variant.fields[i].ident.to_string()),
            VariantInfo::Generator(_, generator_layout, variant_index) => {
1600 1601 1602
                let field = generator_layout.variant_fields[*variant_index][i.into()];
                let decl = &generator_layout.__local_debuginfo_codegen_only_do_not_use[field];
                decl.name.map(|name| name.to_string())
1603 1604 1605 1606
            }
            _ => None,
        };
        field_name.unwrap_or_else(|| format!("__{}", i))
1607 1608 1609
    }
}

T
Tom Tromey 已提交
1610 1611 1612 1613
// 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.
1614 1615 1616
fn describe_enum_variant(
    cx: &CodegenCx<'ll, 'tcx>,
    layout: layout::TyLayout<'tcx>,
1617
    variant: VariantInfo<'tcx>,
1618 1619 1620 1621
    discriminant_info: EnumDiscriminantInfo<'ll>,
    containing_scope: &'ll DIScope,
    span: Span,
) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) {
1622
    let metadata_stub = variant.map_struct_name(|variant_name| {
1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634
        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))
    });
1635

N
Nick Cameron 已提交
1636
    // Build an array of (field name, field type) pairs to be captured in the factory closure.
T
Tom Tromey 已提交
1637 1638 1639
    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 {
1640
            RegularDiscriminant { discr_field, .. } => {
T
Tom Tromey 已提交
1641 1642
                // We have the layout of an enum variant, we need the layout of the outer enum
                let enum_layout = cx.layout_of(layout.ty);
1643 1644 1645 1646 1647
                let offset = enum_layout.fields.offset(discr_field.as_usize());
                let args = (
                    "RUST$ENUM$DISR".to_owned(),
                    enum_layout.field(cx, discr_field.as_usize()).ty);
                (Some(offset), Some(args))
T
Tom Tromey 已提交
1648 1649
            }
            _ => (None, None),
1650
        };
T
Tom Tromey 已提交
1651 1652 1653 1654 1655
        (
            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| {
1656
                (variant.field_name(i), layout.field(cx, i).ty)
T
Tom Tromey 已提交
1657 1658 1659 1660 1661 1662 1663 1664
            })).collect()
        )
    } else {
        (
            (0..layout.fields.count()).map(|i| {
                layout.fields.offset(i)
            }).collect(),
            (0..layout.fields.count()).map(|i| {
1665
                (variant.field_name(i), layout.field(cx, i).ty)
T
Tom Tromey 已提交
1666 1667 1668
            }).collect()
        )
    };
N
Nick Cameron 已提交
1669 1670 1671

    let member_description_factory =
        VariantMDF(VariantMemberDescriptionFactory {
1672
            offsets,
1673
            args,
N
Nick Cameron 已提交
1674
            discriminant_type_metadata: match discriminant_info {
1675 1676
                RegularDiscriminant { discr_type_metadata, .. } => {
                    Some(discr_type_metadata)
N
Nick Cameron 已提交
1677 1678 1679
                }
                _ => None
            },
1680
            span,
N
Nick Cameron 已提交
1681 1682
        });

1683
    (metadata_stub, member_description_factory)
N
Nick Cameron 已提交
1684 1685
}

1686 1687 1688 1689 1690 1691
fn prepare_enum_metadata(
    cx: &CodegenCx<'ll, 'tcx>,
    enum_type: Ty<'tcx>,
    enum_def_id: DefId,
    unique_type_id: UniqueTypeId,
    span: Span,
1692
    outer_field_tys: Vec<Ty<'tcx>>,
1693
) -> RecursiveTypeDescription<'ll, 'tcx> {
1694
    let enum_name = compute_debuginfo_type_name(cx.tcx, enum_type, false);
N
Nick Cameron 已提交
1695

1696
    let containing_scope = get_namespace_for_item(cx, enum_def_id);
1697 1698 1699 1700 1701 1702 1703
    // 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);
N
Nick Cameron 已提交
1704

1705
    let discriminant_type_metadata = |discr: layout::Primitive| {
1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721
        let enumerators_metadata: Vec<_> = match enum_type.sty {
            ty::Adt(def, _) => def
                .discriminants(cx.tcx)
                .zip(&def.variants)
                .map(|((_, discr), v)| {
                    let name = SmallCStr::new(&v.ident.as_str());
                    unsafe {
                        Some(llvm::LLVMRustDIBuilderCreateEnumerator(
                            DIB(cx),
                            name.as_ptr(),
                            // FIXME: what if enumeration has i128 discriminant?
                            discr.val as u64))
                    }
                })
                .collect(),
            ty::Generator(_, substs, _) => substs
1722
                .variant_range(enum_def_id, cx.tcx)
T
Tyler Mandry 已提交
1723 1724
                .map(|variant_index| {
                    let name = SmallCStr::new(&substs.variant_name(variant_index));
1725 1726 1727 1728 1729
                    unsafe {
                        Some(llvm::LLVMRustDIBuilderCreateEnumerator(
                            DIB(cx),
                            name.as_ptr(),
                            // FIXME: what if enumeration has i128 discriminant?
T
Tyler Mandry 已提交
1730
                            variant_index.as_usize() as u64))
1731
                    }
T
Tyler Mandry 已提交
1732
                })
1733 1734 1735
                .collect(),
            _ => bug!(),
        };
T
Tom Tromey 已提交
1736

1737
        let disr_type_key = (enum_def_id, discr);
N
Nick Cameron 已提交
1738 1739
        let cached_discriminant_type_metadata = debug_context(cx).created_enum_disr_types
                                                                 .borrow()
1740
                                                                 .get(&disr_type_key).cloned();
N
Nick Cameron 已提交
1741 1742 1743 1744
        match cached_discriminant_type_metadata {
            Some(discriminant_type_metadata) => discriminant_type_metadata,
            None => {
                let (discriminant_size, discriminant_align) =
1745
                    (discr.size(cx), discr.align(cx));
N
Nick Cameron 已提交
1746
                let discriminant_base_type_metadata =
1747
                    type_metadata(cx, discr.to_ty(cx.tcx), syntax_pos::DUMMY_SP);
N
Nick Cameron 已提交
1748

1749 1750 1751 1752 1753 1754
                let discriminant_name = match enum_type.sty {
                    ty::Adt(..) => SmallCStr::new(&cx.tcx.item_name(enum_def_id).as_str()),
                    ty::Generator(..) => SmallCStr::new(&enum_name),
                    _ => bug!(),
                };

N
Nick Cameron 已提交
1755
                let discriminant_type_metadata = unsafe {
1756
                    llvm::LLVMRustDIBuilderCreateEnumerationType(
N
Nick Cameron 已提交
1757 1758
                        DIB(cx),
                        containing_scope,
1759
                        discriminant_name.as_ptr(),
1760
                        file_metadata,
N
Nick Cameron 已提交
1761
                        UNKNOWN_LINE_NUMBER,
1762
                        discriminant_size.bits(),
1763
                        discriminant_align.abi.bits() as u32,
N
Nick Cameron 已提交
1764
                        create_DIArray(DIB(cx), &enumerators_metadata),
T
Tom Tromey 已提交
1765
                        discriminant_base_type_metadata, true)
N
Nick Cameron 已提交
1766 1767 1768 1769
                };

                debug_context(cx).created_enum_disr_types
                                 .borrow_mut()
1770
                                 .insert(disr_type_key, discriminant_type_metadata);
N
Nick Cameron 已提交
1771 1772 1773 1774 1775 1776

                discriminant_type_metadata
            }
        }
    };

1777
    let layout = cx.layout_of(enum_type);
N
Nick Cameron 已提交
1778

T
Tom Tromey 已提交
1779
    match (&layout.abi, &layout.variants) {
1780 1781 1782 1783 1784
        (&layout::Abi::Scalar(_), &layout::Variants::Multiple {
            discr_kind: layout::DiscriminantKind::Tag,
            ref discr,
            ..
        }) => return FinalMetadata(discriminant_type_metadata(discr.value)),
T
Tom Tromey 已提交
1785
        _ => {}
1786 1787
    }

1788 1789 1790 1791
    let enum_name = SmallCStr::new(&enum_name);
    let unique_type_id_str = SmallCStr::new(
        debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id)
    );
T
Tom Tromey 已提交
1792 1793 1794 1795

    if use_enum_fallback(cx) {
        let discriminant_type_metadata = match layout.variants {
            layout::Variants::Single { .. } |
1796 1797 1798 1799 1800 1801 1802 1803 1804 1805
            layout::Variants::Multiple {
                discr_kind: layout::DiscriminantKind::Niche { .. },
                ..
            } => None,
            layout::Variants::Multiple {
                discr_kind: layout::DiscriminantKind::Tag,
                ref discr,
                ..
            } => {
                Some(discriminant_type_metadata(discr.value))
T
Tom Tromey 已提交
1806 1807 1808 1809 1810 1811 1812 1813 1814 1815
            }
        };

        let enum_metadata = unsafe {
            llvm::LLVMRustDIBuilderCreateUnionType(
                DIB(cx),
                containing_scope,
                enum_name.as_ptr(),
                file_metadata,
                UNKNOWN_LINE_NUMBER,
1816
                layout.size.bits(),
1817
                layout.align.abi.bits() as u32,
T
Tom Tromey 已提交
1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839
                DIFlags::FlagZero,
                None,
                0, // RuntimeLang
                unique_type_id_str.as_ptr())
        };

        return create_and_register_recursive_type_forward_declaration(
            cx,
            enum_type,
            unique_type_id,
            enum_metadata,
            enum_metadata,
            EnumMDF(EnumMemberDescriptionFactory {
                enum_type,
                layout,
                discriminant_type_metadata,
                containing_scope,
                span,
            }),
        );
    }

1840 1841 1842 1843 1844
    let discriminator_name = match &enum_type.sty {
        ty::Generator(..) => Some(SmallCStr::new(&"__state")),
        _ => None,
    };
    let discriminator_name = discriminator_name.map(|n| n.as_ptr()).unwrap_or(ptr::null_mut());
1845
    let discriminator_metadata = match layout.variants {
T
Tom Tromey 已提交
1846
        // A single-variant enum has no discriminant.
1847
        layout::Variants::Single { .. } => None,
T
Tom Tromey 已提交
1848

1849 1850 1851
        layout::Variants::Multiple {
            discr_kind: layout::DiscriminantKind::Niche { .. },
            ref discr,
1852
            discr_index,
1853 1854
            ..
        } => {
T
Tom Tromey 已提交
1855
            // Find the integer type of the correct size.
1856 1857
            let size = discr.value.size(cx);
            let align = discr.value.align(cx);
T
Tom Tromey 已提交
1858

1859
            let discr_type = match discr.value {
T
Tom Tromey 已提交
1860 1861 1862 1863 1864
                layout::Int(t, _) => t,
                layout::Float(layout::FloatTy::F32) => Integer::I32,
                layout::Float(layout::FloatTy::F64) => Integer::I64,
                layout::Pointer => cx.data_layout().ptr_sized_integer(),
            }.to_ty(cx.tcx, false);
T
Tom Tromey 已提交
1865 1866 1867 1868 1869 1870

            let discr_metadata = basic_type_metadata(cx, discr_type);
            unsafe {
                Some(llvm::LLVMRustDIBuilderCreateMemberType(
                    DIB(cx),
                    containing_scope,
1871
                    discriminator_name,
T
Tom Tromey 已提交
1872 1873 1874
                    file_metadata,
                    UNKNOWN_LINE_NUMBER,
                    size.bits(),
1875
                    align.abi.bits() as u32,
1876
                    layout.fields.offset(discr_index).bits(),
T
Tom Tromey 已提交
1877 1878 1879 1880 1881
                    DIFlags::FlagArtificial,
                    discr_metadata))
            }
        },

1882 1883 1884
        layout::Variants::Multiple {
            discr_kind: layout::DiscriminantKind::Tag,
            ref discr,
1885
            discr_index,
1886 1887 1888
            ..
        } => {
            let discr_type = discr.value.to_ty(cx.tcx);
T
Tom Tromey 已提交
1889 1890 1891 1892 1893 1894 1895
            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,
1896
                    discriminator_name,
T
Tom Tromey 已提交
1897 1898 1899
                    file_metadata,
                    UNKNOWN_LINE_NUMBER,
                    size.bits(),
1900
                    align.bits() as u32,
1901
                    layout.fields.offset(discr_index).bits(),
T
Tom Tromey 已提交
1902 1903 1904 1905 1906 1907
                    DIFlags::FlagArtificial,
                    discr_metadata))
            }
        },
    };

1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923
    let mut outer_fields = match layout.variants {
        layout::Variants::Single { .. } => vec![],
        layout::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()
        }
    };

1924 1925 1926 1927 1928
    let variant_part_unique_type_id_str = SmallCStr::new(
        debug_context(cx).type_map
            .borrow_mut()
            .get_unique_type_id_str_of_enum_variant_part(unique_type_id)
    );
T
Tom Tromey 已提交
1929 1930 1931 1932 1933 1934 1935 1936
    let empty_array = create_DIArray(DIB(cx), &[]);
    let variant_part = unsafe {
        llvm::LLVMRustDIBuilderCreateVariantPart(
            DIB(cx),
            containing_scope,
            ptr::null_mut(),
            file_metadata,
            UNKNOWN_LINE_NUMBER,
1937
            layout.size.bits(),
1938
            layout.align.abi.bits() as u32,
T
Tom Tromey 已提交
1939 1940 1941
            DIFlags::FlagZero,
            discriminator_metadata,
            empty_array,
1942
            variant_part_unique_type_id_str.as_ptr())
T
Tom Tromey 已提交
1943
    };
1944
    outer_fields.push(Some(variant_part));
T
Tom Tromey 已提交
1945 1946

    // The variant part must be wrapped in a struct according to DWARF.
1947
    let type_array = create_DIArray(DIB(cx), &outer_fields);
T
Tom Tromey 已提交
1948 1949 1950 1951 1952 1953 1954
    let struct_wrapper = unsafe {
        llvm::LLVMRustDIBuilderCreateStructType(
            DIB(cx),
            Some(containing_scope),
            enum_name.as_ptr(),
            file_metadata,
            UNKNOWN_LINE_NUMBER,
1955
            layout.size.bits(),
1956
            layout.align.abi.bits() as u32,
T
Tom Tromey 已提交
1957 1958 1959 1960 1961 1962
            DIFlags::FlagZero,
            None,
            type_array,
            0,
            None,
            unique_type_id_str.as_ptr())
N
Nick Cameron 已提交
1963 1964 1965 1966 1967 1968
    };

    return create_and_register_recursive_type_forward_declaration(
        cx,
        enum_type,
        unique_type_id,
T
Tom Tromey 已提交
1969 1970
        struct_wrapper,
        variant_part,
N
Nick Cameron 已提交
1971
        EnumMDF(EnumMemberDescriptionFactory {
1972
            enum_type,
1973
            layout,
T
Tom Tromey 已提交
1974
            discriminant_type_metadata: None,
1975 1976
            containing_scope,
            span,
N
Nick Cameron 已提交
1977 1978 1979 1980 1981 1982 1983 1984
        }),
    );
}

/// 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.
1985 1986 1987 1988 1989
fn composite_type_metadata(
    cx: &CodegenCx<'ll, 'tcx>,
    composite_type: Ty<'tcx>,
    composite_type_name: &str,
    composite_type_unique_id: UniqueTypeId,
1990
    member_descriptions: Vec<MemberDescription<'ll>>,
1991 1992 1993 1994 1995 1996 1997
    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 {
N
Nick Cameron 已提交
1998 1999
    // Create the (empty) struct metadata node ...
    let composite_type_metadata = create_struct_stub(cx,
2000
                                                     composite_type,
N
Nick Cameron 已提交
2001 2002 2003 2004 2005
                                                     composite_type_name,
                                                     composite_type_unique_id,
                                                     containing_scope);
    // ... and immediately create and add the member descriptions.
    set_members_of_composite_type(cx,
2006
                                  composite_type,
N
Nick Cameron 已提交
2007 2008 2009
                                  composite_type_metadata,
                                  member_descriptions);

2010
    composite_type_metadata
N
Nick Cameron 已提交
2011 2012
}

2013 2014
fn set_members_of_composite_type(cx: &CodegenCx<'ll, 'tcx>,
                                 composite_type: Ty<'tcx>,
2015
                                 composite_type_metadata: &'ll DICompositeType,
2016
                                 member_descriptions: Vec<MemberDescription<'ll>>) {
N
Nick Cameron 已提交
2017 2018 2019 2020 2021 2022 2023 2024 2025 2026
    // 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.contains(&composite_type_metadata) {
2027 2028
            bug!("debuginfo::set_members_of_composite_type() - \
                  Already completed forward declaration re-encountered.");
N
Nick Cameron 已提交
2029 2030 2031 2032 2033
        } else {
            composite_types_completed.insert(composite_type_metadata);
        }
    }

2034
    let member_metadata: Vec<_> = member_descriptions
2035
        .into_iter()
2036
        .map(|desc| Some(desc.into_metadata(cx, composite_type_metadata)))
N
Nick Cameron 已提交
2037 2038
        .collect();

2039
    let type_params = compute_type_parameters(cx, composite_type);
N
Nick Cameron 已提交
2040 2041
    unsafe {
        let type_array = create_DIArray(DIB(cx), &member_metadata[..]);
2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081
        llvm::LLVMRustDICompositeTypeReplaceArrays(
            DIB(cx), composite_type_metadata, Some(type_array), type_params);
    }
}

// Compute 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.sty {
        if !substs.types().next().is_none() {
            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 UnpackedKind::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, syntax_pos::DUMMY_SP);
                    let name = SmallCStr::new(&name.as_str());
                    Some(unsafe {

                        Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
                            DIB(cx),
                            None,
                            name.as_ptr(),
                            actual_type_metadata,
                            unknown_file_metadata(cx),
                            0,
                            0,
                        ))
                    })
                } else {
                    None
                }
            }).collect();

            return Some(create_DIArray(DIB(cx), &template_params[..]));
        }
    }
    return Some(create_DIArray(DIB(cx), &[]));

2082
    fn get_parameter_names(cx: &CodegenCx<'_, '_>,
2083 2084 2085 2086 2087 2088 2089
                           generics: &ty::Generics)
                           -> Vec<InternedString> {
        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
N
Nick Cameron 已提交
2090 2091 2092
    }
}

2093 2094 2095
// 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().
2096 2097 2098 2099 2100 2101 2102
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>,
) -> &'ll DICompositeType {
2103
    let (struct_size, struct_align) = cx.size_and_align_of(struct_type);
N
Nick Cameron 已提交
2104

2105 2106 2107 2108
    let name = SmallCStr::new(struct_type_name);
    let unique_type_id = SmallCStr::new(
        debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id)
    );
N
Nick Cameron 已提交
2109
    let metadata_stub = unsafe {
2110
        // LLVMRustDIBuilderCreateStructType() wants an empty array. A null
N
Nick Cameron 已提交
2111 2112 2113 2114
        // 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), &[]);

2115
        llvm::LLVMRustDIBuilderCreateStructType(
N
Nick Cameron 已提交
2116 2117 2118
            DIB(cx),
            containing_scope,
            name.as_ptr(),
2119
            unknown_file_metadata(cx),
N
Nick Cameron 已提交
2120
            UNKNOWN_LINE_NUMBER,
2121
            struct_size.bits(),
2122
            struct_align.bits() as u32,
2123
            DIFlags::FlagZero,
2124
            None,
N
Nick Cameron 已提交
2125 2126
            empty_array,
            0,
2127
            None,
N
Nick Cameron 已提交
2128 2129 2130
            unique_type_id.as_ptr())
    };

2131
    metadata_stub
N
Nick Cameron 已提交
2132 2133
}

2134 2135 2136 2137 2138 2139 2140
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 {
2141
    let (union_size, union_align) = cx.size_and_align_of(union_type);
2142

2143 2144 2145 2146
    let name = SmallCStr::new(union_type_name);
    let unique_type_id = SmallCStr::new(
        debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id)
    );
2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158
    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,
            name.as_ptr(),
            unknown_file_metadata(cx),
            UNKNOWN_LINE_NUMBER,
2159
            union_size.bits(),
2160
            union_align.bits() as u32,
2161
            DIFlags::FlagZero,
2162
            Some(empty_array),
2163 2164 2165 2166
            0, // RuntimeLang
            unique_type_id.as_ptr())
    };

2167
    metadata_stub
2168 2169
}

N
Nick Cameron 已提交
2170 2171 2172
/// Creates debug information for the given global variable.
///
/// Adds the created metadata nodes directly to the crate's IR.
2173 2174 2175 2176 2177
pub fn create_global_var_metadata(
    cx: &CodegenCx<'ll, '_>,
    def_id: DefId,
    global: &'ll Value,
) {
2178
    if cx.dbg_cx.is_none() {
N
Nick Cameron 已提交
2179 2180 2181
        return;
    }

2182
    let tcx = cx.tcx;
I
Irina Popa 已提交
2183
    let attrs = tcx.codegen_fn_attrs(def_id);
2184

I
Irina Popa 已提交
2185
    if attrs.flags.contains(CodegenFnAttrFlags::NO_DEBUG) {
2186 2187 2188
        return;
    }

I
Irina Popa 已提交
2189
    let no_mangle = attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE);
2190 2191
    // 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
2192
    let var_scope = get_namespace_for_item(cx, def_id);
2193
    let span = tcx.def_span(def_id);
N
Nick Cameron 已提交
2194

V
Vadim Petrochenkov 已提交
2195
    let (file_metadata, line_number) = if !span.is_dummy() {
N
Nick Cameron 已提交
2196
        let loc = span_start(cx, span);
2197
        (file_metadata(cx, &loc.file.name, LOCAL_CRATE), loc.line as c_uint)
N
Nick Cameron 已提交
2198
    } else {
2199
        (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
N
Nick Cameron 已提交
2200 2201
    };

2202 2203
    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);
N
Nick Cameron 已提交
2204
    let type_metadata = type_metadata(cx, variable_type, span);
2205
    let var_name = SmallCStr::new(&tcx.item_name(def_id).as_str());
2206 2207 2208
    let linkage_name = if no_mangle {
        None
    } else {
2209
        let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id));
2210
        Some(SmallCStr::new(&linkage_name.as_str()))
2211
    };
2212

2213
    let global_align = cx.align_of(variable_type);
2214

N
Nick Cameron 已提交
2215
    unsafe {
2216
        llvm::LLVMRustDIBuilderCreateStaticVariable(DIB(cx),
2217
                                                    Some(var_scope),
2218
                                                    var_name.as_ptr(),
2219 2220 2221 2222
                                                    // If null, linkage_name field is omitted,
                                                    // which is what we want for no_mangle statics
                                                    linkage_name.as_ref()
                                                     .map_or(ptr::null(), |name| name.as_ptr()),
2223 2224 2225 2226 2227
                                                    file_metadata,
                                                    line_number,
                                                    type_metadata,
                                                    is_local_to_unit,
                                                    global,
2228
                                                    None,
2229
                                                    global_align.bytes() as u32,
2230
        );
N
Nick Cameron 已提交
2231 2232
    }
}
2233

2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266
/// 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::Ty<'tcx>,
    vtable: &'ll Value,
) {
    if cx.dbg_cx.is_none() {
        return;
    }

    let type_metadata = type_metadata(cx, ty, syntax_pos::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 = const_cstr!("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(),
            unknown_file_metadata(cx),
            UNKNOWN_LINE_NUMBER,
            Size::ZERO.bits(),
2267
            cx.tcx.data_layout.pointer_align.abi.bits() as u32,
2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278
            DIFlags::FlagArtificial,
            None,
            empty_array,
            0,
            Some(type_metadata),
            name.as_ptr()
        );

        llvm::LLVMRustDIBuilderCreateStaticVariable(DIB(cx),
                                                    NO_SCOPE_METADATA,
                                                    name.as_ptr(),
2279
                                                    ptr::null(),
2280 2281 2282 2283 2284 2285 2286 2287 2288 2289
                                                    unknown_file_metadata(cx),
                                                    UNKNOWN_LINE_NUMBER,
                                                    vtable_type,
                                                    true,
                                                    vtable,
                                                    None,
                                                    0);
    }
}

2290
// Creates an "extension" of an existing DIScope into another file.
2291 2292 2293
pub fn extend_scope_to_file(
    cx: &CodegenCx<'ll, '_>,
    scope_metadata: &'ll DIScope,
D
Donato Sciarra 已提交
2294
    file: &syntax_pos::SourceFile,
2295 2296
    defining_crate: CrateNum,
) -> &'ll DILexicalBlock {
2297
    let file_metadata = file_metadata(cx, &file.name, defining_crate);
2298 2299
    unsafe {
        llvm::LLVMRustDIBuilderCreateLexicalBlockFile(
2300
            DIB(cx),
2301 2302 2303
            scope_metadata,
            file_metadata)
    }
V
Vadim Petrochenkov 已提交
2304
}