]>
Commit | Line | Data |
---|---|---|
d9579d0f | 1 | // Copyright 2015 The Rust Project Developers. See the COPYRIGHT |
1a4d82fc JJ |
2 | // file at the top-level directory of this distribution and at |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
d9579d0f | 11 | use self::RecursiveTypeDescription::*; |
1a4d82fc JJ |
12 | use self::MemberOffset::*; |
13 | use self::MemberDescriptionFactory::*; | |
1a4d82fc | 14 | use self::EnumDiscriminantInfo::*; |
1a4d82fc | 15 | |
d9579d0f | 16 | use super::utils::{debug_context, DIB, span_start, bytes_to_bits, size_and_align_of, |
9e0c209e | 17 | get_namespace_and_span_for_item, create_DIArray, is_node_local_to_unit}; |
a7813a04 | 18 | use super::namespace::mangled_name_of_item; |
c30ab7b3 | 19 | use super::type_names::compute_debuginfo_type_name; |
9e0c209e | 20 | use super::{CrateDebugContext}; |
5bcae85e SL |
21 | use context::SharedCrateContext; |
22 | use session::Session; | |
d9579d0f AL |
23 | |
24 | use llvm::{self, ValueRef}; | |
476ff2be SL |
25 | use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, |
26 | DICompositeType, DILexicalBlock, DIFlags}; | |
d9579d0f | 27 | |
c30ab7b3 | 28 | use rustc::hir::def::CtorKind; |
54a0048b | 29 | use rustc::hir::def_id::DefId; |
c30ab7b3 | 30 | use rustc::ty::fold::TypeVisitor; |
9e0c209e | 31 | use rustc::ty::subst::Substs; |
c30ab7b3 | 32 | use rustc::ty::util::TypeIdHasher; |
9e0c209e | 33 | use rustc::hir; |
476ff2be | 34 | use rustc_data_structures::ToHex; |
9e0c209e SL |
35 | use {type_of, machine, monomorphize}; |
36 | use common::CrateContext; | |
54a0048b | 37 | use type_::Type; |
9e0c209e SL |
38 | use rustc::ty::{self, AdtKind, Ty, layout}; |
39 | use session::config; | |
476ff2be | 40 | use util::nodemap::FxHashMap; |
c34b1796 | 41 | use util::common::path2cstr; |
1a4d82fc | 42 | |
85aaf69f | 43 | use libc::{c_uint, c_longlong}; |
c34b1796 AL |
44 | use std::ffi::CString; |
45 | use std::path::Path; | |
1a4d82fc | 46 | use std::ptr; |
3157f602 | 47 | use syntax::ast; |
476ff2be | 48 | use syntax::symbol::{Interner, InternedString}; |
3157f602 | 49 | use syntax_pos::{self, Span}; |
1a4d82fc | 50 | |
c30ab7b3 | 51 | |
54a0048b SL |
52 | // From DWARF 5. |
53 | // See http://www.dwarfstd.org/ShowIssue.php?issue=140129.1 | |
54 | const DW_LANG_RUST: c_uint = 0x1c; | |
1a4d82fc JJ |
55 | #[allow(non_upper_case_globals)] |
56 | const DW_ATE_boolean: c_uint = 0x02; | |
57 | #[allow(non_upper_case_globals)] | |
58 | const DW_ATE_float: c_uint = 0x04; | |
59 | #[allow(non_upper_case_globals)] | |
60 | const DW_ATE_signed: c_uint = 0x05; | |
61 | #[allow(non_upper_case_globals)] | |
62 | const DW_ATE_unsigned: c_uint = 0x07; | |
63 | #[allow(non_upper_case_globals)] | |
64 | const DW_ATE_unsigned_char: c_uint = 0x08; | |
65 | ||
d9579d0f AL |
66 | pub const UNKNOWN_LINE_NUMBER: c_uint = 0; |
67 | pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0; | |
1a4d82fc JJ |
68 | |
69 | // ptr::null() doesn't work :( | |
a7813a04 | 70 | pub const NO_SCOPE_METADATA: DIScope = (0 as DIScope); |
1a4d82fc | 71 | |
85aaf69f | 72 | #[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)] |
d9579d0f | 73 | pub struct UniqueTypeId(ast::Name); |
1a4d82fc JJ |
74 | |
75 | // The TypeMap is where the CrateDebugContext holds the type metadata nodes | |
76 | // created so far. The metadata nodes are indexed by UniqueTypeId, and, for | |
77 | // faster lookup, also by Ty. The TypeMap is responsible for creating | |
78 | // UniqueTypeIds. | |
d9579d0f | 79 | pub struct TypeMap<'tcx> { |
1a4d82fc | 80 | // The UniqueTypeIds created so far |
5bcae85e | 81 | unique_id_interner: Interner, |
1a4d82fc | 82 | // A map from UniqueTypeId to debuginfo metadata for that type. This is a 1:1 mapping. |
476ff2be | 83 | unique_id_to_metadata: FxHashMap<UniqueTypeId, DIType>, |
1a4d82fc | 84 | // A map from types to debuginfo metadata. This is a N:1 mapping. |
476ff2be | 85 | type_to_metadata: FxHashMap<Ty<'tcx>, DIType>, |
1a4d82fc | 86 | // A map from types to UniqueTypeId. This is a N:1 mapping. |
476ff2be | 87 | type_to_unique_id: FxHashMap<Ty<'tcx>, UniqueTypeId> |
1a4d82fc JJ |
88 | } |
89 | ||
90 | impl<'tcx> TypeMap<'tcx> { | |
d9579d0f | 91 | pub fn new() -> TypeMap<'tcx> { |
1a4d82fc JJ |
92 | TypeMap { |
93 | unique_id_interner: Interner::new(), | |
476ff2be SL |
94 | type_to_metadata: FxHashMap(), |
95 | unique_id_to_metadata: FxHashMap(), | |
96 | type_to_unique_id: FxHashMap(), | |
1a4d82fc JJ |
97 | } |
98 | } | |
99 | ||
100 | // Adds a Ty to metadata mapping to the TypeMap. The method will fail if | |
101 | // the mapping already exists. | |
102 | fn register_type_with_metadata<'a>(&mut self, | |
1a4d82fc JJ |
103 | type_: Ty<'tcx>, |
104 | metadata: DIType) { | |
105 | if self.type_to_metadata.insert(type_, metadata).is_some() { | |
54a0048b | 106 | bug!("Type metadata for Ty '{}' is already in the TypeMap!", type_); |
1a4d82fc JJ |
107 | } |
108 | } | |
109 | ||
110 | // Adds a UniqueTypeId to metadata mapping to the TypeMap. The method will | |
111 | // fail if the mapping already exists. | |
112 | fn register_unique_id_with_metadata(&mut self, | |
1a4d82fc JJ |
113 | unique_type_id: UniqueTypeId, |
114 | metadata: DIType) { | |
115 | if self.unique_id_to_metadata.insert(unique_type_id, metadata).is_some() { | |
54a0048b | 116 | bug!("Type metadata for unique id '{}' is already in the TypeMap!", |
476ff2be | 117 | self.get_unique_type_id_as_string(unique_type_id)); |
1a4d82fc JJ |
118 | } |
119 | } | |
120 | ||
121 | fn find_metadata_for_type(&self, type_: Ty<'tcx>) -> Option<DIType> { | |
122 | self.type_to_metadata.get(&type_).cloned() | |
123 | } | |
124 | ||
125 | fn find_metadata_for_unique_id(&self, unique_type_id: UniqueTypeId) -> Option<DIType> { | |
126 | self.unique_id_to_metadata.get(&unique_type_id).cloned() | |
127 | } | |
128 | ||
129 | // Get the string representation of a UniqueTypeId. This method will fail if | |
130 | // the id is unknown. | |
476ff2be | 131 | fn get_unique_type_id_as_string(&self, unique_type_id: UniqueTypeId) -> &str { |
1a4d82fc JJ |
132 | let UniqueTypeId(interner_key) = unique_type_id; |
133 | self.unique_id_interner.get(interner_key) | |
134 | } | |
135 | ||
136 | // Get the UniqueTypeId for the given type. If the UniqueTypeId for the given | |
137 | // type has been requested before, this is just a table lookup. Otherwise an | |
138 | // ID will be generated and stored for later lookup. | |
139 | fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>, | |
140 | type_: Ty<'tcx>) -> UniqueTypeId { | |
c30ab7b3 | 141 | // Let's see if we already have something in the cache |
1a4d82fc JJ |
142 | match self.type_to_unique_id.get(&type_).cloned() { |
143 | Some(unique_type_id) => return unique_type_id, | |
144 | None => { /* generate one */} | |
145 | }; | |
146 | ||
c30ab7b3 SL |
147 | // The hasher we are using to generate the UniqueTypeId. We want |
148 | // something that provides more than the 64 bits of the DefaultHasher. | |
1a4d82fc | 149 | |
476ff2be | 150 | let mut type_id_hasher = TypeIdHasher::<[u8; 20]>::new(cx.tcx()); |
c30ab7b3 | 151 | type_id_hasher.visit_ty(type_); |
1a4d82fc | 152 | |
476ff2be | 153 | let unique_type_id = type_id_hasher.finish().to_hex(); |
c30ab7b3 | 154 | let key = self.unique_id_interner.intern(&unique_type_id); |
1a4d82fc JJ |
155 | self.type_to_unique_id.insert(type_, UniqueTypeId(key)); |
156 | ||
157 | return UniqueTypeId(key); | |
1a4d82fc JJ |
158 | } |
159 | ||
1a4d82fc JJ |
160 | // Get the UniqueTypeId for an enum variant. Enum variants are not really |
161 | // types of their own, so they need special handling. We still need a | |
162 | // UniqueTypeId for them, since to debuginfo they *are* real types. | |
163 | fn get_unique_type_id_of_enum_variant<'a>(&mut self, | |
164 | cx: &CrateContext<'a, 'tcx>, | |
165 | enum_type: Ty<'tcx>, | |
166 | variant_name: &str) | |
167 | -> UniqueTypeId { | |
168 | let enum_type_id = self.get_unique_type_id_of_type(cx, enum_type); | |
169 | let enum_variant_type_id = format!("{}::{}", | |
476ff2be | 170 | self.get_unique_type_id_as_string(enum_type_id), |
1a4d82fc | 171 | variant_name); |
c30ab7b3 | 172 | let interner_key = self.unique_id_interner.intern(&enum_variant_type_id); |
1a4d82fc JJ |
173 | UniqueTypeId(interner_key) |
174 | } | |
175 | } | |
176 | ||
d9579d0f AL |
177 | // A description of some recursive type. It can either be already finished (as |
178 | // with FinalMetadata) or it is not yet finished, but contains all information | |
179 | // needed to generate the missing parts of the description. See the | |
180 | // documentation section on Recursive Types at the top of this file for more | |
181 | // information. | |
182 | enum RecursiveTypeDescription<'tcx> { | |
183 | UnfinishedMetadata { | |
184 | unfinished_type: Ty<'tcx>, | |
185 | unique_type_id: UniqueTypeId, | |
186 | metadata_stub: DICompositeType, | |
187 | llvm_type: Type, | |
188 | member_description_factory: MemberDescriptionFactory<'tcx>, | |
189 | }, | |
190 | FinalMetadata(DICompositeType) | |
191 | } | |
192 | ||
193 | fn create_and_register_recursive_type_forward_declaration<'a, 'tcx>( | |
194 | cx: &CrateContext<'a, 'tcx>, | |
195 | unfinished_type: Ty<'tcx>, | |
196 | unique_type_id: UniqueTypeId, | |
197 | metadata_stub: DICompositeType, | |
198 | llvm_type: Type, | |
199 | member_description_factory: MemberDescriptionFactory<'tcx>) | |
200 | -> RecursiveTypeDescription<'tcx> { | |
201 | ||
202 | // Insert the stub into the TypeMap in order to allow for recursive references | |
203 | let mut type_map = debug_context(cx).type_map.borrow_mut(); | |
54a0048b SL |
204 | type_map.register_unique_id_with_metadata(unique_type_id, metadata_stub); |
205 | type_map.register_type_with_metadata(unfinished_type, metadata_stub); | |
d9579d0f AL |
206 | |
207 | UnfinishedMetadata { | |
208 | unfinished_type: unfinished_type, | |
209 | unique_type_id: unique_type_id, | |
210 | metadata_stub: metadata_stub, | |
211 | llvm_type: llvm_type, | |
212 | member_description_factory: member_description_factory, | |
213 | } | |
214 | } | |
215 | ||
216 | impl<'tcx> RecursiveTypeDescription<'tcx> { | |
217 | // Finishes up the description of the type in question (mostly by providing | |
218 | // descriptions of the fields of the given type) and returns the final type | |
219 | // metadata. | |
220 | fn finalize<'a>(&self, cx: &CrateContext<'a, 'tcx>) -> MetadataCreationResult { | |
221 | match *self { | |
222 | FinalMetadata(metadata) => MetadataCreationResult::new(metadata, false), | |
223 | UnfinishedMetadata { | |
224 | unfinished_type, | |
225 | unique_type_id, | |
226 | metadata_stub, | |
227 | llvm_type, | |
228 | ref member_description_factory, | |
229 | .. | |
230 | } => { | |
231 | // Make sure that we have a forward declaration of the type in | |
232 | // the TypeMap so that recursive references are possible. This | |
233 | // will always be the case if the RecursiveTypeDescription has | |
234 | // been properly created through the | |
235 | // create_and_register_recursive_type_forward_declaration() | |
236 | // function. | |
237 | { | |
238 | let type_map = debug_context(cx).type_map.borrow(); | |
239 | if type_map.find_metadata_for_unique_id(unique_type_id).is_none() || | |
240 | type_map.find_metadata_for_type(unfinished_type).is_none() { | |
54a0048b SL |
241 | bug!("Forward declaration of potentially recursive type \ |
242 | '{:?}' was not found in TypeMap!", | |
243 | unfinished_type); | |
d9579d0f AL |
244 | } |
245 | } | |
246 | ||
247 | // ... then create the member descriptions ... | |
248 | let member_descriptions = | |
249 | member_description_factory.create_member_descriptions(cx); | |
250 | ||
251 | // ... and attach them to the stub to complete it. | |
252 | set_members_of_composite_type(cx, | |
253 | metadata_stub, | |
254 | llvm_type, | |
255 | &member_descriptions[..]); | |
256 | return MetadataCreationResult::new(metadata_stub, true); | |
257 | } | |
258 | } | |
259 | } | |
260 | } | |
261 | ||
1a4d82fc JJ |
262 | // Returns from the enclosing function if the type metadata with the given |
263 | // unique id can be found in the type map | |
264 | macro_rules! return_if_metadata_created_in_meantime { | |
265 | ($cx: expr, $unique_type_id: expr) => ( | |
266 | match debug_context($cx).type_map | |
267 | .borrow() | |
268 | .find_metadata_for_unique_id($unique_type_id) { | |
269 | Some(metadata) => return MetadataCreationResult::new(metadata, true), | |
270 | None => { /* proceed normally */ } | |
b039eaaf | 271 | } |
1a4d82fc JJ |
272 | ) |
273 | } | |
274 | ||
d9579d0f AL |
275 | fn fixed_vec_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, |
276 | unique_type_id: UniqueTypeId, | |
277 | element_type: Ty<'tcx>, | |
278 | len: Option<u64>, | |
279 | span: Span) | |
280 | -> MetadataCreationResult { | |
281 | let element_type_metadata = type_metadata(cx, element_type, span); | |
282 | ||
283 | return_if_metadata_created_in_meantime!(cx, unique_type_id); | |
1a4d82fc | 284 | |
d9579d0f AL |
285 | let element_llvm_type = type_of::type_of(cx, element_type); |
286 | let (element_type_size, element_type_align) = size_and_align_of(cx, element_llvm_type); | |
1a4d82fc | 287 | |
d9579d0f AL |
288 | let (array_size_in_bytes, upper_bound) = match len { |
289 | Some(len) => (element_type_size * len, len as c_longlong), | |
290 | None => (0, -1) | |
291 | }; | |
1a4d82fc | 292 | |
d9579d0f | 293 | let subrange = unsafe { |
5bcae85e | 294 | llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound) |
d9579d0f | 295 | }; |
1a4d82fc | 296 | |
d9579d0f AL |
297 | let subscripts = create_DIArray(DIB(cx), &[subrange]); |
298 | let metadata = unsafe { | |
5bcae85e | 299 | llvm::LLVMRustDIBuilderCreateArrayType( |
d9579d0f AL |
300 | DIB(cx), |
301 | bytes_to_bits(array_size_in_bytes), | |
302 | bytes_to_bits(element_type_align), | |
303 | element_type_metadata, | |
304 | subscripts) | |
305 | }; | |
1a4d82fc | 306 | |
d9579d0f | 307 | return MetadataCreationResult::new(metadata, false); |
1a4d82fc JJ |
308 | } |
309 | ||
d9579d0f AL |
310 | fn vec_slice_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, |
311 | vec_type: Ty<'tcx>, | |
312 | element_type: Ty<'tcx>, | |
313 | unique_type_id: UniqueTypeId, | |
314 | span: Span) | |
315 | -> MetadataCreationResult { | |
c1a9b12d | 316 | let data_ptr_type = cx.tcx().mk_ptr(ty::TypeAndMut { |
d9579d0f | 317 | ty: element_type, |
e9174d1e | 318 | mutbl: hir::MutImmutable |
d9579d0f | 319 | }); |
1a4d82fc | 320 | |
d9579d0f | 321 | let element_type_metadata = type_metadata(cx, data_ptr_type, span); |
1a4d82fc | 322 | |
d9579d0f | 323 | return_if_metadata_created_in_meantime!(cx, unique_type_id); |
1a4d82fc | 324 | |
d9579d0f AL |
325 | let slice_llvm_type = type_of::type_of(cx, vec_type); |
326 | let slice_type_name = compute_debuginfo_type_name(cx, vec_type, true); | |
1a4d82fc | 327 | |
d9579d0f AL |
328 | let member_llvm_types = slice_llvm_type.field_types(); |
329 | assert!(slice_layout_is_correct(cx, | |
330 | &member_llvm_types[..], | |
331 | element_type)); | |
332 | let member_descriptions = [ | |
333 | MemberDescription { | |
334 | name: "data_ptr".to_string(), | |
335 | llvm_type: member_llvm_types[0], | |
336 | type_metadata: element_type_metadata, | |
337 | offset: ComputedMemberOffset, | |
476ff2be | 338 | flags: DIFlags::FlagZero, |
d9579d0f AL |
339 | }, |
340 | MemberDescription { | |
341 | name: "length".to_string(), | |
342 | llvm_type: member_llvm_types[1], | |
343 | type_metadata: type_metadata(cx, cx.tcx().types.usize, span), | |
344 | offset: ComputedMemberOffset, | |
476ff2be | 345 | flags: DIFlags::FlagZero, |
d9579d0f AL |
346 | }, |
347 | ]; | |
1a4d82fc | 348 | |
d9579d0f | 349 | assert!(member_descriptions.len() == member_llvm_types.len()); |
1a4d82fc | 350 | |
d9579d0f | 351 | let loc = span_start(cx, span); |
3157f602 | 352 | let file_metadata = file_metadata(cx, &loc.file.name, &loc.file.abs_path); |
1a4d82fc | 353 | |
d9579d0f AL |
354 | let metadata = composite_type_metadata(cx, |
355 | slice_llvm_type, | |
356 | &slice_type_name[..], | |
357 | unique_type_id, | |
358 | &member_descriptions, | |
e9174d1e | 359 | NO_SCOPE_METADATA, |
d9579d0f AL |
360 | file_metadata, |
361 | span); | |
362 | return MetadataCreationResult::new(metadata, false); | |
1a4d82fc | 363 | |
d9579d0f AL |
364 | fn slice_layout_is_correct<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, |
365 | member_llvm_types: &[Type], | |
366 | element_type: Ty<'tcx>) | |
367 | -> bool { | |
368 | member_llvm_types.len() == 2 && | |
369 | member_llvm_types[0] == type_of::type_of(cx, element_type).ptr_to() && | |
370 | member_llvm_types[1] == cx.int_type() | |
1a4d82fc | 371 | } |
d9579d0f | 372 | } |
1a4d82fc | 373 | |
d9579d0f AL |
374 | fn subroutine_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, |
375 | unique_type_id: UniqueTypeId, | |
376 | signature: &ty::PolyFnSig<'tcx>, | |
377 | span: Span) | |
378 | -> MetadataCreationResult | |
379 | { | |
c1a9b12d | 380 | let signature = cx.tcx().erase_late_bound_regions(signature); |
1a4d82fc | 381 | |
476ff2be | 382 | let mut signature_metadata: Vec<DIType> = Vec::with_capacity(signature.inputs().len() + 1); |
1a4d82fc | 383 | |
d9579d0f | 384 | // return type |
476ff2be | 385 | signature_metadata.push(match signature.output().sty { |
5bcae85e | 386 | ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(), |
476ff2be | 387 | _ => type_metadata(cx, signature.output(), span) |
d9579d0f | 388 | }); |
1a4d82fc | 389 | |
d9579d0f | 390 | // regular arguments |
476ff2be | 391 | for &argument_type in signature.inputs() { |
d9579d0f | 392 | signature_metadata.push(type_metadata(cx, argument_type, span)); |
1a4d82fc JJ |
393 | } |
394 | ||
d9579d0f | 395 | return_if_metadata_created_in_meantime!(cx, unique_type_id); |
1a4d82fc | 396 | |
d9579d0f AL |
397 | return MetadataCreationResult::new( |
398 | unsafe { | |
5bcae85e | 399 | llvm::LLVMRustDIBuilderCreateSubroutineType( |
d9579d0f | 400 | DIB(cx), |
5bcae85e | 401 | unknown_file_metadata(cx), |
d9579d0f | 402 | create_DIArray(DIB(cx), &signature_metadata[..])) |
1a4d82fc JJ |
403 | }, |
404 | false); | |
405 | } | |
406 | ||
407 | // FIXME(1563) This is all a bit of a hack because 'trait pointer' is an ill- | |
408 | // defined concept. For the case of an actual trait pointer (i.e., Box<Trait>, | |
409 | // &Trait), trait_object_type should be the whole thing (e.g, Box<Trait>) and | |
410 | // trait_type should be the actual trait (e.g., Trait). Where the trait is part | |
411 | // of a DST struct, there is no trait_object_type and the results of this | |
412 | // function will be a little bit weird. | |
413 | fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, | |
414 | trait_type: Ty<'tcx>, | |
415 | trait_object_type: Option<Ty<'tcx>>, | |
416 | unique_type_id: UniqueTypeId) | |
417 | -> DIType { | |
418 | // The implementation provided here is a stub. It makes sure that the trait | |
419 | // type is assigned the correct name, size, namespace, and source location. | |
420 | // But it does not describe the trait's methods. | |
421 | ||
476ff2be SL |
422 | let containing_scope = match trait_type.sty { |
423 | ty::TyDynamic(ref data, ..) => if let Some(principal) = data.principal() { | |
424 | let def_id = principal.def_id(); | |
425 | get_namespace_and_span_for_item(cx, def_id).0 | |
426 | } else { | |
427 | NO_SCOPE_METADATA | |
428 | }, | |
1a4d82fc | 429 | _ => { |
54a0048b SL |
430 | bug!("debuginfo: Unexpected trait-object type in \ |
431 | trait_pointer_metadata(): {:?}", | |
432 | trait_type); | |
1a4d82fc JJ |
433 | } |
434 | }; | |
435 | ||
436 | let trait_object_type = trait_object_type.unwrap_or(trait_type); | |
437 | let trait_type_name = | |
438 | compute_debuginfo_type_name(cx, trait_object_type, false); | |
439 | ||
1a4d82fc | 440 | let trait_llvm_type = type_of::type_of(cx, trait_object_type); |
5bcae85e | 441 | let file_metadata = unknown_file_metadata(cx); |
1a4d82fc JJ |
442 | |
443 | composite_type_metadata(cx, | |
444 | trait_llvm_type, | |
85aaf69f | 445 | &trait_type_name[..], |
1a4d82fc JJ |
446 | unique_type_id, |
447 | &[], | |
448 | containing_scope, | |
5bcae85e | 449 | file_metadata, |
3157f602 | 450 | syntax_pos::DUMMY_SP) |
1a4d82fc JJ |
451 | } |
452 | ||
d9579d0f AL |
453 | pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, |
454 | t: Ty<'tcx>, | |
455 | usage_site_span: Span) | |
456 | -> DIType { | |
1a4d82fc JJ |
457 | // Get the unique type id of this type. |
458 | let unique_type_id = { | |
459 | let mut type_map = debug_context(cx).type_map.borrow_mut(); | |
460 | // First, try to find the type in TypeMap. If we have seen it before, we | |
461 | // can exit early here. | |
462 | match type_map.find_metadata_for_type(t) { | |
463 | Some(metadata) => { | |
464 | return metadata; | |
465 | }, | |
466 | None => { | |
467 | // The Ty is not in the TypeMap but maybe we have already seen | |
468 | // an equivalent type (e.g. only differing in region arguments). | |
469 | // In order to find out, generate the unique type id and look | |
470 | // that up. | |
471 | let unique_type_id = type_map.get_unique_type_id_of_type(cx, t); | |
472 | match type_map.find_metadata_for_unique_id(unique_type_id) { | |
473 | Some(metadata) => { | |
474 | // There is already an equivalent type in the TypeMap. | |
475 | // Register this Ty as an alias in the cache and | |
476 | // return the cached metadata. | |
54a0048b | 477 | type_map.register_type_with_metadata(t, metadata); |
1a4d82fc JJ |
478 | return metadata; |
479 | }, | |
480 | None => { | |
481 | // There really is no type metadata for this type, so | |
482 | // proceed by creating it. | |
483 | unique_type_id | |
484 | } | |
485 | } | |
486 | } | |
487 | } | |
488 | }; | |
489 | ||
490 | debug!("type_metadata: {:?}", t); | |
491 | ||
492 | let sty = &t.sty; | |
493 | let MetadataCreationResult { metadata, already_stored_in_typemap } = match *sty { | |
5bcae85e | 494 | ty::TyNever | |
62682a34 SL |
495 | ty::TyBool | |
496 | ty::TyChar | | |
497 | ty::TyInt(_) | | |
498 | ty::TyUint(_) | | |
499 | ty::TyFloat(_) => { | |
1a4d82fc JJ |
500 | MetadataCreationResult::new(basic_type_metadata(cx, t), false) |
501 | } | |
62682a34 | 502 | ty::TyTuple(ref elements) if elements.is_empty() => { |
1a4d82fc JJ |
503 | MetadataCreationResult::new(basic_type_metadata(cx, t), false) |
504 | } | |
62682a34 SL |
505 | ty::TyArray(typ, len) => { |
506 | fixed_vec_metadata(cx, unique_type_id, typ, Some(len as u64), usage_site_span) | |
507 | } | |
508 | ty::TySlice(typ) => { | |
509 | fixed_vec_metadata(cx, unique_type_id, typ, None, usage_site_span) | |
85aaf69f | 510 | } |
62682a34 | 511 | ty::TyStr => { |
85aaf69f | 512 | fixed_vec_metadata(cx, unique_type_id, cx.tcx().types.i8, None, usage_site_span) |
1a4d82fc | 513 | } |
476ff2be | 514 | ty::TyDynamic(..) => { |
1a4d82fc JJ |
515 | MetadataCreationResult::new( |
516 | trait_pointer_metadata(cx, t, None, unique_type_id), | |
517 | false) | |
518 | } | |
c1a9b12d SL |
519 | ty::TyBox(ty) | |
520 | ty::TyRawPtr(ty::TypeAndMut{ty, ..}) | | |
521 | ty::TyRef(_, ty::TypeAndMut{ty, ..}) => { | |
1a4d82fc | 522 | match ty.sty { |
62682a34 | 523 | ty::TySlice(typ) => { |
1a4d82fc JJ |
524 | vec_slice_metadata(cx, t, typ, unique_type_id, usage_site_span) |
525 | } | |
62682a34 | 526 | ty::TyStr => { |
1a4d82fc JJ |
527 | vec_slice_metadata(cx, t, cx.tcx().types.u8, unique_type_id, usage_site_span) |
528 | } | |
476ff2be | 529 | ty::TyDynamic(..) => { |
1a4d82fc JJ |
530 | MetadataCreationResult::new( |
531 | trait_pointer_metadata(cx, ty, Some(t), unique_type_id), | |
532 | false) | |
533 | } | |
534 | _ => { | |
535 | let pointee_metadata = type_metadata(cx, ty, usage_site_span); | |
536 | ||
537 | match debug_context(cx).type_map | |
538 | .borrow() | |
539 | .find_metadata_for_unique_id(unique_type_id) { | |
540 | Some(metadata) => return metadata, | |
541 | None => { /* proceed normally */ } | |
542 | }; | |
543 | ||
544 | MetadataCreationResult::new(pointer_type_metadata(cx, t, pointee_metadata), | |
545 | false) | |
546 | } | |
547 | } | |
548 | } | |
9e0c209e | 549 | ty::TyFnDef(.., ref barefnty) | ty::TyFnPtr(ref barefnty) => { |
c1a9b12d SL |
550 | let fn_metadata = subroutine_type_metadata(cx, |
551 | unique_type_id, | |
552 | &barefnty.sig, | |
553 | usage_site_span).metadata; | |
554 | match debug_context(cx).type_map | |
555 | .borrow() | |
556 | .find_metadata_for_unique_id(unique_type_id) { | |
557 | Some(metadata) => return metadata, | |
558 | None => { /* proceed normally */ } | |
559 | }; | |
560 | ||
561 | // This is actually a function pointer, so wrap it in pointer DI | |
562 | MetadataCreationResult::new(pointer_type_metadata(cx, t, fn_metadata), false) | |
563 | ||
1a4d82fc | 564 | } |
476ff2be SL |
565 | ty::TyClosure(def_id, substs) => { |
566 | let upvar_tys : Vec<_> = substs.upvar_tys(def_id, cx.tcx()).collect(); | |
c1a9b12d SL |
567 | prepare_tuple_metadata(cx, |
568 | t, | |
476ff2be | 569 | &upvar_tys, |
c1a9b12d SL |
570 | unique_type_id, |
571 | usage_site_span).finalize(cx) | |
1a4d82fc | 572 | } |
9e0c209e SL |
573 | ty::TyAdt(def, ..) => match def.adt_kind() { |
574 | AdtKind::Struct => { | |
575 | prepare_struct_metadata(cx, | |
576 | t, | |
577 | unique_type_id, | |
578 | usage_site_span).finalize(cx) | |
579 | } | |
580 | AdtKind::Union => { | |
581 | prepare_union_metadata(cx, | |
1a4d82fc | 582 | t, |
1a4d82fc JJ |
583 | unique_type_id, |
584 | usage_site_span).finalize(cx) | |
9e0c209e SL |
585 | } |
586 | AdtKind::Enum => { | |
587 | prepare_enum_metadata(cx, | |
588 | t, | |
589 | def.did, | |
590 | unique_type_id, | |
591 | usage_site_span).finalize(cx) | |
592 | } | |
593 | }, | |
62682a34 | 594 | ty::TyTuple(ref elements) => { |
1a4d82fc JJ |
595 | prepare_tuple_metadata(cx, |
596 | t, | |
85aaf69f | 597 | &elements[..], |
1a4d82fc JJ |
598 | unique_type_id, |
599 | usage_site_span).finalize(cx) | |
600 | } | |
601 | _ => { | |
54a0048b | 602 | bug!("debuginfo: unexpected type in type_metadata: {:?}", sty) |
1a4d82fc JJ |
603 | } |
604 | }; | |
605 | ||
606 | { | |
607 | let mut type_map = debug_context(cx).type_map.borrow_mut(); | |
608 | ||
609 | if already_stored_in_typemap { | |
b039eaaf | 610 | // Also make sure that we already have a TypeMap entry for the unique type id. |
1a4d82fc JJ |
611 | let metadata_for_uid = match type_map.find_metadata_for_unique_id(unique_type_id) { |
612 | Some(metadata) => metadata, | |
613 | None => { | |
54a0048b SL |
614 | span_bug!(usage_site_span, |
615 | "Expected type metadata for unique \ | |
616 | type id '{}' to already be in \ | |
617 | the debuginfo::TypeMap but it \ | |
618 | was not. (Ty = {})", | |
476ff2be | 619 | type_map.get_unique_type_id_as_string(unique_type_id), |
54a0048b | 620 | t); |
1a4d82fc JJ |
621 | } |
622 | }; | |
623 | ||
624 | match type_map.find_metadata_for_type(t) { | |
625 | Some(metadata) => { | |
626 | if metadata != metadata_for_uid { | |
54a0048b SL |
627 | span_bug!(usage_site_span, |
628 | "Mismatch between Ty and \ | |
629 | UniqueTypeId maps in \ | |
630 | debuginfo::TypeMap. \ | |
631 | UniqueTypeId={}, Ty={}", | |
476ff2be | 632 | type_map.get_unique_type_id_as_string(unique_type_id), |
54a0048b | 633 | t); |
1a4d82fc JJ |
634 | } |
635 | } | |
636 | None => { | |
54a0048b | 637 | type_map.register_type_with_metadata(t, metadata); |
1a4d82fc JJ |
638 | } |
639 | } | |
640 | } else { | |
54a0048b SL |
641 | type_map.register_type_with_metadata(t, metadata); |
642 | type_map.register_unique_id_with_metadata(unique_type_id, metadata); | |
1a4d82fc JJ |
643 | } |
644 | } | |
645 | ||
646 | metadata | |
647 | } | |
648 | ||
3157f602 | 649 | pub fn file_metadata(cx: &CrateContext, path: &str, full_path: &Option<String>) -> DIFile { |
d9579d0f AL |
650 | // FIXME (#9639): This needs to handle non-utf8 paths |
651 | let work_dir = cx.sess().working_dir.to_str().unwrap(); | |
652 | let file_name = | |
3157f602 XL |
653 | full_path.as_ref().map(|p| p.as_str()).unwrap_or_else(|| { |
654 | if path.starts_with(work_dir) { | |
655 | &path[work_dir.len() + 1..path.len()] | |
656 | } else { | |
657 | path | |
658 | } | |
659 | }); | |
d9579d0f | 660 | |
3157f602 | 661 | file_metadata_(cx, path, file_name, &work_dir) |
e9174d1e SL |
662 | } |
663 | ||
664 | pub fn unknown_file_metadata(cx: &CrateContext) -> DIFile { | |
665 | // Regular filenames should not be empty, so we abuse an empty name as the | |
666 | // key for the special unknown file metadata | |
667 | file_metadata_(cx, "", "<unknown>", "") | |
668 | ||
669 | } | |
670 | ||
671 | fn file_metadata_(cx: &CrateContext, key: &str, file_name: &str, work_dir: &str) -> DIFile { | |
3157f602 XL |
672 | if let Some(file_metadata) = debug_context(cx).created_files.borrow().get(key) { |
673 | return *file_metadata; | |
e9174d1e SL |
674 | } |
675 | ||
676 | debug!("file_metadata: file_name: {}, work_dir: {}", file_name, work_dir); | |
677 | ||
d9579d0f AL |
678 | let file_name = CString::new(file_name).unwrap(); |
679 | let work_dir = CString::new(work_dir).unwrap(); | |
680 | let file_metadata = unsafe { | |
5bcae85e SL |
681 | llvm::LLVMRustDIBuilderCreateFile(DIB(cx), file_name.as_ptr(), |
682 | work_dir.as_ptr()) | |
d9579d0f AL |
683 | }; |
684 | ||
685 | let mut created_files = debug_context(cx).created_files.borrow_mut(); | |
e9174d1e SL |
686 | created_files.insert(key.to_string(), file_metadata); |
687 | file_metadata | |
d9579d0f AL |
688 | } |
689 | ||
d9579d0f AL |
690 | fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, |
691 | t: Ty<'tcx>) -> DIType { | |
692 | ||
693 | debug!("basic_type_metadata: {:?}", t); | |
694 | ||
695 | let (name, encoding) = match t.sty { | |
5bcae85e | 696 | ty::TyNever => ("!", DW_ATE_unsigned), |
62682a34 | 697 | ty::TyTuple(ref elements) if elements.is_empty() => |
92a42be0 SL |
698 | ("()", DW_ATE_unsigned), |
699 | ty::TyBool => ("bool", DW_ATE_boolean), | |
700 | ty::TyChar => ("char", DW_ATE_unsigned_char), | |
701 | ty::TyInt(int_ty) => { | |
9cc50fc6 | 702 | (int_ty.ty_to_string(), DW_ATE_signed) |
d9579d0f | 703 | }, |
92a42be0 | 704 | ty::TyUint(uint_ty) => { |
9cc50fc6 | 705 | (uint_ty.ty_to_string(), DW_ATE_unsigned) |
d9579d0f | 706 | }, |
92a42be0 | 707 | ty::TyFloat(float_ty) => { |
9cc50fc6 | 708 | (float_ty.ty_to_string(), DW_ATE_float) |
d9579d0f | 709 | }, |
54a0048b | 710 | _ => bug!("debuginfo::basic_type_metadata - t is invalid type") |
d9579d0f AL |
711 | }; |
712 | ||
713 | let llvm_type = type_of::type_of(cx, t); | |
714 | let (size, align) = size_and_align_of(cx, llvm_type); | |
715 | let name = CString::new(name).unwrap(); | |
716 | let ty_metadata = unsafe { | |
5bcae85e | 717 | llvm::LLVMRustDIBuilderCreateBasicType( |
d9579d0f AL |
718 | DIB(cx), |
719 | name.as_ptr(), | |
720 | bytes_to_bits(size), | |
721 | bytes_to_bits(align), | |
722 | encoding) | |
723 | }; | |
724 | ||
725 | return ty_metadata; | |
726 | } | |
727 | ||
728 | fn pointer_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, | |
729 | pointer_type: Ty<'tcx>, | |
730 | pointee_type_metadata: DIType) | |
731 | -> DIType { | |
732 | let pointer_llvm_type = type_of::type_of(cx, pointer_type); | |
733 | let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type); | |
734 | let name = compute_debuginfo_type_name(cx, pointer_type, false); | |
735 | let name = CString::new(name).unwrap(); | |
736 | let ptr_metadata = unsafe { | |
5bcae85e | 737 | llvm::LLVMRustDIBuilderCreatePointerType( |
d9579d0f AL |
738 | DIB(cx), |
739 | pointee_type_metadata, | |
740 | bytes_to_bits(pointer_size), | |
741 | bytes_to_bits(pointer_align), | |
742 | name.as_ptr()) | |
743 | }; | |
744 | return ptr_metadata; | |
745 | } | |
746 | ||
5bcae85e SL |
747 | pub fn compile_unit_metadata(scc: &SharedCrateContext, |
748 | debug_context: &CrateDebugContext, | |
749 | sess: &Session) | |
750 | -> DIDescriptor { | |
751 | let work_dir = &sess.working_dir; | |
752 | let compile_unit_name = match sess.local_crate_source_file { | |
753 | None => fallback_path(scc), | |
d9579d0f AL |
754 | Some(ref abs_path) => { |
755 | if abs_path.is_relative() { | |
5bcae85e SL |
756 | sess.warn("debuginfo: Invalid path to crate's local root source file!"); |
757 | fallback_path(scc) | |
d9579d0f | 758 | } else { |
9cc50fc6 SL |
759 | match abs_path.strip_prefix(work_dir) { |
760 | Ok(ref p) if p.is_relative() => { | |
d9579d0f AL |
761 | if p.starts_with(Path::new("./")) { |
762 | path2cstr(p) | |
763 | } else { | |
764 | path2cstr(&Path::new(".").join(p)) | |
765 | } | |
766 | } | |
5bcae85e | 767 | _ => fallback_path(scc) |
d9579d0f AL |
768 | } |
769 | } | |
770 | } | |
771 | }; | |
772 | ||
773 | debug!("compile_unit_metadata: {:?}", compile_unit_name); | |
774 | let producer = format!("rustc version {}", | |
775 | (option_env!("CFG_VERSION")).expect("CFG_VERSION")); | |
776 | ||
777 | let compile_unit_name = compile_unit_name.as_ptr(); | |
778 | let work_dir = path2cstr(&work_dir); | |
779 | let producer = CString::new(producer).unwrap(); | |
780 | let flags = "\0"; | |
781 | let split_name = "\0"; | |
782 | return unsafe { | |
5bcae85e SL |
783 | llvm::LLVMRustDIBuilderCreateCompileUnit( |
784 | debug_context.builder, | |
d9579d0f AL |
785 | DW_LANG_RUST, |
786 | compile_unit_name, | |
787 | work_dir.as_ptr(), | |
788 | producer.as_ptr(), | |
5bcae85e | 789 | sess.opts.optimize != config::OptLevel::No, |
d9579d0f AL |
790 | flags.as_ptr() as *const _, |
791 | 0, | |
792 | split_name.as_ptr() as *const _) | |
793 | }; | |
794 | ||
5bcae85e | 795 | fn fallback_path(scc: &SharedCrateContext) -> CString { |
476ff2be | 796 | CString::new(scc.link_meta().crate_name.to_string()).unwrap() |
d9579d0f AL |
797 | } |
798 | } | |
799 | ||
1a4d82fc JJ |
800 | struct MetadataCreationResult { |
801 | metadata: DIType, | |
802 | already_stored_in_typemap: bool | |
803 | } | |
804 | ||
805 | impl MetadataCreationResult { | |
806 | fn new(metadata: DIType, already_stored_in_typemap: bool) -> MetadataCreationResult { | |
807 | MetadataCreationResult { | |
808 | metadata: metadata, | |
809 | already_stored_in_typemap: already_stored_in_typemap | |
810 | } | |
811 | } | |
812 | } | |
813 | ||
d9579d0f AL |
814 | #[derive(Debug)] |
815 | enum MemberOffset { | |
816 | FixedMemberOffset { bytes: usize }, | |
817 | // For ComputedMemberOffset, the offset is read from the llvm type definition. | |
818 | ComputedMemberOffset | |
819 | } | |
820 | ||
821 | // Description of a type member, which can either be a regular field (as in | |
822 | // structs or tuples) or an enum variant. | |
823 | #[derive(Debug)] | |
824 | struct MemberDescription { | |
825 | name: String, | |
826 | llvm_type: Type, | |
827 | type_metadata: DIType, | |
828 | offset: MemberOffset, | |
476ff2be | 829 | flags: DIFlags, |
d9579d0f AL |
830 | } |
831 | ||
832 | // A factory for MemberDescriptions. It produces a list of member descriptions | |
833 | // for some record-like type. MemberDescriptionFactories are used to defer the | |
834 | // creation of type member descriptions in order to break cycles arising from | |
835 | // recursive type definitions. | |
836 | enum MemberDescriptionFactory<'tcx> { | |
837 | StructMDF(StructMemberDescriptionFactory<'tcx>), | |
838 | TupleMDF(TupleMemberDescriptionFactory<'tcx>), | |
839 | EnumMDF(EnumMemberDescriptionFactory<'tcx>), | |
9e0c209e | 840 | UnionMDF(UnionMemberDescriptionFactory<'tcx>), |
d9579d0f AL |
841 | VariantMDF(VariantMemberDescriptionFactory<'tcx>) |
842 | } | |
843 | ||
844 | impl<'tcx> MemberDescriptionFactory<'tcx> { | |
845 | fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>) | |
846 | -> Vec<MemberDescription> { | |
847 | match *self { | |
848 | StructMDF(ref this) => { | |
849 | this.create_member_descriptions(cx) | |
850 | } | |
851 | TupleMDF(ref this) => { | |
852 | this.create_member_descriptions(cx) | |
853 | } | |
854 | EnumMDF(ref this) => { | |
855 | this.create_member_descriptions(cx) | |
856 | } | |
9e0c209e SL |
857 | UnionMDF(ref this) => { |
858 | this.create_member_descriptions(cx) | |
859 | } | |
d9579d0f AL |
860 | VariantMDF(ref this) => { |
861 | this.create_member_descriptions(cx) | |
862 | } | |
863 | } | |
864 | } | |
865 | } | |
866 | ||
867 | //=----------------------------------------------------------------------------- | |
868 | // Structs | |
869 | //=----------------------------------------------------------------------------- | |
870 | ||
871 | // Creates MemberDescriptions for the fields of a struct | |
872 | struct StructMemberDescriptionFactory<'tcx> { | |
476ff2be SL |
873 | ty: Ty<'tcx>, |
874 | variant: &'tcx ty::VariantDef, | |
9e0c209e | 875 | substs: &'tcx Substs<'tcx>, |
d9579d0f AL |
876 | span: Span, |
877 | } | |
878 | ||
879 | impl<'tcx> StructMemberDescriptionFactory<'tcx> { | |
880 | fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>) | |
881 | -> Vec<MemberDescription> { | |
476ff2be SL |
882 | let layout = cx.layout_of(self.ty); |
883 | ||
884 | let tmp; | |
885 | let offsets = match *layout { | |
886 | layout::Univariant { ref variant, .. } => &variant.offsets, | |
887 | layout::Vector { element, count } => { | |
888 | let element_size = element.size(&cx.tcx().data_layout).bytes(); | |
889 | tmp = (0..count). | |
890 | map(|i| layout::Size::from_bytes(i*element_size)) | |
891 | .collect::<Vec<layout::Size>>(); | |
892 | &tmp | |
893 | } | |
894 | _ => bug!("{} is not a struct", self.ty) | |
d9579d0f AL |
895 | }; |
896 | ||
e9174d1e | 897 | self.variant.fields.iter().enumerate().map(|(i, f)| { |
c30ab7b3 | 898 | let name = if self.variant.ctor_kind == CtorKind::Fn { |
d9579d0f AL |
899 | format!("__{}", i) |
900 | } else { | |
e9174d1e | 901 | f.name.to_string() |
d9579d0f | 902 | }; |
e9174d1e | 903 | let fty = monomorphize::field_ty(cx.tcx(), self.substs, f); |
1a4d82fc | 904 | |
476ff2be | 905 | let offset = FixedMemberOffset { bytes: offsets[i].bytes() as usize}; |
d9579d0f AL |
906 | |
907 | MemberDescription { | |
908 | name: name, | |
e9174d1e SL |
909 | llvm_type: type_of::type_of(cx, fty), |
910 | type_metadata: type_metadata(cx, fty, self.span), | |
d9579d0f | 911 | offset: offset, |
476ff2be | 912 | flags: DIFlags::FlagZero, |
d9579d0f AL |
913 | } |
914 | }).collect() | |
1a4d82fc JJ |
915 | } |
916 | } | |
917 | ||
1a4d82fc | 918 | |
d9579d0f AL |
919 | fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, |
920 | struct_type: Ty<'tcx>, | |
d9579d0f AL |
921 | unique_type_id: UniqueTypeId, |
922 | span: Span) | |
923 | -> RecursiveTypeDescription<'tcx> { | |
924 | let struct_name = compute_debuginfo_type_name(cx, struct_type, false); | |
925 | let struct_llvm_type = type_of::in_memory_type_of(cx, struct_type); | |
926 | ||
a7813a04 | 927 | let (struct_def_id, variant, substs) = match struct_type.sty { |
9e0c209e SL |
928 | ty::TyAdt(def, substs) => (def.did, def.struct_variant(), substs), |
929 | _ => bug!("prepare_struct_metadata on a non-ADT") | |
e9174d1e SL |
930 | }; |
931 | ||
a7813a04 | 932 | let (containing_scope, _) = get_namespace_and_span_for_item(cx, struct_def_id); |
1a4d82fc | 933 | |
d9579d0f AL |
934 | let struct_metadata_stub = create_struct_stub(cx, |
935 | struct_llvm_type, | |
936 | &struct_name, | |
937 | unique_type_id, | |
938 | containing_scope); | |
85aaf69f | 939 | |
d9579d0f AL |
940 | create_and_register_recursive_type_forward_declaration( |
941 | cx, | |
942 | struct_type, | |
943 | unique_type_id, | |
944 | struct_metadata_stub, | |
945 | struct_llvm_type, | |
946 | StructMDF(StructMemberDescriptionFactory { | |
476ff2be | 947 | ty: struct_type, |
e9174d1e SL |
948 | variant: variant, |
949 | substs: substs, | |
d9579d0f AL |
950 | span: span, |
951 | }) | |
952 | ) | |
1a4d82fc JJ |
953 | } |
954 | ||
955 | //=----------------------------------------------------------------------------- | |
d9579d0f | 956 | // Tuples |
1a4d82fc JJ |
957 | //=----------------------------------------------------------------------------- |
958 | ||
d9579d0f AL |
959 | // Creates MemberDescriptions for the fields of a tuple |
960 | struct TupleMemberDescriptionFactory<'tcx> { | |
476ff2be | 961 | ty: Ty<'tcx>, |
d9579d0f AL |
962 | component_types: Vec<Ty<'tcx>>, |
963 | span: Span, | |
1a4d82fc JJ |
964 | } |
965 | ||
d9579d0f AL |
966 | impl<'tcx> TupleMemberDescriptionFactory<'tcx> { |
967 | fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>) | |
968 | -> Vec<MemberDescription> { | |
476ff2be SL |
969 | let layout = cx.layout_of(self.ty); |
970 | let offsets = if let layout::Univariant { ref variant, .. } = *layout { | |
971 | &variant.offsets | |
972 | } else { | |
973 | bug!("{} is not a tuple", self.ty); | |
974 | }; | |
975 | ||
d9579d0f AL |
976 | self.component_types |
977 | .iter() | |
978 | .enumerate() | |
979 | .map(|(i, &component_type)| { | |
980 | MemberDescription { | |
981 | name: format!("__{}", i), | |
982 | llvm_type: type_of::type_of(cx, component_type), | |
983 | type_metadata: type_metadata(cx, component_type, self.span), | |
476ff2be SL |
984 | offset: FixedMemberOffset { bytes: offsets[i].bytes() as usize }, |
985 | flags: DIFlags::FlagZero, | |
d9579d0f AL |
986 | } |
987 | }).collect() | |
988 | } | |
1a4d82fc JJ |
989 | } |
990 | ||
d9579d0f AL |
991 | fn prepare_tuple_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, |
992 | tuple_type: Ty<'tcx>, | |
993 | component_types: &[Ty<'tcx>], | |
994 | unique_type_id: UniqueTypeId, | |
995 | span: Span) | |
996 | -> RecursiveTypeDescription<'tcx> { | |
997 | let tuple_name = compute_debuginfo_type_name(cx, tuple_type, false); | |
998 | let tuple_llvm_type = type_of::type_of(cx, tuple_type); | |
1a4d82fc | 999 | |
d9579d0f AL |
1000 | create_and_register_recursive_type_forward_declaration( |
1001 | cx, | |
1002 | tuple_type, | |
1003 | unique_type_id, | |
1004 | create_struct_stub(cx, | |
1005 | tuple_llvm_type, | |
1006 | &tuple_name[..], | |
1007 | unique_type_id, | |
e9174d1e | 1008 | NO_SCOPE_METADATA), |
d9579d0f AL |
1009 | tuple_llvm_type, |
1010 | TupleMDF(TupleMemberDescriptionFactory { | |
476ff2be | 1011 | ty: tuple_type, |
d9579d0f AL |
1012 | component_types: component_types.to_vec(), |
1013 | span: span, | |
1014 | }) | |
1015 | ) | |
1a4d82fc JJ |
1016 | } |
1017 | ||
9e0c209e SL |
1018 | //=----------------------------------------------------------------------------- |
1019 | // Unions | |
1020 | //=----------------------------------------------------------------------------- | |
1021 | ||
1022 | struct UnionMemberDescriptionFactory<'tcx> { | |
476ff2be | 1023 | variant: &'tcx ty::VariantDef, |
9e0c209e SL |
1024 | substs: &'tcx Substs<'tcx>, |
1025 | span: Span, | |
1026 | } | |
1027 | ||
1028 | impl<'tcx> UnionMemberDescriptionFactory<'tcx> { | |
1029 | fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>) | |
1030 | -> Vec<MemberDescription> { | |
1031 | self.variant.fields.iter().map(|field| { | |
1032 | let fty = monomorphize::field_ty(cx.tcx(), self.substs, field); | |
1033 | MemberDescription { | |
1034 | name: field.name.to_string(), | |
1035 | llvm_type: type_of::type_of(cx, fty), | |
1036 | type_metadata: type_metadata(cx, fty, self.span), | |
1037 | offset: FixedMemberOffset { bytes: 0 }, | |
476ff2be | 1038 | flags: DIFlags::FlagZero, |
9e0c209e SL |
1039 | } |
1040 | }).collect() | |
1041 | } | |
1042 | } | |
1043 | ||
1044 | fn prepare_union_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, | |
1045 | union_type: Ty<'tcx>, | |
1046 | unique_type_id: UniqueTypeId, | |
1047 | span: Span) | |
1048 | -> RecursiveTypeDescription<'tcx> { | |
1049 | let union_name = compute_debuginfo_type_name(cx, union_type, false); | |
1050 | let union_llvm_type = type_of::in_memory_type_of(cx, union_type); | |
1051 | ||
1052 | let (union_def_id, variant, substs) = match union_type.sty { | |
1053 | ty::TyAdt(def, substs) => (def.did, def.struct_variant(), substs), | |
1054 | _ => bug!("prepare_union_metadata on a non-ADT") | |
1055 | }; | |
1056 | ||
1057 | let (containing_scope, _) = get_namespace_and_span_for_item(cx, union_def_id); | |
1058 | ||
1059 | let union_metadata_stub = create_union_stub(cx, | |
1060 | union_llvm_type, | |
1061 | &union_name, | |
1062 | unique_type_id, | |
1063 | containing_scope); | |
1064 | ||
1065 | create_and_register_recursive_type_forward_declaration( | |
1066 | cx, | |
1067 | union_type, | |
1068 | unique_type_id, | |
1069 | union_metadata_stub, | |
1070 | union_llvm_type, | |
1071 | UnionMDF(UnionMemberDescriptionFactory { | |
1072 | variant: variant, | |
1073 | substs: substs, | |
1074 | span: span, | |
1075 | }) | |
1076 | ) | |
1077 | } | |
1a4d82fc | 1078 | |
d9579d0f AL |
1079 | //=----------------------------------------------------------------------------- |
1080 | // Enums | |
1081 | //=----------------------------------------------------------------------------- | |
1a4d82fc | 1082 | |
d9579d0f AL |
1083 | // Describes the members of an enum value: An enum is described as a union of |
1084 | // structs in DWARF. This MemberDescriptionFactory provides the description for | |
1085 | // the members of this union; so for every variant of the given enum, this | |
1086 | // factory will produce one MemberDescription (all with no name and a fixed | |
1087 | // offset of zero bytes). | |
1088 | struct EnumMemberDescriptionFactory<'tcx> { | |
1089 | enum_type: Ty<'tcx>, | |
9e0c209e | 1090 | type_rep: &'tcx layout::Layout, |
d9579d0f AL |
1091 | discriminant_type_metadata: Option<DIType>, |
1092 | containing_scope: DIScope, | |
1093 | file_metadata: DIFile, | |
1094 | span: Span, | |
1a4d82fc JJ |
1095 | } |
1096 | ||
d9579d0f AL |
1097 | impl<'tcx> EnumMemberDescriptionFactory<'tcx> { |
1098 | fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>) | |
1099 | -> Vec<MemberDescription> { | |
e9174d1e | 1100 | let adt = &self.enum_type.ty_adt_def().unwrap(); |
9e0c209e SL |
1101 | let substs = match self.enum_type.sty { |
1102 | ty::TyAdt(def, ref s) if def.adt_kind() == AdtKind::Enum => s, | |
1103 | _ => bug!("{} is not an enum", self.enum_type) | |
1104 | }; | |
d9579d0f | 1105 | match *self.type_rep { |
9e0c209e | 1106 | layout::General { ref variants, .. } => { |
d9579d0f AL |
1107 | let discriminant_info = RegularDiscriminant(self.discriminant_type_metadata |
1108 | .expect("")); | |
9e0c209e | 1109 | variants |
d9579d0f AL |
1110 | .iter() |
1111 | .enumerate() | |
1112 | .map(|(i, struct_def)| { | |
1113 | let (variant_type_metadata, | |
1114 | variant_llvm_type, | |
1115 | member_desc_factory) = | |
1116 | describe_enum_variant(cx, | |
1117 | self.enum_type, | |
1118 | struct_def, | |
e9174d1e | 1119 | &adt.variants[i], |
d9579d0f AL |
1120 | discriminant_info, |
1121 | self.containing_scope, | |
1122 | self.span); | |
1a4d82fc | 1123 | |
d9579d0f AL |
1124 | let member_descriptions = member_desc_factory |
1125 | .create_member_descriptions(cx); | |
1a4d82fc | 1126 | |
d9579d0f AL |
1127 | set_members_of_composite_type(cx, |
1128 | variant_type_metadata, | |
1129 | variant_llvm_type, | |
1130 | &member_descriptions); | |
1131 | MemberDescription { | |
1132 | name: "".to_string(), | |
1133 | llvm_type: variant_llvm_type, | |
1134 | type_metadata: variant_type_metadata, | |
1135 | offset: FixedMemberOffset { bytes: 0 }, | |
476ff2be | 1136 | flags: DIFlags::FlagZero |
d9579d0f AL |
1137 | } |
1138 | }).collect() | |
1139 | }, | |
9e0c209e | 1140 | layout::Univariant{ ref variant, .. } => { |
e9174d1e | 1141 | assert!(adt.variants.len() <= 1); |
1a4d82fc | 1142 | |
e9174d1e | 1143 | if adt.variants.is_empty() { |
d9579d0f AL |
1144 | vec![] |
1145 | } else { | |
1146 | let (variant_type_metadata, | |
1147 | variant_llvm_type, | |
1148 | member_description_factory) = | |
1149 | describe_enum_variant(cx, | |
1150 | self.enum_type, | |
9e0c209e | 1151 | variant, |
e9174d1e | 1152 | &adt.variants[0], |
d9579d0f AL |
1153 | NoDiscriminant, |
1154 | self.containing_scope, | |
1155 | self.span); | |
1a4d82fc | 1156 | |
d9579d0f AL |
1157 | let member_descriptions = |
1158 | member_description_factory.create_member_descriptions(cx); | |
1a4d82fc | 1159 | |
d9579d0f AL |
1160 | set_members_of_composite_type(cx, |
1161 | variant_type_metadata, | |
1162 | variant_llvm_type, | |
1163 | &member_descriptions[..]); | |
1164 | vec![ | |
1165 | MemberDescription { | |
1166 | name: "".to_string(), | |
1167 | llvm_type: variant_llvm_type, | |
1168 | type_metadata: variant_type_metadata, | |
1169 | offset: FixedMemberOffset { bytes: 0 }, | |
476ff2be | 1170 | flags: DIFlags::FlagZero |
d9579d0f AL |
1171 | } |
1172 | ] | |
1173 | } | |
1174 | } | |
9e0c209e | 1175 | layout::RawNullablePointer { nndiscr: non_null_variant_index, .. } => { |
d9579d0f AL |
1176 | // As far as debuginfo is concerned, the pointer this enum |
1177 | // represents is still wrapped in a struct. This is to make the | |
1178 | // DWARF representation of enums uniform. | |
1a4d82fc | 1179 | |
d9579d0f | 1180 | // First create a description of the artificial wrapper struct: |
9e0c209e | 1181 | let non_null_variant = &adt.variants[non_null_variant_index as usize]; |
c1a9b12d | 1182 | let non_null_variant_name = non_null_variant.name.as_str(); |
1a4d82fc | 1183 | |
d9579d0f | 1184 | // The llvm type and metadata of the pointer |
9e0c209e | 1185 | let nnty = monomorphize::field_ty(cx.tcx(), &substs, &non_null_variant.fields[0] ); |
d9579d0f AL |
1186 | let non_null_llvm_type = type_of::type_of(cx, nnty); |
1187 | let non_null_type_metadata = type_metadata(cx, nnty, self.span); | |
1a4d82fc | 1188 | |
d9579d0f AL |
1189 | // The type of the artificial struct wrapping the pointer |
1190 | let artificial_struct_llvm_type = Type::struct_(cx, | |
1191 | &[non_null_llvm_type], | |
1192 | false); | |
1a4d82fc | 1193 | |
d9579d0f AL |
1194 | // For the metadata of the wrapper struct, we need to create a |
1195 | // MemberDescription of the struct's single field. | |
1196 | let sole_struct_member_description = MemberDescription { | |
c30ab7b3 SL |
1197 | name: match non_null_variant.ctor_kind { |
1198 | CtorKind::Fn => "__0".to_string(), | |
1199 | CtorKind::Fictive => { | |
e9174d1e SL |
1200 | non_null_variant.fields[0].name.to_string() |
1201 | } | |
c30ab7b3 | 1202 | CtorKind::Const => bug!() |
d9579d0f AL |
1203 | }, |
1204 | llvm_type: non_null_llvm_type, | |
1205 | type_metadata: non_null_type_metadata, | |
1206 | offset: FixedMemberOffset { bytes: 0 }, | |
476ff2be | 1207 | flags: DIFlags::FlagZero |
d9579d0f | 1208 | }; |
1a4d82fc | 1209 | |
d9579d0f AL |
1210 | let unique_type_id = debug_context(cx).type_map |
1211 | .borrow_mut() | |
1212 | .get_unique_type_id_of_enum_variant( | |
1213 | cx, | |
1214 | self.enum_type, | |
1215 | &non_null_variant_name); | |
1a4d82fc | 1216 | |
d9579d0f AL |
1217 | // Now we can create the metadata of the artificial struct |
1218 | let artificial_struct_metadata = | |
1219 | composite_type_metadata(cx, | |
1220 | artificial_struct_llvm_type, | |
1221 | &non_null_variant_name, | |
1222 | unique_type_id, | |
1223 | &[sole_struct_member_description], | |
1224 | self.containing_scope, | |
1225 | self.file_metadata, | |
3157f602 | 1226 | syntax_pos::DUMMY_SP); |
1a4d82fc | 1227 | |
d9579d0f AL |
1228 | // Encode the information about the null variant in the union |
1229 | // member's name. | |
9e0c209e | 1230 | let null_variant_index = (1 - non_null_variant_index) as usize; |
e9174d1e | 1231 | let null_variant_name = adt.variants[null_variant_index].name; |
d9579d0f AL |
1232 | let union_member_name = format!("RUST$ENCODED$ENUM${}${}", |
1233 | 0, | |
1234 | null_variant_name); | |
1a4d82fc | 1235 | |
d9579d0f AL |
1236 | // Finally create the (singleton) list of descriptions of union |
1237 | // members. | |
1238 | vec![ | |
1239 | MemberDescription { | |
1240 | name: union_member_name, | |
1241 | llvm_type: artificial_struct_llvm_type, | |
1242 | type_metadata: artificial_struct_metadata, | |
1243 | offset: FixedMemberOffset { bytes: 0 }, | |
476ff2be | 1244 | flags: DIFlags::FlagZero |
d9579d0f AL |
1245 | } |
1246 | ] | |
1247 | }, | |
9e0c209e | 1248 | layout::StructWrappedNullablePointer { nonnull: ref struct_def, |
d9579d0f | 1249 | nndiscr, |
476ff2be | 1250 | ref discrfield_source, ..} => { |
d9579d0f AL |
1251 | // Create a description of the non-null variant |
1252 | let (variant_type_metadata, variant_llvm_type, member_description_factory) = | |
1253 | describe_enum_variant(cx, | |
1254 | self.enum_type, | |
1255 | struct_def, | |
9e0c209e | 1256 | &adt.variants[nndiscr as usize], |
d9579d0f AL |
1257 | OptimizedDiscriminant, |
1258 | self.containing_scope, | |
1259 | self.span); | |
1a4d82fc | 1260 | |
d9579d0f AL |
1261 | let variant_member_descriptions = |
1262 | member_description_factory.create_member_descriptions(cx); | |
1a4d82fc | 1263 | |
d9579d0f AL |
1264 | set_members_of_composite_type(cx, |
1265 | variant_type_metadata, | |
1266 | variant_llvm_type, | |
1267 | &variant_member_descriptions[..]); | |
1a4d82fc | 1268 | |
d9579d0f AL |
1269 | // Encode the information about the null variant in the union |
1270 | // member's name. | |
9e0c209e | 1271 | let null_variant_index = (1 - nndiscr) as usize; |
e9174d1e | 1272 | let null_variant_name = adt.variants[null_variant_index].name; |
476ff2be | 1273 | let discrfield_source = discrfield_source.iter() |
d9579d0f AL |
1274 | .skip(1) |
1275 | .map(|x| x.to_string()) | |
c1a9b12d | 1276 | .collect::<Vec<_>>().join("$"); |
d9579d0f | 1277 | let union_member_name = format!("RUST$ENCODED$ENUM${}${}", |
476ff2be | 1278 | discrfield_source, |
d9579d0f | 1279 | null_variant_name); |
1a4d82fc | 1280 | |
d9579d0f AL |
1281 | // Create the (singleton) list of descriptions of union members. |
1282 | vec![ | |
1283 | MemberDescription { | |
1284 | name: union_member_name, | |
1285 | llvm_type: variant_llvm_type, | |
1286 | type_metadata: variant_type_metadata, | |
1287 | offset: FixedMemberOffset { bytes: 0 }, | |
476ff2be | 1288 | flags: DIFlags::FlagZero |
d9579d0f AL |
1289 | } |
1290 | ] | |
1291 | }, | |
9e0c209e SL |
1292 | layout::CEnum { .. } => span_bug!(self.span, "This should be unreachable."), |
1293 | ref l @ _ => bug!("Not an enum layout: {:#?}", l) | |
1a4d82fc JJ |
1294 | } |
1295 | } | |
d9579d0f | 1296 | } |
1a4d82fc | 1297 | |
d9579d0f AL |
1298 | // Creates MemberDescriptions for the fields of a single enum variant. |
1299 | struct VariantMemberDescriptionFactory<'tcx> { | |
476ff2be SL |
1300 | // Cloned from the layout::Struct describing the variant. |
1301 | offsets: &'tcx [layout::Size], | |
d9579d0f AL |
1302 | args: Vec<(String, Ty<'tcx>)>, |
1303 | discriminant_type_metadata: Option<DIType>, | |
1304 | span: Span, | |
1305 | } | |
1a4d82fc | 1306 | |
d9579d0f AL |
1307 | impl<'tcx> VariantMemberDescriptionFactory<'tcx> { |
1308 | fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>) | |
1309 | -> Vec<MemberDescription> { | |
1310 | self.args.iter().enumerate().map(|(i, &(ref name, ty))| { | |
1311 | MemberDescription { | |
1312 | name: name.to_string(), | |
1313 | llvm_type: type_of::type_of(cx, ty), | |
1314 | type_metadata: match self.discriminant_type_metadata { | |
1315 | Some(metadata) if i == 0 => metadata, | |
1316 | _ => type_metadata(cx, ty, self.span) | |
1317 | }, | |
476ff2be SL |
1318 | offset: FixedMemberOffset { bytes: self.offsets[i].bytes() as usize }, |
1319 | flags: DIFlags::FlagZero | |
1a4d82fc | 1320 | } |
d9579d0f | 1321 | }).collect() |
1a4d82fc | 1322 | } |
d9579d0f | 1323 | } |
1a4d82fc | 1324 | |
d9579d0f AL |
1325 | #[derive(Copy, Clone)] |
1326 | enum EnumDiscriminantInfo { | |
1327 | RegularDiscriminant(DIType), | |
1328 | OptimizedDiscriminant, | |
1329 | NoDiscriminant | |
1330 | } | |
1a4d82fc | 1331 | |
d9579d0f AL |
1332 | // Returns a tuple of (1) type_metadata_stub of the variant, (2) the llvm_type |
1333 | // of the variant, and (3) a MemberDescriptionFactory for producing the | |
1334 | // descriptions of the fields of the variant. This is a rudimentary version of a | |
1335 | // full RecursiveTypeDescription. | |
1336 | fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, | |
1337 | enum_type: Ty<'tcx>, | |
476ff2be SL |
1338 | struct_def: &'tcx layout::Struct, |
1339 | variant: &'tcx ty::VariantDef, | |
d9579d0f AL |
1340 | discriminant_info: EnumDiscriminantInfo, |
1341 | containing_scope: DIScope, | |
1342 | span: Span) | |
1343 | -> (DICompositeType, Type, MemberDescriptionFactory<'tcx>) { | |
9e0c209e SL |
1344 | let substs = match enum_type.sty { |
1345 | ty::TyAdt(def, s) if def.adt_kind() == AdtKind::Enum => s, | |
1346 | ref t @ _ => bug!("{:#?} is not an enum", t) | |
1347 | }; | |
1348 | ||
1349 | let maybe_discr_and_signed: Option<(layout::Integer, bool)> = match *cx.layout_of(enum_type) { | |
1350 | layout::CEnum {discr, ..} => Some((discr, true)), | |
1351 | layout::General{discr, ..} => Some((discr, false)), | |
1352 | layout::Univariant { .. } | |
1353 | | layout::RawNullablePointer { .. } | |
1354 | | layout::StructWrappedNullablePointer { .. } => None, | |
1355 | ref l @ _ => bug!("This should be unreachable. Type is {:#?} layout is {:#?}", enum_type, l) | |
1356 | }; | |
1357 | ||
476ff2be | 1358 | let mut field_tys = variant.fields.iter().map(|f| { |
9e0c209e SL |
1359 | monomorphize::field_ty(cx.tcx(), &substs, f) |
1360 | }).collect::<Vec<_>>(); | |
1361 | ||
1362 | if let Some((discr, signed)) = maybe_discr_and_signed { | |
1363 | field_tys.insert(0, discr.to_ty(&cx.tcx(), signed)); | |
1364 | } | |
1365 | ||
1366 | ||
d9579d0f | 1367 | let variant_llvm_type = |
9e0c209e | 1368 | Type::struct_(cx, &field_tys |
d9579d0f | 1369 | .iter() |
9e0c209e | 1370 | .map(|t| type_of::type_of(cx, t)) |
d9579d0f AL |
1371 | .collect::<Vec<_>>() |
1372 | , | |
1373 | struct_def.packed); | |
1374 | // Could do some consistency checks here: size, align, field count, discr type | |
1a4d82fc | 1375 | |
e9174d1e | 1376 | let variant_name = variant.name.as_str(); |
d9579d0f AL |
1377 | let unique_type_id = debug_context(cx).type_map |
1378 | .borrow_mut() | |
1379 | .get_unique_type_id_of_enum_variant( | |
1380 | cx, | |
1381 | enum_type, | |
c1a9b12d | 1382 | &variant_name); |
1a4d82fc | 1383 | |
d9579d0f AL |
1384 | let metadata_stub = create_struct_stub(cx, |
1385 | variant_llvm_type, | |
c1a9b12d | 1386 | &variant_name, |
d9579d0f AL |
1387 | unique_type_id, |
1388 | containing_scope); | |
1a4d82fc | 1389 | |
d9579d0f | 1390 | // Get the argument names from the enum variant info |
c30ab7b3 SL |
1391 | let mut arg_names: Vec<_> = match variant.ctor_kind { |
1392 | CtorKind::Const => vec![], | |
1393 | CtorKind::Fn => { | |
e9174d1e SL |
1394 | variant.fields |
1395 | .iter() | |
1396 | .enumerate() | |
1397 | .map(|(i, _)| format!("__{}", i)) | |
1398 | .collect() | |
d9579d0f | 1399 | } |
c30ab7b3 | 1400 | CtorKind::Fictive => { |
e9174d1e SL |
1401 | variant.fields |
1402 | .iter() | |
1403 | .map(|f| f.name.to_string()) | |
1404 | .collect() | |
d9579d0f AL |
1405 | } |
1406 | }; | |
1a4d82fc | 1407 | |
d9579d0f AL |
1408 | // If this is not a univariant enum, there is also the discriminant field. |
1409 | match discriminant_info { | |
1410 | RegularDiscriminant(_) => arg_names.insert(0, "RUST$ENUM$DISR".to_string()), | |
1411 | _ => { /* do nothing */ } | |
1412 | }; | |
1a4d82fc | 1413 | |
d9579d0f AL |
1414 | // Build an array of (field name, field type) pairs to be captured in the factory closure. |
1415 | let args: Vec<(String, Ty)> = arg_names.iter() | |
9e0c209e | 1416 | .zip(field_tys.iter()) |
d9579d0f AL |
1417 | .map(|(s, &t)| (s.to_string(), t)) |
1418 | .collect(); | |
1a4d82fc | 1419 | |
d9579d0f AL |
1420 | let member_description_factory = |
1421 | VariantMDF(VariantMemberDescriptionFactory { | |
476ff2be | 1422 | offsets: &struct_def.offsets[..], |
d9579d0f AL |
1423 | args: args, |
1424 | discriminant_type_metadata: match discriminant_info { | |
1425 | RegularDiscriminant(discriminant_type_metadata) => { | |
1426 | Some(discriminant_type_metadata) | |
1a4d82fc | 1427 | } |
d9579d0f AL |
1428 | _ => None |
1429 | }, | |
1430 | span: span, | |
1431 | }); | |
1a4d82fc | 1432 | |
d9579d0f AL |
1433 | (metadata_stub, variant_llvm_type, member_description_factory) |
1434 | } | |
1a4d82fc | 1435 | |
d9579d0f AL |
1436 | fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, |
1437 | enum_type: Ty<'tcx>, | |
e9174d1e | 1438 | enum_def_id: DefId, |
d9579d0f AL |
1439 | unique_type_id: UniqueTypeId, |
1440 | span: Span) | |
1441 | -> RecursiveTypeDescription<'tcx> { | |
1442 | let enum_name = compute_debuginfo_type_name(cx, enum_type, false); | |
1a4d82fc | 1443 | |
e9174d1e SL |
1444 | let (containing_scope, _) = get_namespace_and_span_for_item(cx, enum_def_id); |
1445 | // FIXME: This should emit actual file metadata for the enum, but we | |
1446 | // currently can't get the necessary information when it comes to types | |
1447 | // imported from other crates. Formerly we violated the ODR when performing | |
1448 | // LTO because we emitted debuginfo for the same type with varying file | |
1449 | // metadata, so as a workaround we pretend that the type comes from | |
1450 | // <unknown> | |
1451 | let file_metadata = unknown_file_metadata(cx); | |
1a4d82fc | 1452 | |
e9174d1e | 1453 | let variants = &enum_type.ty_adt_def().unwrap().variants; |
d9579d0f AL |
1454 | let enumerators_metadata: Vec<DIDescriptor> = variants |
1455 | .iter() | |
1456 | .map(|v| { | |
c1a9b12d | 1457 | let token = v.name.as_str(); |
d9579d0f AL |
1458 | let name = CString::new(token.as_bytes()).unwrap(); |
1459 | unsafe { | |
5bcae85e | 1460 | llvm::LLVMRustDIBuilderCreateEnumerator( |
d9579d0f AL |
1461 | DIB(cx), |
1462 | name.as_ptr(), | |
54a0048b | 1463 | v.disr_val.to_u64_unchecked()) |
1a4d82fc | 1464 | } |
d9579d0f AL |
1465 | }) |
1466 | .collect(); | |
1a4d82fc | 1467 | |
9e0c209e | 1468 | let discriminant_type_metadata = |inttype: layout::Integer, signed: bool| { |
c1a9b12d | 1469 | let disr_type_key = (enum_def_id, inttype); |
d9579d0f AL |
1470 | let cached_discriminant_type_metadata = debug_context(cx).created_enum_disr_types |
1471 | .borrow() | |
c1a9b12d | 1472 | .get(&disr_type_key).cloned(); |
d9579d0f AL |
1473 | match cached_discriminant_type_metadata { |
1474 | Some(discriminant_type_metadata) => discriminant_type_metadata, | |
1475 | None => { | |
9e0c209e | 1476 | let discriminant_llvm_type = Type::from_integer(cx, inttype); |
d9579d0f AL |
1477 | let (discriminant_size, discriminant_align) = |
1478 | size_and_align_of(cx, discriminant_llvm_type); | |
1479 | let discriminant_base_type_metadata = | |
1480 | type_metadata(cx, | |
9e0c209e | 1481 | inttype.to_ty(&cx.tcx(), signed), |
3157f602 | 1482 | syntax_pos::DUMMY_SP); |
d9579d0f | 1483 | let discriminant_name = get_enum_discriminant_name(cx, enum_def_id); |
1a4d82fc | 1484 | |
d9579d0f AL |
1485 | let name = CString::new(discriminant_name.as_bytes()).unwrap(); |
1486 | let discriminant_type_metadata = unsafe { | |
5bcae85e | 1487 | llvm::LLVMRustDIBuilderCreateEnumerationType( |
d9579d0f AL |
1488 | DIB(cx), |
1489 | containing_scope, | |
1490 | name.as_ptr(), | |
5bcae85e | 1491 | file_metadata, |
d9579d0f AL |
1492 | UNKNOWN_LINE_NUMBER, |
1493 | bytes_to_bits(discriminant_size), | |
1494 | bytes_to_bits(discriminant_align), | |
1495 | create_DIArray(DIB(cx), &enumerators_metadata), | |
1496 | discriminant_base_type_metadata) | |
1497 | }; | |
1a4d82fc | 1498 | |
d9579d0f AL |
1499 | debug_context(cx).created_enum_disr_types |
1500 | .borrow_mut() | |
c1a9b12d | 1501 | .insert(disr_type_key, discriminant_type_metadata); |
1a4d82fc | 1502 | |
d9579d0f | 1503 | discriminant_type_metadata |
1a4d82fc JJ |
1504 | } |
1505 | } | |
d9579d0f | 1506 | }; |
1a4d82fc | 1507 | |
9e0c209e | 1508 | let type_rep = cx.layout_of(enum_type); |
1a4d82fc | 1509 | |
d9579d0f | 1510 | let discriminant_type_metadata = match *type_rep { |
9e0c209e SL |
1511 | layout::CEnum { discr, signed, .. } => { |
1512 | return FinalMetadata(discriminant_type_metadata(discr, signed)) | |
d9579d0f | 1513 | }, |
9e0c209e SL |
1514 | layout::RawNullablePointer { .. } | |
1515 | layout::StructWrappedNullablePointer { .. } | | |
1516 | layout::Univariant { .. } => None, | |
1517 | layout::General { discr, .. } => Some(discriminant_type_metadata(discr, false)), | |
1518 | ref l @ _ => bug!("Not an enum layout: {:#?}", l) | |
d9579d0f | 1519 | }; |
1a4d82fc | 1520 | |
d9579d0f AL |
1521 | let enum_llvm_type = type_of::type_of(cx, enum_type); |
1522 | let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type); | |
1a4d82fc | 1523 | |
d9579d0f | 1524 | let enum_name = CString::new(enum_name).unwrap(); |
476ff2be SL |
1525 | let unique_type_id_str = CString::new( |
1526 | debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id).as_bytes() | |
1527 | ).unwrap(); | |
d9579d0f | 1528 | let enum_metadata = unsafe { |
5bcae85e | 1529 | llvm::LLVMRustDIBuilderCreateUnionType( |
d9579d0f AL |
1530 | DIB(cx), |
1531 | containing_scope, | |
1532 | enum_name.as_ptr(), | |
62682a34 | 1533 | file_metadata, |
d9579d0f AL |
1534 | UNKNOWN_LINE_NUMBER, |
1535 | bytes_to_bits(enum_type_size), | |
1536 | bytes_to_bits(enum_type_align), | |
476ff2be | 1537 | DIFlags::FlagZero, |
d9579d0f AL |
1538 | ptr::null_mut(), |
1539 | 0, // RuntimeLang | |
1540 | unique_type_id_str.as_ptr()) | |
1541 | }; | |
1a4d82fc | 1542 | |
d9579d0f AL |
1543 | return create_and_register_recursive_type_forward_declaration( |
1544 | cx, | |
1545 | enum_type, | |
1546 | unique_type_id, | |
1547 | enum_metadata, | |
1548 | enum_llvm_type, | |
1549 | EnumMDF(EnumMemberDescriptionFactory { | |
1550 | enum_type: enum_type, | |
9e0c209e | 1551 | type_rep: type_rep, |
d9579d0f AL |
1552 | discriminant_type_metadata: discriminant_type_metadata, |
1553 | containing_scope: containing_scope, | |
1554 | file_metadata: file_metadata, | |
1555 | span: span, | |
1556 | }), | |
1557 | ); | |
1a4d82fc | 1558 | |
d9579d0f | 1559 | fn get_enum_discriminant_name(cx: &CrateContext, |
e9174d1e | 1560 | def_id: DefId) |
476ff2be | 1561 | -> InternedString { |
e9174d1e | 1562 | cx.tcx().item_name(def_id).as_str() |
d9579d0f AL |
1563 | } |
1564 | } | |
1a4d82fc | 1565 | |
d9579d0f AL |
1566 | /// Creates debug information for a composite type, that is, anything that |
1567 | /// results in a LLVM struct. | |
1568 | /// | |
1569 | /// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums. | |
1570 | fn composite_type_metadata(cx: &CrateContext, | |
1571 | composite_llvm_type: Type, | |
1572 | composite_type_name: &str, | |
1573 | composite_type_unique_id: UniqueTypeId, | |
1574 | member_descriptions: &[MemberDescription], | |
1575 | containing_scope: DIScope, | |
1a4d82fc | 1576 | |
d9579d0f AL |
1577 | // Ignore source location information as long as it |
1578 | // can't be reconstructed for non-local crates. | |
1579 | _file_metadata: DIFile, | |
1580 | _definition_span: Span) | |
1581 | -> DICompositeType { | |
1582 | // Create the (empty) struct metadata node ... | |
1583 | let composite_type_metadata = create_struct_stub(cx, | |
1584 | composite_llvm_type, | |
1585 | composite_type_name, | |
1586 | composite_type_unique_id, | |
1587 | containing_scope); | |
1588 | // ... and immediately create and add the member descriptions. | |
1589 | set_members_of_composite_type(cx, | |
1590 | composite_type_metadata, | |
1591 | composite_llvm_type, | |
1592 | member_descriptions); | |
1a4d82fc | 1593 | |
d9579d0f AL |
1594 | return composite_type_metadata; |
1595 | } | |
1a4d82fc | 1596 | |
d9579d0f AL |
1597 | fn set_members_of_composite_type(cx: &CrateContext, |
1598 | composite_type_metadata: DICompositeType, | |
1599 | composite_llvm_type: Type, | |
1600 | member_descriptions: &[MemberDescription]) { | |
1601 | // In some rare cases LLVM metadata uniquing would lead to an existing type | |
1602 | // description being used instead of a new one created in | |
1603 | // create_struct_stub. This would cause a hard to trace assertion in | |
1604 | // DICompositeType::SetTypeArray(). The following check makes sure that we | |
1605 | // get a better error message if this should happen again due to some | |
1606 | // regression. | |
1607 | { | |
1608 | let mut composite_types_completed = | |
1609 | debug_context(cx).composite_types_completed.borrow_mut(); | |
1610 | if composite_types_completed.contains(&composite_type_metadata) { | |
54a0048b SL |
1611 | bug!("debuginfo::set_members_of_composite_type() - \ |
1612 | Already completed forward declaration re-encountered."); | |
d9579d0f AL |
1613 | } else { |
1614 | composite_types_completed.insert(composite_type_metadata); | |
1615 | } | |
1616 | } | |
1a4d82fc | 1617 | |
d9579d0f AL |
1618 | let member_metadata: Vec<DIDescriptor> = member_descriptions |
1619 | .iter() | |
1620 | .enumerate() | |
1621 | .map(|(i, member_description)| { | |
1622 | let (member_size, member_align) = size_and_align_of(cx, member_description.llvm_type); | |
1623 | let member_offset = match member_description.offset { | |
1624 | FixedMemberOffset { bytes } => bytes as u64, | |
1625 | ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i) | |
1626 | }; | |
1a4d82fc | 1627 | |
d9579d0f AL |
1628 | let member_name = member_description.name.as_bytes(); |
1629 | let member_name = CString::new(member_name).unwrap(); | |
1630 | unsafe { | |
5bcae85e | 1631 | llvm::LLVMRustDIBuilderCreateMemberType( |
d9579d0f AL |
1632 | DIB(cx), |
1633 | composite_type_metadata, | |
1634 | member_name.as_ptr(), | |
5bcae85e | 1635 | unknown_file_metadata(cx), |
d9579d0f AL |
1636 | UNKNOWN_LINE_NUMBER, |
1637 | bytes_to_bits(member_size), | |
1638 | bytes_to_bits(member_align), | |
1639 | bytes_to_bits(member_offset), | |
1640 | member_description.flags, | |
1641 | member_description.type_metadata) | |
1a4d82fc | 1642 | } |
d9579d0f AL |
1643 | }) |
1644 | .collect(); | |
1a4d82fc | 1645 | |
d9579d0f AL |
1646 | unsafe { |
1647 | let type_array = create_DIArray(DIB(cx), &member_metadata[..]); | |
5bcae85e SL |
1648 | llvm::LLVMRustDICompositeTypeSetTypeArray( |
1649 | DIB(cx), composite_type_metadata, type_array); | |
d9579d0f AL |
1650 | } |
1651 | } | |
1a4d82fc | 1652 | |
5bcae85e SL |
1653 | // A convenience wrapper around LLVMRustDIBuilderCreateStructType(). Does not do |
1654 | // any caching, does not add any fields to the struct. This can be done later | |
1655 | // with set_members_of_composite_type(). | |
d9579d0f AL |
1656 | fn create_struct_stub(cx: &CrateContext, |
1657 | struct_llvm_type: Type, | |
1658 | struct_type_name: &str, | |
1659 | unique_type_id: UniqueTypeId, | |
1660 | containing_scope: DIScope) | |
1661 | -> DICompositeType { | |
1662 | let (struct_size, struct_align) = size_and_align_of(cx, struct_llvm_type); | |
1a4d82fc | 1663 | |
d9579d0f | 1664 | let name = CString::new(struct_type_name).unwrap(); |
476ff2be SL |
1665 | let unique_type_id = CString::new( |
1666 | debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id).as_bytes() | |
1667 | ).unwrap(); | |
d9579d0f | 1668 | let metadata_stub = unsafe { |
5bcae85e | 1669 | // LLVMRustDIBuilderCreateStructType() wants an empty array. A null |
d9579d0f AL |
1670 | // pointer will lead to hard to trace and debug LLVM assertions |
1671 | // later on in llvm/lib/IR/Value.cpp. | |
1672 | let empty_array = create_DIArray(DIB(cx), &[]); | |
1a4d82fc | 1673 | |
5bcae85e | 1674 | llvm::LLVMRustDIBuilderCreateStructType( |
d9579d0f AL |
1675 | DIB(cx), |
1676 | containing_scope, | |
1677 | name.as_ptr(), | |
5bcae85e | 1678 | unknown_file_metadata(cx), |
d9579d0f AL |
1679 | UNKNOWN_LINE_NUMBER, |
1680 | bytes_to_bits(struct_size), | |
1681 | bytes_to_bits(struct_align), | |
476ff2be | 1682 | DIFlags::FlagZero, |
d9579d0f AL |
1683 | ptr::null_mut(), |
1684 | empty_array, | |
1685 | 0, | |
1686 | ptr::null_mut(), | |
1687 | unique_type_id.as_ptr()) | |
1688 | }; | |
1a4d82fc | 1689 | |
d9579d0f AL |
1690 | return metadata_stub; |
1691 | } | |
1a4d82fc | 1692 | |
9e0c209e SL |
1693 | fn create_union_stub(cx: &CrateContext, |
1694 | union_llvm_type: Type, | |
1695 | union_type_name: &str, | |
1696 | unique_type_id: UniqueTypeId, | |
1697 | containing_scope: DIScope) | |
1698 | -> DICompositeType { | |
1699 | let (union_size, union_align) = size_and_align_of(cx, union_llvm_type); | |
1700 | ||
9e0c209e | 1701 | let name = CString::new(union_type_name).unwrap(); |
476ff2be SL |
1702 | let unique_type_id = CString::new( |
1703 | debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id).as_bytes() | |
1704 | ).unwrap(); | |
9e0c209e SL |
1705 | let metadata_stub = unsafe { |
1706 | // LLVMRustDIBuilderCreateUnionType() wants an empty array. A null | |
1707 | // pointer will lead to hard to trace and debug LLVM assertions | |
1708 | // later on in llvm/lib/IR/Value.cpp. | |
1709 | let empty_array = create_DIArray(DIB(cx), &[]); | |
1710 | ||
1711 | llvm::LLVMRustDIBuilderCreateUnionType( | |
1712 | DIB(cx), | |
1713 | containing_scope, | |
1714 | name.as_ptr(), | |
1715 | unknown_file_metadata(cx), | |
1716 | UNKNOWN_LINE_NUMBER, | |
1717 | bytes_to_bits(union_size), | |
1718 | bytes_to_bits(union_align), | |
476ff2be | 1719 | DIFlags::FlagZero, |
9e0c209e SL |
1720 | empty_array, |
1721 | 0, // RuntimeLang | |
1722 | unique_type_id.as_ptr()) | |
1723 | }; | |
1724 | ||
1725 | return metadata_stub; | |
1726 | } | |
1727 | ||
d9579d0f AL |
1728 | /// Creates debug information for the given global variable. |
1729 | /// | |
1730 | /// Adds the created metadata nodes directly to the crate's IR. | |
1731 | pub fn create_global_var_metadata(cx: &CrateContext, | |
1732 | node_id: ast::NodeId, | |
1733 | global: ValueRef) { | |
1734 | if cx.dbg_cx().is_none() { | |
1735 | return; | |
1736 | } | |
1a4d82fc | 1737 | |
c30ab7b3 SL |
1738 | let tcx = cx.tcx(); |
1739 | ||
d9579d0f AL |
1740 | // Don't create debuginfo for globals inlined from other crates. The other |
1741 | // crate should already contain debuginfo for it. More importantly, the | |
1742 | // global might not even exist in un-inlined form anywhere which would lead | |
1743 | // to a linker errors. | |
c30ab7b3 | 1744 | if tcx.map.is_inlined_node_id(node_id) { |
d9579d0f AL |
1745 | return; |
1746 | } | |
1a4d82fc | 1747 | |
c30ab7b3 | 1748 | let node_def_id = tcx.map.local_def_id(node_id); |
a7813a04 | 1749 | let (var_scope, span) = get_namespace_and_span_for_item(cx, node_def_id); |
1a4d82fc | 1750 | |
3157f602 | 1751 | let (file_metadata, line_number) = if span != syntax_pos::DUMMY_SP { |
d9579d0f | 1752 | let loc = span_start(cx, span); |
3157f602 | 1753 | (file_metadata(cx, &loc.file.name, &loc.file.abs_path), loc.line as c_uint) |
d9579d0f | 1754 | } else { |
5bcae85e | 1755 | (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) |
d9579d0f | 1756 | }; |
1a4d82fc | 1757 | |
d9579d0f | 1758 | let is_local_to_unit = is_node_local_to_unit(cx, node_id); |
476ff2be | 1759 | let variable_type = tcx.erase_regions(&tcx.item_type(node_def_id)); |
d9579d0f | 1760 | let type_metadata = type_metadata(cx, variable_type, span); |
c30ab7b3 | 1761 | let var_name = tcx.item_name(node_def_id).to_string(); |
a7813a04 | 1762 | let linkage_name = mangled_name_of_item(cx, node_def_id, ""); |
1a4d82fc | 1763 | |
d9579d0f AL |
1764 | let var_name = CString::new(var_name).unwrap(); |
1765 | let linkage_name = CString::new(linkage_name).unwrap(); | |
476ff2be SL |
1766 | |
1767 | let ty = cx.tcx().item_type(node_def_id); | |
1768 | let global_align = type_of::align_of(cx, ty); | |
1769 | ||
d9579d0f | 1770 | unsafe { |
5bcae85e SL |
1771 | llvm::LLVMRustDIBuilderCreateStaticVariable(DIB(cx), |
1772 | var_scope, | |
1773 | var_name.as_ptr(), | |
1774 | linkage_name.as_ptr(), | |
1775 | file_metadata, | |
1776 | line_number, | |
1777 | type_metadata, | |
1778 | is_local_to_unit, | |
1779 | global, | |
476ff2be SL |
1780 | ptr::null_mut(), |
1781 | global_align as u64, | |
1782 | ); | |
d9579d0f AL |
1783 | } |
1784 | } | |
1a4d82fc | 1785 | |
9e0c209e SL |
1786 | // Creates an "extension" of an existing DIScope into another file. |
1787 | pub fn extend_scope_to_file(ccx: &CrateContext, | |
1788 | scope_metadata: DIScope, | |
1789 | file: &syntax_pos::FileMap) | |
1790 | -> DILexicalBlock { | |
1791 | let file_metadata = file_metadata(ccx, &file.name, &file.abs_path); | |
1792 | unsafe { | |
1793 | llvm::LLVMRustDIBuilderCreateLexicalBlockFile( | |
1794 | DIB(ccx), | |
1795 | scope_metadata, | |
1796 | file_metadata) | |
d9579d0f | 1797 | } |
1a4d82fc | 1798 | } |