]>
Commit | Line | Data |
---|---|---|
f035d41b | 1 | use self::EnumTagInfo::*; |
dfeec247 XL |
2 | use self::MemberDescriptionFactory::*; |
3 | use self::RecursiveTypeDescription::*; | |
1a4d82fc | 4 | |
0531ce1d | 5 | use super::namespace::mangled_name_of_instance; |
c30ab7b3 | 6 | use super::type_names::compute_debuginfo_type_name; |
dfeec247 | 7 | use super::utils::{ |
ba9703b0 | 8 | create_DIArray, debug_context, get_namespace_for_item, is_node_local_to_unit, DIB, |
dfeec247 | 9 | }; |
e74abb32 | 10 | use super::CrateDebugContext; |
d9579d0f | 11 | |
60c5eb7d XL |
12 | use crate::abi; |
13 | use crate::common::CodegenCx; | |
9fa01778 | 14 | use crate::llvm; |
dfeec247 XL |
15 | use crate::llvm::debuginfo::{ |
16 | DIArray, DICompositeType, DIDescriptor, DIFile, DIFlags, DILexicalBlock, DIScope, DIType, | |
17 | DebugEmissionKind, | |
18 | }; | |
60c5eb7d | 19 | use crate::value::Value; |
d9579d0f | 20 | |
6a06907d | 21 | use cstr::cstr; |
dfeec247 | 22 | use rustc_codegen_ssa::traits::*; |
dfeec247 XL |
23 | use rustc_data_structures::fingerprint::Fingerprint; |
24 | use rustc_data_structures::fx::FxHashMap; | |
dfeec247 XL |
25 | use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; |
26 | use rustc_fs_util::path_to_c_string; | |
27 | use rustc_hir::def::CtorKind; | |
29967ef6 | 28 | use rustc_hir::def_id::{DefId, LOCAL_CRATE}; |
dfeec247 | 29 | use rustc_index::vec::{Idx, IndexVec}; |
ba9703b0 | 30 | use rustc_middle::ich::NodeIdHashingMode; |
ba9703b0 XL |
31 | use rustc_middle::mir::{self, Field, GeneratorLayout}; |
32 | use rustc_middle::ty::layout::{self, IntegerExt, PrimitiveExt, TyAndLayout}; | |
f035d41b | 33 | use rustc_middle::ty::subst::GenericArgKind; |
ba9703b0 | 34 | use rustc_middle::ty::Instance; |
f035d41b | 35 | use rustc_middle::ty::{self, AdtKind, GeneratorSubsts, ParamEnv, Ty, TyCtxt}; |
ba9703b0 XL |
36 | use rustc_middle::{bug, span_bug}; |
37 | use rustc_session::config::{self, DebugInfo}; | |
dfeec247 | 38 | use rustc_span::symbol::{Interner, Symbol}; |
ba9703b0 | 39 | use rustc_span::{self, SourceFile, SourceFileHash, Span}; |
f035d41b | 40 | use rustc_target::abi::{Abi, Align, HasDataLayout, Integer, LayoutOf, TagEncoding}; |
ba9703b0 XL |
41 | use rustc_target::abi::{Int, Pointer, F32, F64}; |
42 | use rustc_target::abi::{Primitive, Size, VariantIdx, Variants}; | |
3dfed10e | 43 | use tracing::debug; |
1a4d82fc | 44 | |
dfeec247 | 45 | use libc::{c_longlong, c_uint}; |
dc9dc135 | 46 | use std::collections::hash_map::Entry; |
b7449926 XL |
47 | use std::fmt::{self, Write}; |
48 | use std::hash::{Hash, Hasher}; | |
8faf50e0 | 49 | use std::iter; |
ff7c6d11 | 50 | use std::path::{Path, PathBuf}; |
dfeec247 | 51 | use std::ptr; |
1a4d82fc | 52 | |
b7449926 XL |
53 | impl PartialEq for llvm::Metadata { |
54 | fn eq(&self, other: &Self) -> bool { | |
0731742a | 55 | ptr::eq(self, other) |
b7449926 XL |
56 | } |
57 | } | |
58 | ||
59 | impl Eq for llvm::Metadata {} | |
60 | ||
61 | impl Hash for llvm::Metadata { | |
62 | fn hash<H: Hasher>(&self, hasher: &mut H) { | |
63 | (self as *const Self).hash(hasher); | |
64 | } | |
65 | } | |
66 | ||
67 | impl fmt::Debug for llvm::Metadata { | |
9fa01778 | 68 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
b7449926 XL |
69 | (self as *const Self).fmt(f) |
70 | } | |
71 | } | |
c30ab7b3 | 72 | |
54a0048b | 73 | // From DWARF 5. |
60c5eb7d | 74 | // See http://www.dwarfstd.org/ShowIssue.php?issue=140129.1. |
54a0048b | 75 | const DW_LANG_RUST: c_uint = 0x1c; |
1a4d82fc JJ |
76 | #[allow(non_upper_case_globals)] |
77 | const DW_ATE_boolean: c_uint = 0x02; | |
78 | #[allow(non_upper_case_globals)] | |
79 | const DW_ATE_float: c_uint = 0x04; | |
80 | #[allow(non_upper_case_globals)] | |
81 | const DW_ATE_signed: c_uint = 0x05; | |
82 | #[allow(non_upper_case_globals)] | |
83 | const DW_ATE_unsigned: c_uint = 0x07; | |
84 | #[allow(non_upper_case_globals)] | |
85 | const DW_ATE_unsigned_char: c_uint = 0x08; | |
86 | ||
d9579d0f AL |
87 | pub const UNKNOWN_LINE_NUMBER: c_uint = 0; |
88 | pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0; | |
1a4d82fc | 89 | |
b7449926 | 90 | pub const NO_SCOPE_METADATA: Option<&DIScope> = None; |
1a4d82fc | 91 | |
85aaf69f | 92 | #[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)] |
f9f354fc | 93 | pub struct UniqueTypeId(Symbol); |
1a4d82fc | 94 | |
60c5eb7d XL |
95 | /// The `TypeMap` is where the `CrateDebugContext` holds the type metadata nodes |
96 | /// created so far. The metadata nodes are indexed by `UniqueTypeId`, and, for | |
97 | /// faster lookup, also by `Ty`. The `TypeMap` is responsible for creating | |
98 | /// `UniqueTypeId`s. | |
0bf4aa26 | 99 | #[derive(Default)] |
b7449926 | 100 | pub struct TypeMap<'ll, 'tcx> { |
60c5eb7d | 101 | /// The `UniqueTypeId`s created so far. |
5bcae85e | 102 | unique_id_interner: Interner, |
60c5eb7d | 103 | /// A map from `UniqueTypeId` to debuginfo metadata for that type. This is a 1:1 mapping. |
b7449926 | 104 | unique_id_to_metadata: FxHashMap<UniqueTypeId, &'ll DIType>, |
60c5eb7d | 105 | /// A map from types to debuginfo metadata. This is an N:1 mapping. |
b7449926 | 106 | type_to_metadata: FxHashMap<Ty<'tcx>, &'ll DIType>, |
60c5eb7d | 107 | /// A map from types to `UniqueTypeId`. This is an N:1 mapping. |
dfeec247 | 108 | type_to_unique_id: FxHashMap<Ty<'tcx>, UniqueTypeId>, |
1a4d82fc JJ |
109 | } |
110 | ||
b7449926 | 111 | impl TypeMap<'ll, 'tcx> { |
60c5eb7d XL |
112 | /// Adds a Ty to metadata mapping to the TypeMap. The method will fail if |
113 | /// the mapping already exists. | |
dfeec247 | 114 | fn register_type_with_metadata(&mut self, type_: Ty<'tcx>, metadata: &'ll DIType) { |
1a4d82fc | 115 | if self.type_to_metadata.insert(type_, metadata).is_some() { |
60c5eb7d | 116 | bug!("type metadata for `Ty` '{}' is already in the `TypeMap`!", type_); |
1a4d82fc JJ |
117 | } |
118 | } | |
119 | ||
60c5eb7d XL |
120 | /// Removes a `Ty`-to-metadata mapping. |
121 | /// This is useful when computing the metadata for a potentially | |
122 | /// recursive type (e.g., a function pointer of the form: | |
123 | /// | |
124 | /// fn foo() -> impl Copy { foo } | |
125 | /// | |
126 | /// This kind of type cannot be properly represented | |
127 | /// via LLVM debuginfo. As a workaround, | |
128 | /// we register a temporary Ty to metadata mapping | |
129 | /// for the function before we compute its actual metadata. | |
130 | /// If the metadata computation ends up recursing back to the | |
131 | /// original function, it will use the temporary mapping | |
132 | /// for the inner self-reference, preventing us from | |
133 | /// recursing forever. | |
134 | /// | |
135 | /// This function is used to remove the temporary metadata | |
136 | /// mapping after we've computed the actual metadata. | |
dfeec247 | 137 | fn remove_type(&mut self, type_: Ty<'tcx>) { |
532ac7d7 | 138 | if self.type_to_metadata.remove(type_).is_none() { |
60c5eb7d | 139 | bug!("type metadata `Ty` '{}' is not in the `TypeMap`!", type_); |
532ac7d7 XL |
140 | } |
141 | } | |
142 | ||
60c5eb7d XL |
143 | /// Adds a `UniqueTypeId` to metadata mapping to the `TypeMap`. The method will |
144 | /// fail if the mapping already exists. | |
b7449926 XL |
145 | fn register_unique_id_with_metadata( |
146 | &mut self, | |
147 | unique_type_id: UniqueTypeId, | |
148 | metadata: &'ll DIType, | |
149 | ) { | |
1a4d82fc | 150 | if self.unique_id_to_metadata.insert(unique_type_id, metadata).is_some() { |
dfeec247 XL |
151 | bug!( |
152 | "type metadata for unique ID '{}' is already in the `TypeMap`!", | |
153 | self.get_unique_type_id_as_string(unique_type_id) | |
154 | ); | |
1a4d82fc JJ |
155 | } |
156 | } | |
157 | ||
b7449926 | 158 | fn find_metadata_for_type(&self, type_: Ty<'tcx>) -> Option<&'ll DIType> { |
1a4d82fc JJ |
159 | self.type_to_metadata.get(&type_).cloned() |
160 | } | |
161 | ||
b7449926 | 162 | fn find_metadata_for_unique_id(&self, unique_type_id: UniqueTypeId) -> Option<&'ll DIType> { |
1a4d82fc JJ |
163 | self.unique_id_to_metadata.get(&unique_type_id).cloned() |
164 | } | |
165 | ||
60c5eb7d XL |
166 | /// Gets the string representation of a `UniqueTypeId`. This method will fail if |
167 | /// the ID is unknown. | |
476ff2be | 168 | fn get_unique_type_id_as_string(&self, unique_type_id: UniqueTypeId) -> &str { |
1a4d82fc JJ |
169 | let UniqueTypeId(interner_key) = unique_type_id; |
170 | self.unique_id_interner.get(interner_key) | |
171 | } | |
172 | ||
60c5eb7d XL |
173 | /// Gets the `UniqueTypeId` for the given type. If the `UniqueTypeId` for the given |
174 | /// type has been requested before, this is just a table lookup. Otherwise, an | |
175 | /// ID will be generated and stored for later lookup. | |
dfeec247 XL |
176 | fn get_unique_type_id_of_type<'a>( |
177 | &mut self, | |
178 | cx: &CodegenCx<'a, 'tcx>, | |
179 | type_: Ty<'tcx>, | |
180 | ) -> UniqueTypeId { | |
60c5eb7d | 181 | // Let's see if we already have something in the cache. |
0bf4aa26 XL |
182 | if let Some(unique_type_id) = self.type_to_unique_id.get(&type_).cloned() { |
183 | return unique_type_id; | |
184 | } | |
60c5eb7d | 185 | // If not, generate one. |
1a4d82fc | 186 | |
c30ab7b3 SL |
187 | // The hasher we are using to generate the UniqueTypeId. We want |
188 | // something that provides more than the 64 bits of the DefaultHasher. | |
e74abb32 | 189 | let mut hasher = StableHasher::new(); |
94b46f34 | 190 | let mut hcx = cx.tcx.create_stable_hashing_context(); |
fc512014 | 191 | let type_ = cx.tcx.erase_regions(type_); |
94b46f34 XL |
192 | hcx.while_hashing_spans(false, |hcx| { |
193 | hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { | |
194 | type_.hash_stable(hcx, &mut hasher); | |
195 | }); | |
196 | }); | |
e74abb32 | 197 | let unique_type_id = hasher.finish::<Fingerprint>().to_hex(); |
abe05a73 | 198 | |
c30ab7b3 | 199 | let key = self.unique_id_interner.intern(&unique_type_id); |
1a4d82fc JJ |
200 | self.type_to_unique_id.insert(type_, UniqueTypeId(key)); |
201 | ||
ba9703b0 | 202 | UniqueTypeId(key) |
1a4d82fc JJ |
203 | } |
204 | ||
60c5eb7d XL |
205 | /// Gets the `UniqueTypeId` for an enum variant. Enum variants are not really |
206 | /// types of their own, so they need special handling. We still need a | |
207 | /// `UniqueTypeId` for them, since to debuginfo they *are* real types. | |
dfeec247 XL |
208 | fn get_unique_type_id_of_enum_variant<'a>( |
209 | &mut self, | |
210 | cx: &CodegenCx<'a, 'tcx>, | |
211 | enum_type: Ty<'tcx>, | |
212 | variant_name: &str, | |
213 | ) -> UniqueTypeId { | |
1a4d82fc | 214 | let enum_type_id = self.get_unique_type_id_of_type(cx, enum_type); |
dfeec247 XL |
215 | let enum_variant_type_id = |
216 | format!("{}::{}", self.get_unique_type_id_as_string(enum_type_id), variant_name); | |
c30ab7b3 | 217 | let interner_key = self.unique_id_interner.intern(&enum_variant_type_id); |
1a4d82fc JJ |
218 | UniqueTypeId(interner_key) |
219 | } | |
532ac7d7 | 220 | |
60c5eb7d XL |
221 | /// Gets the unique type ID string for an enum variant part. |
222 | /// Variant parts are not types and shouldn't really have their own ID, | |
223 | /// but it makes `set_members_of_composite_type()` simpler. | |
74b04a01 XL |
224 | fn get_unique_type_id_str_of_enum_variant_part( |
225 | &mut self, | |
226 | enum_type_id: UniqueTypeId, | |
227 | ) -> String { | |
228 | format!("{}_variant_part", self.get_unique_type_id_as_string(enum_type_id)) | |
532ac7d7 | 229 | } |
1a4d82fc JJ |
230 | } |
231 | ||
60c5eb7d XL |
232 | /// A description of some recursive type. It can either be already finished (as |
233 | /// with `FinalMetadata`) or it is not yet finished, but contains all information | |
234 | /// needed to generate the missing parts of the description. See the | |
235 | /// documentation section on Recursive Types at the top of this file for more | |
236 | /// information. | |
b7449926 | 237 | enum RecursiveTypeDescription<'ll, 'tcx> { |
d9579d0f AL |
238 | UnfinishedMetadata { |
239 | unfinished_type: Ty<'tcx>, | |
240 | unique_type_id: UniqueTypeId, | |
b7449926 | 241 | metadata_stub: &'ll DICompositeType, |
a1dfa0c6 | 242 | member_holding_stub: &'ll DICompositeType, |
b7449926 | 243 | member_description_factory: MemberDescriptionFactory<'ll, 'tcx>, |
d9579d0f | 244 | }, |
dfeec247 | 245 | FinalMetadata(&'ll DICompositeType), |
d9579d0f AL |
246 | } |
247 | ||
b7449926 XL |
248 | fn create_and_register_recursive_type_forward_declaration( |
249 | cx: &CodegenCx<'ll, 'tcx>, | |
d9579d0f AL |
250 | unfinished_type: Ty<'tcx>, |
251 | unique_type_id: UniqueTypeId, | |
b7449926 | 252 | metadata_stub: &'ll DICompositeType, |
a1dfa0c6 | 253 | member_holding_stub: &'ll DICompositeType, |
b7449926 XL |
254 | member_description_factory: MemberDescriptionFactory<'ll, 'tcx>, |
255 | ) -> RecursiveTypeDescription<'ll, 'tcx> { | |
60c5eb7d | 256 | // Insert the stub into the `TypeMap` in order to allow for recursive references. |
d9579d0f | 257 | let mut type_map = debug_context(cx).type_map.borrow_mut(); |
54a0048b SL |
258 | type_map.register_unique_id_with_metadata(unique_type_id, metadata_stub); |
259 | type_map.register_type_with_metadata(unfinished_type, metadata_stub); | |
d9579d0f AL |
260 | |
261 | UnfinishedMetadata { | |
3b2f2976 XL |
262 | unfinished_type, |
263 | unique_type_id, | |
264 | metadata_stub, | |
a1dfa0c6 | 265 | member_holding_stub, |
3b2f2976 | 266 | member_description_factory, |
d9579d0f AL |
267 | } |
268 | } | |
269 | ||
b7449926 | 270 | impl RecursiveTypeDescription<'ll, 'tcx> { |
60c5eb7d XL |
271 | /// Finishes up the description of the type in question (mostly by providing |
272 | /// descriptions of the fields of the given type) and returns the final type | |
273 | /// metadata. | |
b7449926 | 274 | fn finalize(&self, cx: &CodegenCx<'ll, 'tcx>) -> MetadataCreationResult<'ll> { |
d9579d0f AL |
275 | match *self { |
276 | FinalMetadata(metadata) => MetadataCreationResult::new(metadata, false), | |
277 | UnfinishedMetadata { | |
278 | unfinished_type, | |
279 | unique_type_id, | |
280 | metadata_stub, | |
a1dfa0c6 | 281 | member_holding_stub, |
d9579d0f | 282 | ref member_description_factory, |
d9579d0f AL |
283 | } => { |
284 | // Make sure that we have a forward declaration of the type in | |
285 | // the TypeMap so that recursive references are possible. This | |
286 | // will always be the case if the RecursiveTypeDescription has | |
287 | // been properly created through the | |
60c5eb7d | 288 | // `create_and_register_recursive_type_forward_declaration()` |
d9579d0f AL |
289 | // function. |
290 | { | |
291 | let type_map = debug_context(cx).type_map.borrow(); | |
dfeec247 XL |
292 | if type_map.find_metadata_for_unique_id(unique_type_id).is_none() |
293 | || type_map.find_metadata_for_type(unfinished_type).is_none() | |
294 | { | |
295 | bug!( | |
296 | "Forward declaration of potentially recursive type \ | |
54a0048b | 297 | '{:?}' was not found in TypeMap!", |
dfeec247 XL |
298 | unfinished_type |
299 | ); | |
d9579d0f AL |
300 | } |
301 | } | |
302 | ||
303 | // ... then create the member descriptions ... | |
dfeec247 | 304 | let member_descriptions = member_description_factory.create_member_descriptions(cx); |
d9579d0f AL |
305 | |
306 | // ... and attach them to the stub to complete it. | |
dfeec247 XL |
307 | set_members_of_composite_type( |
308 | cx, | |
309 | unfinished_type, | |
310 | member_holding_stub, | |
311 | member_descriptions, | |
312 | ); | |
ba9703b0 | 313 | MetadataCreationResult::new(metadata_stub, true) |
d9579d0f AL |
314 | } |
315 | } | |
316 | } | |
317 | } | |
318 | ||
60c5eb7d XL |
319 | /// Returns from the enclosing function if the type metadata with the given |
320 | /// unique ID can be found in the type map. | |
1a4d82fc | 321 | macro_rules! return_if_metadata_created_in_meantime { |
dfeec247 XL |
322 | ($cx: expr, $unique_type_id: expr) => { |
323 | if let Some(metadata) = | |
324 | debug_context($cx).type_map.borrow().find_metadata_for_unique_id($unique_type_id) | |
0bf4aa26 XL |
325 | { |
326 | return MetadataCreationResult::new(metadata, true); | |
b039eaaf | 327 | } |
dfeec247 | 328 | }; |
1a4d82fc JJ |
329 | } |
330 | ||
b7449926 XL |
331 | fn fixed_vec_metadata( |
332 | cx: &CodegenCx<'ll, 'tcx>, | |
333 | unique_type_id: UniqueTypeId, | |
334 | array_or_slice_type: Ty<'tcx>, | |
335 | element_type: Ty<'tcx>, | |
336 | span: Span, | |
337 | ) -> MetadataCreationResult<'ll> { | |
d9579d0f AL |
338 | let element_type_metadata = type_metadata(cx, element_type, span); |
339 | ||
340 | return_if_metadata_created_in_meantime!(cx, unique_type_id); | |
1a4d82fc | 341 | |
ff7c6d11 | 342 | let (size, align) = cx.size_and_align_of(array_or_slice_type); |
1a4d82fc | 343 | |
1b1a35ee | 344 | let upper_bound = match array_or_slice_type.kind() { |
416331ca | 345 | ty::Array(_, len) => len.eval_usize(cx.tcx, ty::ParamEnv::reveal_all()) as c_longlong, |
dfeec247 | 346 | _ => -1, |
d9579d0f | 347 | }; |
1a4d82fc | 348 | |
dfeec247 XL |
349 | let subrange = |
350 | unsafe { Some(llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)) }; | |
1a4d82fc | 351 | |
d9579d0f AL |
352 | let subscripts = create_DIArray(DIB(cx), &[subrange]); |
353 | let metadata = unsafe { | |
5bcae85e | 354 | llvm::LLVMRustDIBuilderCreateArrayType( |
d9579d0f | 355 | DIB(cx), |
ff7c6d11 | 356 | size.bits(), |
a1dfa0c6 | 357 | align.bits() as u32, |
d9579d0f | 358 | element_type_metadata, |
dfeec247 XL |
359 | subscripts, |
360 | ) | |
d9579d0f | 361 | }; |
1a4d82fc | 362 | |
ba9703b0 | 363 | MetadataCreationResult::new(metadata, false) |
1a4d82fc JJ |
364 | } |
365 | ||
b7449926 XL |
366 | fn vec_slice_metadata( |
367 | cx: &CodegenCx<'ll, 'tcx>, | |
368 | slice_ptr_type: Ty<'tcx>, | |
369 | element_type: Ty<'tcx>, | |
370 | unique_type_id: UniqueTypeId, | |
371 | span: Span, | |
372 | ) -> MetadataCreationResult<'ll> { | |
2c00a5a8 | 373 | let data_ptr_type = cx.tcx.mk_imm_ptr(element_type); |
1a4d82fc | 374 | |
ff7c6d11 | 375 | let data_ptr_metadata = type_metadata(cx, data_ptr_type, span); |
1a4d82fc | 376 | |
d9579d0f | 377 | return_if_metadata_created_in_meantime!(cx, unique_type_id); |
1a4d82fc | 378 | |
48663c56 | 379 | let slice_type_name = compute_debuginfo_type_name(cx.tcx, slice_ptr_type, true); |
ff7c6d11 XL |
380 | |
381 | let (pointer_size, pointer_align) = cx.size_and_align_of(data_ptr_type); | |
2c00a5a8 | 382 | let (usize_size, usize_align) = cx.size_and_align_of(cx.tcx.types.usize); |
1a4d82fc | 383 | |
b7449926 | 384 | let member_descriptions = vec![ |
d9579d0f | 385 | MemberDescription { |
0bf4aa26 | 386 | name: "data_ptr".to_owned(), |
ff7c6d11 | 387 | type_metadata: data_ptr_metadata, |
94b46f34 | 388 | offset: Size::ZERO, |
ff7c6d11 XL |
389 | size: pointer_size, |
390 | align: pointer_align, | |
476ff2be | 391 | flags: DIFlags::FlagZero, |
a1dfa0c6 | 392 | discriminant: None, |
f035d41b | 393 | source_info: None, |
d9579d0f AL |
394 | }, |
395 | MemberDescription { | |
0bf4aa26 | 396 | name: "length".to_owned(), |
2c00a5a8 | 397 | type_metadata: type_metadata(cx, cx.tcx.types.usize, span), |
ff7c6d11 XL |
398 | offset: pointer_size, |
399 | size: usize_size, | |
400 | align: usize_align, | |
476ff2be | 401 | flags: DIFlags::FlagZero, |
a1dfa0c6 | 402 | discriminant: None, |
f035d41b | 403 | source_info: None, |
d9579d0f AL |
404 | }, |
405 | ]; | |
1a4d82fc | 406 | |
7cac9316 | 407 | let file_metadata = unknown_file_metadata(cx); |
1a4d82fc | 408 | |
dfeec247 XL |
409 | let metadata = composite_type_metadata( |
410 | cx, | |
411 | slice_ptr_type, | |
412 | &slice_type_name[..], | |
413 | unique_type_id, | |
414 | member_descriptions, | |
415 | NO_SCOPE_METADATA, | |
416 | file_metadata, | |
417 | span, | |
418 | ); | |
ff7c6d11 | 419 | MetadataCreationResult::new(metadata, false) |
d9579d0f | 420 | } |
1a4d82fc | 421 | |
b7449926 XL |
422 | fn subroutine_type_metadata( |
423 | cx: &CodegenCx<'ll, 'tcx>, | |
424 | unique_type_id: UniqueTypeId, | |
425 | signature: ty::PolyFnSig<'tcx>, | |
426 | span: Span, | |
427 | ) -> MetadataCreationResult<'ll> { | |
dfeec247 | 428 | let signature = |
fc512014 | 429 | cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), signature); |
1a4d82fc | 430 | |
b7449926 | 431 | let signature_metadata: Vec<_> = iter::once( |
8faf50e0 | 432 | // return type |
1b1a35ee | 433 | match signature.output().kind() { |
b7449926 | 434 | ty::Tuple(ref tys) if tys.is_empty() => None, |
dfeec247 XL |
435 | _ => Some(type_metadata(cx, signature.output(), span)), |
436 | }, | |
437 | ) | |
438 | .chain( | |
8faf50e0 | 439 | // regular arguments |
dfeec247 XL |
440 | signature.inputs().iter().map(|argument_type| Some(type_metadata(cx, argument_type, span))), |
441 | ) | |
442 | .collect(); | |
1a4d82fc | 443 | |
d9579d0f | 444 | return_if_metadata_created_in_meantime!(cx, unique_type_id); |
1a4d82fc | 445 | |
ba9703b0 | 446 | MetadataCreationResult::new( |
d9579d0f | 447 | unsafe { |
5bcae85e | 448 | llvm::LLVMRustDIBuilderCreateSubroutineType( |
d9579d0f | 449 | DIB(cx), |
dfeec247 XL |
450 | create_DIArray(DIB(cx), &signature_metadata[..]), |
451 | ) | |
1a4d82fc | 452 | }, |
dfeec247 | 453 | false, |
ba9703b0 | 454 | ) |
1a4d82fc JJ |
455 | } |
456 | ||
416331ca XL |
457 | // FIXME(1563): This is all a bit of a hack because 'trait pointer' is an ill- |
458 | // defined concept. For the case of an actual trait pointer (i.e., `Box<Trait>`, | |
459 | // `&Trait`), `trait_object_type` should be the whole thing (e.g, `Box<Trait>`) and | |
460 | // `trait_type` should be the actual trait (e.g., `Trait`). Where the trait is part | |
461 | // of a DST struct, there is no `trait_object_type` and the results of this | |
1a4d82fc | 462 | // function will be a little bit weird. |
b7449926 XL |
463 | fn trait_pointer_metadata( |
464 | cx: &CodegenCx<'ll, 'tcx>, | |
465 | trait_type: Ty<'tcx>, | |
466 | trait_object_type: Option<Ty<'tcx>>, | |
467 | unique_type_id: UniqueTypeId, | |
468 | ) -> &'ll DIType { | |
1a4d82fc JJ |
469 | // The implementation provided here is a stub. It makes sure that the trait |
470 | // type is assigned the correct name, size, namespace, and source location. | |
416331ca | 471 | // However, it does not describe the trait's methods. |
1a4d82fc | 472 | |
1b1a35ee | 473 | let containing_scope = match trait_type.kind() { |
dfeec247 XL |
474 | ty::Dynamic(ref data, ..) => { |
475 | data.principal_def_id().map(|did| get_namespace_for_item(cx, did)) | |
476 | } | |
1a4d82fc | 477 | _ => { |
dfeec247 XL |
478 | bug!( |
479 | "debuginfo: unexpected trait-object type in \ | |
54a0048b | 480 | trait_pointer_metadata(): {:?}", |
dfeec247 XL |
481 | trait_type |
482 | ); | |
1a4d82fc JJ |
483 | } |
484 | }; | |
485 | ||
486 | let trait_object_type = trait_object_type.unwrap_or(trait_type); | |
dfeec247 | 487 | let trait_type_name = compute_debuginfo_type_name(cx.tcx, trait_object_type, false); |
1a4d82fc | 488 | |
5bcae85e | 489 | let file_metadata = unknown_file_metadata(cx); |
1a4d82fc | 490 | |
2c00a5a8 | 491 | let layout = cx.layout_of(cx.tcx.mk_mut_ptr(trait_type)); |
abe05a73 XL |
492 | |
493 | assert_eq!(abi::FAT_PTR_ADDR, 0); | |
494 | assert_eq!(abi::FAT_PTR_EXTRA, 1); | |
ff7c6d11 XL |
495 | |
496 | let data_ptr_field = layout.field(cx, 0); | |
497 | let vtable_field = layout.field(cx, 1); | |
b7449926 | 498 | let member_descriptions = vec![ |
abe05a73 | 499 | MemberDescription { |
0bf4aa26 | 500 | name: "pointer".to_owned(), |
dfeec247 XL |
501 | type_metadata: type_metadata( |
502 | cx, | |
2c00a5a8 | 503 | cx.tcx.mk_mut_ptr(cx.tcx.types.u8), |
dfeec247 XL |
504 | rustc_span::DUMMY_SP, |
505 | ), | |
ff7c6d11 XL |
506 | offset: layout.fields.offset(0), |
507 | size: data_ptr_field.size, | |
a1dfa0c6 | 508 | align: data_ptr_field.align.abi, |
abe05a73 | 509 | flags: DIFlags::FlagArtificial, |
a1dfa0c6 | 510 | discriminant: None, |
f035d41b | 511 | source_info: None, |
abe05a73 XL |
512 | }, |
513 | MemberDescription { | |
0bf4aa26 | 514 | name: "vtable".to_owned(), |
dfeec247 | 515 | type_metadata: type_metadata(cx, vtable_field.ty, rustc_span::DUMMY_SP), |
ff7c6d11 XL |
516 | offset: layout.fields.offset(1), |
517 | size: vtable_field.size, | |
a1dfa0c6 | 518 | align: vtable_field.align.abi, |
abe05a73 | 519 | flags: DIFlags::FlagArtificial, |
a1dfa0c6 | 520 | discriminant: None, |
f035d41b | 521 | source_info: None, |
abe05a73 XL |
522 | }, |
523 | ]; | |
524 | ||
dfeec247 XL |
525 | composite_type_metadata( |
526 | cx, | |
527 | trait_object_type, | |
528 | &trait_type_name[..], | |
529 | unique_type_id, | |
530 | member_descriptions, | |
531 | containing_scope, | |
532 | file_metadata, | |
533 | rustc_span::DUMMY_SP, | |
534 | ) | |
1a4d82fc JJ |
535 | } |
536 | ||
dfeec247 | 537 | pub fn type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>, usage_site_span: Span) -> &'ll DIType { |
60c5eb7d | 538 | // Get the unique type ID of this type. |
1a4d82fc JJ |
539 | let unique_type_id = { |
540 | let mut type_map = debug_context(cx).type_map.borrow_mut(); | |
60c5eb7d | 541 | // First, try to find the type in `TypeMap`. If we have seen it before, we |
1a4d82fc JJ |
542 | // can exit early here. |
543 | match type_map.find_metadata_for_type(t) { | |
544 | Some(metadata) => { | |
545 | return metadata; | |
dfeec247 | 546 | } |
1a4d82fc | 547 | None => { |
60c5eb7d | 548 | // The Ty is not in the `TypeMap` but maybe we have already seen |
0731742a | 549 | // an equivalent type (e.g., only differing in region arguments). |
60c5eb7d | 550 | // In order to find out, generate the unique type ID and look |
1a4d82fc JJ |
551 | // that up. |
552 | let unique_type_id = type_map.get_unique_type_id_of_type(cx, t); | |
553 | match type_map.find_metadata_for_unique_id(unique_type_id) { | |
554 | Some(metadata) => { | |
555 | // There is already an equivalent type in the TypeMap. | |
556 | // Register this Ty as an alias in the cache and | |
557 | // return the cached metadata. | |
54a0048b | 558 | type_map.register_type_with_metadata(t, metadata); |
1a4d82fc | 559 | return metadata; |
dfeec247 | 560 | } |
1a4d82fc JJ |
561 | None => { |
562 | // There really is no type metadata for this type, so | |
563 | // proceed by creating it. | |
564 | unique_type_id | |
565 | } | |
566 | } | |
567 | } | |
568 | } | |
569 | }; | |
570 | ||
571 | debug!("type_metadata: {:?}", t); | |
572 | ||
1b1a35ee | 573 | let ptr_metadata = |ty: Ty<'tcx>| match *ty.kind() { |
dfeec247 XL |
574 | ty::Slice(typ) => Ok(vec_slice_metadata(cx, t, typ, unique_type_id, usage_site_span)), |
575 | ty::Str => Ok(vec_slice_metadata(cx, t, cx.tcx.types.u8, unique_type_id, usage_site_span)), | |
576 | ty::Dynamic(..) => Ok(MetadataCreationResult::new( | |
577 | trait_pointer_metadata(cx, ty, Some(t), unique_type_id), | |
578 | false, | |
579 | )), | |
580 | _ => { | |
581 | let pointee_metadata = type_metadata(cx, ty, usage_site_span); | |
32a655c1 | 582 | |
dfeec247 XL |
583 | if let Some(metadata) = |
584 | debug_context(cx).type_map.borrow().find_metadata_for_unique_id(unique_type_id) | |
585 | { | |
586 | return Err(metadata); | |
32a655c1 | 587 | } |
dfeec247 XL |
588 | |
589 | Ok(MetadataCreationResult::new(pointer_type_metadata(cx, t, pointee_metadata), false)) | |
32a655c1 SL |
590 | } |
591 | }; | |
592 | ||
1b1a35ee | 593 | let MetadataCreationResult { metadata, already_stored_in_typemap } = match *t.kind() { |
dfeec247 | 594 | ty::Never | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) => { |
1a4d82fc JJ |
595 | MetadataCreationResult::new(basic_type_metadata(cx, t), false) |
596 | } | |
b7449926 | 597 | ty::Tuple(ref elements) if elements.is_empty() => { |
1a4d82fc JJ |
598 | MetadataCreationResult::new(basic_type_metadata(cx, t), false) |
599 | } | |
dfeec247 | 600 | ty::Array(typ, _) | ty::Slice(typ) => { |
ff7c6d11 | 601 | fixed_vec_metadata(cx, unique_type_id, t, typ, usage_site_span) |
85aaf69f | 602 | } |
dfeec247 | 603 | ty::Str => fixed_vec_metadata(cx, unique_type_id, t, cx.tcx.types.i8, usage_site_span), |
b7449926 | 604 | ty::Dynamic(..) => { |
dfeec247 | 605 | MetadataCreationResult::new(trait_pointer_metadata(cx, t, None, unique_type_id), false) |
1a4d82fc | 606 | } |
b7449926 | 607 | ty::Foreign(..) => { |
dfeec247 | 608 | MetadataCreationResult::new(foreign_type_metadata(cx, t, unique_type_id), false) |
1a4d82fc | 609 | } |
dfeec247 XL |
610 | ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _) => match ptr_metadata(ty) { |
611 | Ok(res) => res, | |
612 | Err(metadata) => return metadata, | |
613 | }, | |
614 | ty::Adt(def, _) if def.is_box() => match ptr_metadata(t.boxed_ty()) { | |
615 | Ok(res) => res, | |
616 | Err(metadata) => return metadata, | |
617 | }, | |
b7449926 | 618 | ty::FnDef(..) | ty::FnPtr(_) => { |
dfeec247 XL |
619 | if let Some(metadata) = |
620 | debug_context(cx).type_map.borrow().find_metadata_for_unique_id(unique_type_id) | |
0bf4aa26 XL |
621 | { |
622 | return metadata; | |
623 | } | |
c1a9b12d | 624 | |
532ac7d7 XL |
625 | // It's possible to create a self-referential |
626 | // type in Rust by using 'impl trait': | |
627 | // | |
628 | // fn foo() -> impl Copy { foo } | |
629 | // | |
60c5eb7d XL |
630 | // See `TypeMap::remove_type` for more detals |
631 | // about the workaround. | |
532ac7d7 XL |
632 | |
633 | let temp_type = { | |
634 | unsafe { | |
635 | // The choice of type here is pretty arbitrary - | |
636 | // anything reading the debuginfo for a recursive | |
74b04a01 | 637 | // type is going to see *something* weird - the only |
60c5eb7d | 638 | // question is what exactly it will see. |
74b04a01 | 639 | let name = "<recur_type>"; |
532ac7d7 XL |
640 | llvm::LLVMRustDIBuilderCreateBasicType( |
641 | DIB(cx), | |
74b04a01 XL |
642 | name.as_ptr().cast(), |
643 | name.len(), | |
f9f354fc | 644 | cx.size_of(t).bits(), |
dfeec247 XL |
645 | DW_ATE_unsigned, |
646 | ) | |
532ac7d7 XL |
647 | } |
648 | }; | |
649 | ||
650 | let type_map = &debug_context(cx).type_map; | |
651 | type_map.borrow_mut().register_type_with_metadata(t, temp_type); | |
652 | ||
dfeec247 XL |
653 | let fn_metadata = |
654 | subroutine_type_metadata(cx, unique_type_id, t.fn_sig(cx.tcx), usage_site_span) | |
655 | .metadata; | |
532ac7d7 XL |
656 | |
657 | type_map.borrow_mut().remove_type(t); | |
658 | ||
60c5eb7d | 659 | // This is actually a function pointer, so wrap it in pointer DI. |
c1a9b12d | 660 | MetadataCreationResult::new(pointer_type_metadata(cx, t, fn_metadata), false) |
1a4d82fc | 661 | } |
b7449926 | 662 | ty::Closure(def_id, substs) => { |
ba9703b0 | 663 | let upvar_tys: Vec<_> = substs.as_closure().upvar_tys().collect(); |
416331ca | 664 | let containing_scope = get_namespace_for_item(cx, def_id); |
dfeec247 XL |
665 | prepare_tuple_metadata( |
666 | cx, | |
667 | t, | |
668 | &upvar_tys, | |
669 | unique_type_id, | |
670 | usage_site_span, | |
671 | Some(containing_scope), | |
672 | ) | |
673 | .finalize(cx) | |
1a4d82fc | 674 | } |
dfeec247 XL |
675 | ty::Generator(def_id, substs, _) => { |
676 | let upvar_tys: Vec<_> = substs | |
677 | .as_generator() | |
ba9703b0 | 678 | .prefix_tys() |
dfeec247 XL |
679 | .map(|t| cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)) |
680 | .collect(); | |
681 | prepare_enum_metadata(cx, t, def_id, unique_type_id, usage_site_span, upvar_tys) | |
682 | .finalize(cx) | |
ea8adc8c | 683 | } |
b7449926 | 684 | ty::Adt(def, ..) => match def.adt_kind() { |
9e0c209e | 685 | AdtKind::Struct => { |
dfeec247 | 686 | prepare_struct_metadata(cx, t, unique_type_id, usage_site_span).finalize(cx) |
9e0c209e SL |
687 | } |
688 | AdtKind::Union => { | |
dfeec247 | 689 | prepare_union_metadata(cx, t, unique_type_id, usage_site_span).finalize(cx) |
9e0c209e SL |
690 | } |
691 | AdtKind::Enum => { | |
dfeec247 XL |
692 | prepare_enum_metadata(cx, t, def.did, unique_type_id, usage_site_span, vec![]) |
693 | .finalize(cx) | |
9e0c209e SL |
694 | } |
695 | }, | |
b7449926 | 696 | ty::Tuple(ref elements) => { |
48663c56 | 697 | let tys: Vec<_> = elements.iter().map(|k| k.expect_ty()).collect(); |
dfeec247 XL |
698 | prepare_tuple_metadata(cx, t, &tys, unique_type_id, usage_site_span, NO_SCOPE_METADATA) |
699 | .finalize(cx) | |
1a4d82fc | 700 | } |
3dfed10e XL |
701 | // Type parameters from polymorphized functions. |
702 | ty::Param(_) => MetadataCreationResult::new(param_type_metadata(cx, t), false), | |
dfeec247 | 703 | _ => bug!("debuginfo: unexpected type in type_metadata: {:?}", t), |
1a4d82fc JJ |
704 | }; |
705 | ||
706 | { | |
707 | let mut type_map = debug_context(cx).type_map.borrow_mut(); | |
708 | ||
709 | if already_stored_in_typemap { | |
60c5eb7d | 710 | // Also make sure that we already have a `TypeMap` entry for the unique type ID. |
1a4d82fc JJ |
711 | let metadata_for_uid = match type_map.find_metadata_for_unique_id(unique_type_id) { |
712 | Some(metadata) => metadata, | |
713 | None => { | |
dfeec247 XL |
714 | span_bug!( |
715 | usage_site_span, | |
716 | "expected type metadata for unique \ | |
60c5eb7d XL |
717 | type ID '{}' to already be in \ |
718 | the `debuginfo::TypeMap` but it \ | |
54a0048b | 719 | was not. (Ty = {})", |
dfeec247 XL |
720 | type_map.get_unique_type_id_as_string(unique_type_id), |
721 | t | |
722 | ); | |
1a4d82fc JJ |
723 | } |
724 | }; | |
725 | ||
726 | match type_map.find_metadata_for_type(t) { | |
727 | Some(metadata) => { | |
728 | if metadata != metadata_for_uid { | |
dfeec247 XL |
729 | span_bug!( |
730 | usage_site_span, | |
731 | "mismatch between `Ty` and \ | |
60c5eb7d XL |
732 | `UniqueTypeId` maps in \ |
733 | `debuginfo::TypeMap`. \ | |
54a0048b | 734 | UniqueTypeId={}, Ty={}", |
dfeec247 XL |
735 | type_map.get_unique_type_id_as_string(unique_type_id), |
736 | t | |
737 | ); | |
1a4d82fc JJ |
738 | } |
739 | } | |
740 | None => { | |
54a0048b | 741 | type_map.register_type_with_metadata(t, metadata); |
1a4d82fc JJ |
742 | } |
743 | } | |
744 | } else { | |
54a0048b SL |
745 | type_map.register_type_with_metadata(t, metadata); |
746 | type_map.register_unique_id_with_metadata(unique_type_id, metadata); | |
1a4d82fc JJ |
747 | } |
748 | } | |
749 | ||
750 | metadata | |
751 | } | |
752 | ||
ba9703b0 XL |
753 | fn hex_encode(data: &[u8]) -> String { |
754 | let mut hex_string = String::with_capacity(data.len() * 2); | |
755 | for byte in data.iter() { | |
756 | write!(&mut hex_string, "{:02x}", byte).unwrap(); | |
757 | } | |
758 | hex_string | |
759 | } | |
760 | ||
29967ef6 XL |
761 | pub fn file_metadata(cx: &CodegenCx<'ll, '_>, source_file: &SourceFile) -> &'ll DIFile { |
762 | debug!("file_metadata: file_name: {}", source_file.name); | |
7cac9316 | 763 | |
ba9703b0 XL |
764 | let hash = Some(&source_file.src_hash); |
765 | let file_name = Some(source_file.name.to_string()); | |
29967ef6 | 766 | let directory = if source_file.is_real_file() && !source_file.is_imported() { |
dc9dc135 | 767 | Some(cx.sess().working_dir.0.to_string_lossy().to_string()) |
7cac9316 XL |
768 | } else { |
769 | // If the path comes from an upstream crate we assume it has been made | |
770 | // independent of the compiler's working directory one way or another. | |
dc9dc135 XL |
771 | None |
772 | }; | |
ba9703b0 | 773 | file_metadata_raw(cx, file_name, directory, hash) |
e9174d1e SL |
774 | } |
775 | ||
b7449926 | 776 | pub fn unknown_file_metadata(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile { |
ba9703b0 | 777 | file_metadata_raw(cx, None, None, None) |
e9174d1e SL |
778 | } |
779 | ||
dfeec247 XL |
780 | fn file_metadata_raw( |
781 | cx: &CodegenCx<'ll, '_>, | |
782 | file_name: Option<String>, | |
783 | directory: Option<String>, | |
ba9703b0 | 784 | hash: Option<&SourceFileHash>, |
dfeec247 | 785 | ) -> &'ll DIFile { |
dc9dc135 XL |
786 | let key = (file_name, directory); |
787 | ||
788 | match debug_context(cx).created_files.borrow_mut().entry(key) { | |
ba9703b0 | 789 | Entry::Occupied(o) => o.get(), |
dc9dc135 XL |
790 | Entry::Vacant(v) => { |
791 | let (file_name, directory) = v.key(); | |
792 | debug!("file_metadata: file_name: {:?}, directory: {:?}", file_name, directory); | |
793 | ||
74b04a01 XL |
794 | let file_name = file_name.as_deref().unwrap_or("<unknown>"); |
795 | let directory = directory.as_deref().unwrap_or(""); | |
dc9dc135 | 796 | |
ba9703b0 XL |
797 | let (hash_kind, hash_value) = match hash { |
798 | Some(hash) => { | |
799 | let kind = match hash.kind { | |
800 | rustc_span::SourceFileHashAlgorithm::Md5 => llvm::ChecksumKind::MD5, | |
801 | rustc_span::SourceFileHashAlgorithm::Sha1 => llvm::ChecksumKind::SHA1, | |
29967ef6 | 802 | rustc_span::SourceFileHashAlgorithm::Sha256 => llvm::ChecksumKind::SHA256, |
ba9703b0 XL |
803 | }; |
804 | (kind, hex_encode(hash.hash_bytes())) | |
805 | } | |
806 | None => (llvm::ChecksumKind::None, String::new()), | |
807 | }; | |
808 | ||
dc9dc135 | 809 | let file_metadata = unsafe { |
74b04a01 XL |
810 | llvm::LLVMRustDIBuilderCreateFile( |
811 | DIB(cx), | |
812 | file_name.as_ptr().cast(), | |
813 | file_name.len(), | |
814 | directory.as_ptr().cast(), | |
815 | directory.len(), | |
ba9703b0 XL |
816 | hash_kind, |
817 | hash_value.as_ptr().cast(), | |
818 | hash_value.len(), | |
74b04a01 | 819 | ) |
dc9dc135 | 820 | }; |
7cac9316 | 821 | |
dc9dc135 XL |
822 | v.insert(file_metadata); |
823 | file_metadata | |
824 | } | |
e9174d1e | 825 | } |
d9579d0f AL |
826 | } |
827 | ||
f035d41b XL |
828 | trait MsvcBasicName { |
829 | fn msvc_basic_name(self) -> &'static str; | |
830 | } | |
831 | ||
5869c6ff | 832 | impl MsvcBasicName for ty::IntTy { |
f035d41b XL |
833 | fn msvc_basic_name(self) -> &'static str { |
834 | match self { | |
5869c6ff XL |
835 | ty::IntTy::Isize => "ptrdiff_t", |
836 | ty::IntTy::I8 => "__int8", | |
837 | ty::IntTy::I16 => "__int16", | |
838 | ty::IntTy::I32 => "__int32", | |
839 | ty::IntTy::I64 => "__int64", | |
840 | ty::IntTy::I128 => "__int128", | |
f035d41b XL |
841 | } |
842 | } | |
843 | } | |
844 | ||
5869c6ff | 845 | impl MsvcBasicName for ty::UintTy { |
f035d41b XL |
846 | fn msvc_basic_name(self) -> &'static str { |
847 | match self { | |
5869c6ff XL |
848 | ty::UintTy::Usize => "size_t", |
849 | ty::UintTy::U8 => "unsigned __int8", | |
850 | ty::UintTy::U16 => "unsigned __int16", | |
851 | ty::UintTy::U32 => "unsigned __int32", | |
852 | ty::UintTy::U64 => "unsigned __int64", | |
853 | ty::UintTy::U128 => "unsigned __int128", | |
f035d41b XL |
854 | } |
855 | } | |
856 | } | |
857 | ||
5869c6ff | 858 | impl MsvcBasicName for ty::FloatTy { |
f035d41b XL |
859 | fn msvc_basic_name(self) -> &'static str { |
860 | match self { | |
5869c6ff XL |
861 | ty::FloatTy::F32 => "float", |
862 | ty::FloatTy::F64 => "double", | |
f035d41b XL |
863 | } |
864 | } | |
865 | } | |
866 | ||
b7449926 | 867 | fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { |
d9579d0f AL |
868 | debug!("basic_type_metadata: {:?}", t); |
869 | ||
f035d41b XL |
870 | // When targeting MSVC, emit MSVC style type names for compatibility with |
871 | // .natvis visualizers (and perhaps other existing native debuggers?) | |
29967ef6 | 872 | let msvc_like_names = cx.tcx.sess.target.is_like_msvc; |
f035d41b | 873 | |
1b1a35ee | 874 | let (name, encoding) = match t.kind() { |
b7449926 | 875 | ty::Never => ("!", DW_ATE_unsigned), |
dfeec247 | 876 | ty::Tuple(ref elements) if elements.is_empty() => ("()", DW_ATE_unsigned), |
b7449926 XL |
877 | ty::Bool => ("bool", DW_ATE_boolean), |
878 | ty::Char => ("char", DW_ATE_unsigned_char), | |
f035d41b XL |
879 | ty::Int(int_ty) if msvc_like_names => (int_ty.msvc_basic_name(), DW_ATE_signed), |
880 | ty::Uint(uint_ty) if msvc_like_names => (uint_ty.msvc_basic_name(), DW_ATE_unsigned), | |
881 | ty::Float(float_ty) if msvc_like_names => (float_ty.msvc_basic_name(), DW_ATE_float), | |
dfeec247 XL |
882 | ty::Int(int_ty) => (int_ty.name_str(), DW_ATE_signed), |
883 | ty::Uint(uint_ty) => (uint_ty.name_str(), DW_ATE_unsigned), | |
884 | ty::Float(float_ty) => (float_ty.name_str(), DW_ATE_float), | |
885 | _ => bug!("debuginfo::basic_type_metadata - `t` is invalid type"), | |
d9579d0f AL |
886 | }; |
887 | ||
d9579d0f | 888 | let ty_metadata = unsafe { |
5bcae85e | 889 | llvm::LLVMRustDIBuilderCreateBasicType( |
d9579d0f | 890 | DIB(cx), |
74b04a01 XL |
891 | name.as_ptr().cast(), |
892 | name.len(), | |
f9f354fc | 893 | cx.size_of(t).bits(), |
dfeec247 XL |
894 | encoding, |
895 | ) | |
d9579d0f AL |
896 | }; |
897 | ||
f035d41b XL |
898 | if !msvc_like_names { |
899 | return ty_metadata; | |
900 | } | |
901 | ||
1b1a35ee | 902 | let typedef_name = match t.kind() { |
f035d41b XL |
903 | ty::Int(int_ty) => int_ty.name_str(), |
904 | ty::Uint(uint_ty) => uint_ty.name_str(), | |
905 | ty::Float(float_ty) => float_ty.name_str(), | |
906 | _ => return ty_metadata, | |
907 | }; | |
908 | ||
909 | let typedef_metadata = unsafe { | |
910 | llvm::LLVMRustDIBuilderCreateTypedef( | |
911 | DIB(cx), | |
912 | ty_metadata, | |
913 | typedef_name.as_ptr().cast(), | |
914 | typedef_name.len(), | |
915 | unknown_file_metadata(cx), | |
916 | 0, | |
917 | None, | |
918 | ) | |
919 | }; | |
920 | ||
921 | typedef_metadata | |
d9579d0f AL |
922 | } |
923 | ||
b7449926 XL |
924 | fn foreign_type_metadata( |
925 | cx: &CodegenCx<'ll, 'tcx>, | |
926 | t: Ty<'tcx>, | |
927 | unique_type_id: UniqueTypeId, | |
928 | ) -> &'ll DIType { | |
abe05a73 XL |
929 | debug!("foreign_type_metadata: {:?}", t); |
930 | ||
48663c56 | 931 | let name = compute_debuginfo_type_name(cx.tcx, t, false); |
f035d41b | 932 | create_struct_stub(cx, t, &name, unique_type_id, NO_SCOPE_METADATA, DIFlags::FlagZero) |
abe05a73 XL |
933 | } |
934 | ||
b7449926 XL |
935 | fn pointer_type_metadata( |
936 | cx: &CodegenCx<'ll, 'tcx>, | |
937 | pointer_type: Ty<'tcx>, | |
938 | pointee_type_metadata: &'ll DIType, | |
939 | ) -> &'ll DIType { | |
ff7c6d11 | 940 | let (pointer_size, pointer_align) = cx.size_and_align_of(pointer_type); |
48663c56 | 941 | let name = compute_debuginfo_type_name(cx.tcx, pointer_type, false); |
ff7c6d11 | 942 | unsafe { |
5bcae85e | 943 | llvm::LLVMRustDIBuilderCreatePointerType( |
d9579d0f AL |
944 | DIB(cx), |
945 | pointee_type_metadata, | |
ff7c6d11 | 946 | pointer_size.bits(), |
a1dfa0c6 | 947 | pointer_align.bits() as u32, |
74b04a01 XL |
948 | 0, // Ignore DWARF address space. |
949 | name.as_ptr().cast(), | |
950 | name.len(), | |
dfeec247 | 951 | ) |
ff7c6d11 | 952 | } |
d9579d0f AL |
953 | } |
954 | ||
3dfed10e XL |
955 | fn param_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { |
956 | debug!("param_type_metadata: {:?}", t); | |
957 | let name = format!("{:?}", t); | |
958 | unsafe { | |
959 | llvm::LLVMRustDIBuilderCreateBasicType( | |
960 | DIB(cx), | |
961 | name.as_ptr().cast(), | |
962 | name.len(), | |
963 | Size::ZERO.bits(), | |
964 | DW_ATE_unsigned, | |
965 | ) | |
966 | } | |
967 | } | |
968 | ||
dc9dc135 XL |
969 | pub fn compile_unit_metadata( |
970 | tcx: TyCtxt<'_>, | |
971 | codegen_unit_name: &str, | |
972 | debug_context: &CrateDebugContext<'ll, '_>, | |
973 | ) -> &'ll DIDescriptor { | |
2c00a5a8 | 974 | let mut name_in_debuginfo = match tcx.sess.local_crate_source_file { |
7cac9316 | 975 | Some(ref path) => path.clone(), |
2c00a5a8 | 976 | None => PathBuf::from(&*tcx.crate_name(LOCAL_CRATE).as_str()), |
d9579d0f AL |
977 | }; |
978 | ||
7cac9316 | 979 | // The OSX linker has an idiosyncrasy where it will ignore some debuginfo |
60c5eb7d | 980 | // if multiple object files with the same `DW_AT_name` are linked together. |
7cac9316 | 981 | // As a workaround we generate unique names for each object file. Those do |
6a06907d | 982 | // not correspond to an actual source file but that is harmless. |
29967ef6 | 983 | if tcx.sess.target.is_like_osx { |
ff7c6d11 XL |
984 | name_in_debuginfo.push("@"); |
985 | name_in_debuginfo.push(codegen_unit_name); | |
7cac9316 XL |
986 | } |
987 | ||
988 | debug!("compile_unit_metadata: {:?}", name_in_debuginfo); | |
dfeec247 XL |
989 | let rustc_producer = |
990 | format!("rustc version {}", option_env!("CFG_VERSION").expect("CFG_VERSION"),); | |
cc61c64b | 991 | // FIXME(#41252) Remove "clang LLVM" if we can get GDB and LLVM to play nice. |
416331ca | 992 | let producer = format!("clang LLVM ({})", rustc_producer); |
d9579d0f | 993 | |
b7449926 | 994 | let name_in_debuginfo = name_in_debuginfo.to_string_lossy(); |
6a06907d | 995 | let work_dir = tcx.sess.working_dir.0.to_string_lossy(); |
d9579d0f | 996 | let flags = "\0"; |
fc512014 | 997 | let out_dir = &tcx.output_filenames(LOCAL_CRATE).out_directory; |
5869c6ff XL |
998 | let split_name = if tcx.sess.target_can_use_split_dwarf() { |
999 | tcx.output_filenames(LOCAL_CRATE) | |
6a06907d XL |
1000 | .split_dwarf_path(tcx.sess.split_debuginfo(), Some(codegen_unit_name)) |
1001 | .map(|f| out_dir.join(f)) | |
5869c6ff XL |
1002 | } else { |
1003 | None | |
1004 | } | |
1005 | .unwrap_or_default(); | |
fc512014 | 1006 | let split_name = split_name.to_str().unwrap(); |
48663c56 XL |
1007 | |
1008 | // FIXME(#60020): | |
1009 | // | |
1010 | // This should actually be | |
1011 | // | |
60c5eb7d | 1012 | // let kind = DebugEmissionKind::from_generic(tcx.sess.opts.debuginfo); |
48663c56 | 1013 | // |
60c5eb7d | 1014 | // That is, we should set LLVM's emission kind to `LineTablesOnly` if |
48663c56 XL |
1015 | // we are compiling with "limited" debuginfo. However, some of the |
1016 | // existing tools relied on slightly more debuginfo being generated than | |
1017 | // would be the case with `LineTablesOnly`, and we did not want to break | |
1018 | // these tools in a "drive-by fix", without a good idea or plan about | |
1019 | // what limited debuginfo should exactly look like. So for now we keep | |
1020 | // the emission kind as `FullDebug`. | |
1021 | // | |
1022 | // See https://github.com/rust-lang/rust/issues/60020 for details. | |
1023 | let kind = DebugEmissionKind::FullDebug; | |
1024 | assert!(tcx.sess.opts.debuginfo != DebugInfo::None); | |
8bb4bdeb XL |
1025 | |
1026 | unsafe { | |
6a06907d | 1027 | let compile_unit_file = llvm::LLVMRustDIBuilderCreateFile( |
dfeec247 | 1028 | debug_context.builder, |
74b04a01 XL |
1029 | name_in_debuginfo.as_ptr().cast(), |
1030 | name_in_debuginfo.len(), | |
6a06907d XL |
1031 | work_dir.as_ptr().cast(), |
1032 | work_dir.len(), | |
ba9703b0 XL |
1033 | llvm::ChecksumKind::None, |
1034 | ptr::null(), | |
1035 | 0, | |
dfeec247 | 1036 | ); |
8bb4bdeb | 1037 | |
041b39d2 | 1038 | let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit( |
5bcae85e | 1039 | debug_context.builder, |
d9579d0f | 1040 | DW_LANG_RUST, |
6a06907d | 1041 | compile_unit_file, |
74b04a01 XL |
1042 | producer.as_ptr().cast(), |
1043 | producer.len(), | |
2c00a5a8 | 1044 | tcx.sess.opts.optimize != config::OptLevel::No, |
e74abb32 | 1045 | flags.as_ptr().cast(), |
d9579d0f | 1046 | 0, |
6a06907d XL |
1047 | // NB: this doesn't actually have any perceptible effect, it seems. LLVM will instead |
1048 | // put the path supplied to `MCSplitDwarfFile` into the debug info of the final | |
1049 | // output(s). | |
e74abb32 | 1050 | split_name.as_ptr().cast(), |
74b04a01 | 1051 | split_name.len(), |
dfeec247 | 1052 | kind, |
fc512014 XL |
1053 | 0, |
1054 | tcx.sess.opts.debugging_opts.split_dwarf_inlining, | |
dfeec247 | 1055 | ); |
041b39d2 | 1056 | |
2c00a5a8 | 1057 | if tcx.sess.opts.debugging_opts.profile { |
dfeec247 XL |
1058 | let cu_desc_metadata = |
1059 | llvm::LLVMRustMetadataAsValue(debug_context.llcontext, unit_metadata); | |
f9f354fc XL |
1060 | let default_gcda_path = &tcx.output_filenames(LOCAL_CRATE).with_extension("gcda"); |
1061 | let gcda_path = | |
1062 | tcx.sess.opts.debugging_opts.profile_emit.as_ref().unwrap_or(default_gcda_path); | |
041b39d2 XL |
1063 | |
1064 | let gcov_cu_info = [ | |
dfeec247 XL |
1065 | path_to_mdstring( |
1066 | debug_context.llcontext, | |
1067 | &tcx.output_filenames(LOCAL_CRATE).with_extension("gcno"), | |
1068 | ), | |
f9f354fc | 1069 | path_to_mdstring(debug_context.llcontext, &gcda_path), |
041b39d2 XL |
1070 | cu_desc_metadata, |
1071 | ]; | |
dfeec247 XL |
1072 | let gcov_metadata = llvm::LLVMMDNodeInContext( |
1073 | debug_context.llcontext, | |
1074 | gcov_cu_info.as_ptr(), | |
1075 | gcov_cu_info.len() as c_uint, | |
1076 | ); | |
041b39d2 | 1077 | |
6a06907d | 1078 | let llvm_gcov_ident = cstr!("llvm.gcov"); |
dfeec247 XL |
1079 | llvm::LLVMAddNamedMetadataOperand( |
1080 | debug_context.llmod, | |
1081 | llvm_gcov_ident.as_ptr(), | |
1082 | gcov_metadata, | |
1083 | ); | |
041b39d2 XL |
1084 | } |
1085 | ||
416331ca XL |
1086 | // Insert `llvm.ident` metadata on the wasm32 targets since that will |
1087 | // get hooked up to the "producer" sections `processed-by` information. | |
1088 | if tcx.sess.opts.target_triple.triple().starts_with("wasm32") { | |
1089 | let name_metadata = llvm::LLVMMDStringInContext( | |
1090 | debug_context.llcontext, | |
e74abb32 | 1091 | rustc_producer.as_ptr().cast(), |
416331ca XL |
1092 | rustc_producer.as_bytes().len() as c_uint, |
1093 | ); | |
1094 | llvm::LLVMAddNamedMetadataOperand( | |
1095 | debug_context.llmod, | |
6a06907d | 1096 | cstr!("llvm.ident").as_ptr(), |
416331ca XL |
1097 | llvm::LLVMMDNodeInContext(debug_context.llcontext, &name_metadata, 1), |
1098 | ); | |
1099 | } | |
1100 | ||
041b39d2 | 1101 | return unit_metadata; |
d9579d0f | 1102 | }; |
041b39d2 | 1103 | |
b7449926 | 1104 | fn path_to_mdstring(llcx: &'ll llvm::Context, path: &Path) -> &'ll Value { |
a1dfa0c6 | 1105 | let path_str = path_to_c_string(path); |
041b39d2 | 1106 | unsafe { |
dfeec247 XL |
1107 | llvm::LLVMMDStringInContext( |
1108 | llcx, | |
1109 | path_str.as_ptr(), | |
1110 | path_str.as_bytes().len() as c_uint, | |
1111 | ) | |
041b39d2 XL |
1112 | } |
1113 | } | |
d9579d0f AL |
1114 | } |
1115 | ||
b7449926 XL |
1116 | struct MetadataCreationResult<'ll> { |
1117 | metadata: &'ll DIType, | |
dfeec247 | 1118 | already_stored_in_typemap: bool, |
1a4d82fc JJ |
1119 | } |
1120 | ||
b7449926 XL |
1121 | impl MetadataCreationResult<'ll> { |
1122 | fn new(metadata: &'ll DIType, already_stored_in_typemap: bool) -> Self { | |
dfeec247 | 1123 | MetadataCreationResult { metadata, already_stored_in_typemap } |
1a4d82fc JJ |
1124 | } |
1125 | } | |
1126 | ||
f035d41b XL |
1127 | #[derive(Debug)] |
1128 | struct SourceInfo<'ll> { | |
1129 | file: &'ll DIFile, | |
1130 | line: u32, | |
1131 | } | |
1132 | ||
60c5eb7d XL |
1133 | /// Description of a type member, which can either be a regular field (as in |
1134 | /// structs or tuples) or an enum variant. | |
d9579d0f | 1135 | #[derive(Debug)] |
b7449926 | 1136 | struct MemberDescription<'ll> { |
d9579d0f | 1137 | name: String, |
b7449926 | 1138 | type_metadata: &'ll DIType, |
ff7c6d11 XL |
1139 | offset: Size, |
1140 | size: Size, | |
1141 | align: Align, | |
476ff2be | 1142 | flags: DIFlags, |
a1dfa0c6 | 1143 | discriminant: Option<u64>, |
f035d41b | 1144 | source_info: Option<SourceInfo<'ll>>, |
d9579d0f AL |
1145 | } |
1146 | ||
48663c56 | 1147 | impl<'ll> MemberDescription<'ll> { |
dfeec247 XL |
1148 | fn into_metadata( |
1149 | self, | |
1150 | cx: &CodegenCx<'ll, '_>, | |
1151 | composite_type_metadata: &'ll DIScope, | |
1152 | ) -> &'ll DIType { | |
f035d41b XL |
1153 | let (file, line) = self |
1154 | .source_info | |
1155 | .map(|info| (info.file, info.line)) | |
1156 | .unwrap_or_else(|| (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)); | |
48663c56 XL |
1157 | unsafe { |
1158 | llvm::LLVMRustDIBuilderCreateVariantMemberType( | |
1159 | DIB(cx), | |
1160 | composite_type_metadata, | |
74b04a01 XL |
1161 | self.name.as_ptr().cast(), |
1162 | self.name.len(), | |
f035d41b XL |
1163 | file, |
1164 | line, | |
48663c56 XL |
1165 | self.size.bits(), |
1166 | self.align.bits() as u32, | |
1167 | self.offset.bits(), | |
fc512014 | 1168 | self.discriminant.map(|v| cx.const_u64(v)), |
48663c56 | 1169 | self.flags, |
dfeec247 XL |
1170 | self.type_metadata, |
1171 | ) | |
48663c56 XL |
1172 | } |
1173 | } | |
1174 | } | |
1175 | ||
60c5eb7d XL |
1176 | /// A factory for `MemberDescription`s. It produces a list of member descriptions |
1177 | /// for some record-like type. `MemberDescriptionFactory`s are used to defer the | |
1178 | /// creation of type member descriptions in order to break cycles arising from | |
1179 | /// recursive type definitions. | |
b7449926 | 1180 | enum MemberDescriptionFactory<'ll, 'tcx> { |
d9579d0f AL |
1181 | StructMDF(StructMemberDescriptionFactory<'tcx>), |
1182 | TupleMDF(TupleMemberDescriptionFactory<'tcx>), | |
b7449926 | 1183 | EnumMDF(EnumMemberDescriptionFactory<'ll, 'tcx>), |
9e0c209e | 1184 | UnionMDF(UnionMemberDescriptionFactory<'tcx>), |
dfeec247 | 1185 | VariantMDF(VariantMemberDescriptionFactory<'ll, 'tcx>), |
d9579d0f AL |
1186 | } |
1187 | ||
b7449926 | 1188 | impl MemberDescriptionFactory<'ll, 'tcx> { |
dfeec247 | 1189 | fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDescription<'ll>> { |
d9579d0f | 1190 | match *self { |
dfeec247 XL |
1191 | StructMDF(ref this) => this.create_member_descriptions(cx), |
1192 | TupleMDF(ref this) => this.create_member_descriptions(cx), | |
1193 | EnumMDF(ref this) => this.create_member_descriptions(cx), | |
1194 | UnionMDF(ref this) => this.create_member_descriptions(cx), | |
1195 | VariantMDF(ref this) => this.create_member_descriptions(cx), | |
d9579d0f AL |
1196 | } |
1197 | } | |
1198 | } | |
1199 | ||
1200 | //=----------------------------------------------------------------------------- | |
1201 | // Structs | |
1202 | //=----------------------------------------------------------------------------- | |
1203 | ||
60c5eb7d | 1204 | /// Creates `MemberDescription`s for the fields of a struct. |
d9579d0f | 1205 | struct StructMemberDescriptionFactory<'tcx> { |
476ff2be SL |
1206 | ty: Ty<'tcx>, |
1207 | variant: &'tcx ty::VariantDef, | |
d9579d0f AL |
1208 | span: Span, |
1209 | } | |
1210 | ||
1211 | impl<'tcx> StructMemberDescriptionFactory<'tcx> { | |
dfeec247 | 1212 | fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDescription<'ll>> { |
476ff2be | 1213 | let layout = cx.layout_of(self.ty); |
dfeec247 XL |
1214 | self.variant |
1215 | .fields | |
1216 | .iter() | |
1217 | .enumerate() | |
1218 | .map(|(i, f)| { | |
1219 | let name = if self.variant.ctor_kind == CtorKind::Fn { | |
1220 | format!("__{}", i) | |
1221 | } else { | |
1222 | f.ident.to_string() | |
1223 | }; | |
1224 | let field = layout.field(cx, i); | |
1225 | MemberDescription { | |
1226 | name, | |
1227 | type_metadata: type_metadata(cx, field.ty, self.span), | |
1228 | offset: layout.fields.offset(i), | |
1229 | size: field.size, | |
1230 | align: field.align.abi, | |
1231 | flags: DIFlags::FlagZero, | |
1232 | discriminant: None, | |
f035d41b | 1233 | source_info: None, |
dfeec247 XL |
1234 | } |
1235 | }) | |
1236 | .collect() | |
1a4d82fc JJ |
1237 | } |
1238 | } | |
1239 | ||
b7449926 XL |
1240 | fn prepare_struct_metadata( |
1241 | cx: &CodegenCx<'ll, 'tcx>, | |
1242 | struct_type: Ty<'tcx>, | |
1243 | unique_type_id: UniqueTypeId, | |
1244 | span: Span, | |
1245 | ) -> RecursiveTypeDescription<'ll, 'tcx> { | |
48663c56 | 1246 | let struct_name = compute_debuginfo_type_name(cx.tcx, struct_type, false); |
d9579d0f | 1247 | |
1b1a35ee | 1248 | let (struct_def_id, variant) = match struct_type.kind() { |
b7449926 | 1249 | ty::Adt(def, _) => (def.did, def.non_enum_variant()), |
dfeec247 | 1250 | _ => bug!("prepare_struct_metadata on a non-ADT"), |
e9174d1e SL |
1251 | }; |
1252 | ||
041b39d2 | 1253 | let containing_scope = get_namespace_for_item(cx, struct_def_id); |
1a4d82fc | 1254 | |
f035d41b XL |
1255 | let struct_metadata_stub = create_struct_stub( |
1256 | cx, | |
1257 | struct_type, | |
1258 | &struct_name, | |
1259 | unique_type_id, | |
1260 | Some(containing_scope), | |
1261 | DIFlags::FlagZero, | |
1262 | ); | |
85aaf69f | 1263 | |
d9579d0f AL |
1264 | create_and_register_recursive_type_forward_declaration( |
1265 | cx, | |
1266 | struct_type, | |
1267 | unique_type_id, | |
1268 | struct_metadata_stub, | |
a1dfa0c6 | 1269 | struct_metadata_stub, |
dfeec247 | 1270 | StructMDF(StructMemberDescriptionFactory { ty: struct_type, variant, span }), |
d9579d0f | 1271 | ) |
1a4d82fc JJ |
1272 | } |
1273 | ||
1274 | //=----------------------------------------------------------------------------- | |
d9579d0f | 1275 | // Tuples |
1a4d82fc JJ |
1276 | //=----------------------------------------------------------------------------- |
1277 | ||
60c5eb7d | 1278 | /// Creates `MemberDescription`s for the fields of a tuple. |
d9579d0f | 1279 | struct TupleMemberDescriptionFactory<'tcx> { |
476ff2be | 1280 | ty: Ty<'tcx>, |
d9579d0f AL |
1281 | component_types: Vec<Ty<'tcx>>, |
1282 | span: Span, | |
1a4d82fc JJ |
1283 | } |
1284 | ||
d9579d0f | 1285 | impl<'tcx> TupleMemberDescriptionFactory<'tcx> { |
dfeec247 | 1286 | fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDescription<'ll>> { |
476ff2be | 1287 | let layout = cx.layout_of(self.ty); |
dfeec247 XL |
1288 | self.component_types |
1289 | .iter() | |
1290 | .enumerate() | |
1291 | .map(|(i, &component_type)| { | |
1292 | let (size, align) = cx.size_and_align_of(component_type); | |
1293 | MemberDescription { | |
1294 | name: format!("__{}", i), | |
1295 | type_metadata: type_metadata(cx, component_type, self.span), | |
1296 | offset: layout.fields.offset(i), | |
1297 | size, | |
1298 | align, | |
1299 | flags: DIFlags::FlagZero, | |
1300 | discriminant: None, | |
f035d41b | 1301 | source_info: None, |
dfeec247 XL |
1302 | } |
1303 | }) | |
1304 | .collect() | |
d9579d0f | 1305 | } |
1a4d82fc JJ |
1306 | } |
1307 | ||
b7449926 XL |
1308 | fn prepare_tuple_metadata( |
1309 | cx: &CodegenCx<'ll, 'tcx>, | |
1310 | tuple_type: Ty<'tcx>, | |
1311 | component_types: &[Ty<'tcx>], | |
1312 | unique_type_id: UniqueTypeId, | |
1313 | span: Span, | |
416331ca | 1314 | containing_scope: Option<&'ll DIScope>, |
b7449926 | 1315 | ) -> RecursiveTypeDescription<'ll, 'tcx> { |
48663c56 | 1316 | let tuple_name = compute_debuginfo_type_name(cx.tcx, tuple_type, false); |
1a4d82fc | 1317 | |
f035d41b XL |
1318 | let struct_stub = create_struct_stub( |
1319 | cx, | |
1320 | tuple_type, | |
1321 | &tuple_name[..], | |
1322 | unique_type_id, | |
1323 | containing_scope, | |
1324 | DIFlags::FlagZero, | |
1325 | ); | |
a1dfa0c6 | 1326 | |
d9579d0f AL |
1327 | create_and_register_recursive_type_forward_declaration( |
1328 | cx, | |
1329 | tuple_type, | |
1330 | unique_type_id, | |
a1dfa0c6 XL |
1331 | struct_stub, |
1332 | struct_stub, | |
d9579d0f | 1333 | TupleMDF(TupleMemberDescriptionFactory { |
476ff2be | 1334 | ty: tuple_type, |
d9579d0f | 1335 | component_types: component_types.to_vec(), |
3b2f2976 | 1336 | span, |
dfeec247 | 1337 | }), |
d9579d0f | 1338 | ) |
1a4d82fc JJ |
1339 | } |
1340 | ||
9e0c209e SL |
1341 | //=----------------------------------------------------------------------------- |
1342 | // Unions | |
1343 | //=----------------------------------------------------------------------------- | |
1344 | ||
1345 | struct UnionMemberDescriptionFactory<'tcx> { | |
ba9703b0 | 1346 | layout: TyAndLayout<'tcx>, |
476ff2be | 1347 | variant: &'tcx ty::VariantDef, |
9e0c209e SL |
1348 | span: Span, |
1349 | } | |
1350 | ||
1351 | impl<'tcx> UnionMemberDescriptionFactory<'tcx> { | |
dfeec247 XL |
1352 | fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDescription<'ll>> { |
1353 | self.variant | |
1354 | .fields | |
1355 | .iter() | |
1356 | .enumerate() | |
1357 | .map(|(i, f)| { | |
1358 | let field = self.layout.field(cx, i); | |
1359 | MemberDescription { | |
1360 | name: f.ident.to_string(), | |
1361 | type_metadata: type_metadata(cx, field.ty, self.span), | |
1362 | offset: Size::ZERO, | |
1363 | size: field.size, | |
1364 | align: field.align.abi, | |
1365 | flags: DIFlags::FlagZero, | |
1366 | discriminant: None, | |
f035d41b | 1367 | source_info: None, |
dfeec247 XL |
1368 | } |
1369 | }) | |
1370 | .collect() | |
9e0c209e SL |
1371 | } |
1372 | } | |
1373 | ||
b7449926 XL |
1374 | fn prepare_union_metadata( |
1375 | cx: &CodegenCx<'ll, 'tcx>, | |
1376 | union_type: Ty<'tcx>, | |
1377 | unique_type_id: UniqueTypeId, | |
1378 | span: Span, | |
1379 | ) -> RecursiveTypeDescription<'ll, 'tcx> { | |
48663c56 | 1380 | let union_name = compute_debuginfo_type_name(cx.tcx, union_type, false); |
9e0c209e | 1381 | |
1b1a35ee | 1382 | let (union_def_id, variant) = match union_type.kind() { |
b7449926 | 1383 | ty::Adt(def, _) => (def.did, def.non_enum_variant()), |
dfeec247 | 1384 | _ => bug!("prepare_union_metadata on a non-ADT"), |
9e0c209e SL |
1385 | }; |
1386 | ||
041b39d2 | 1387 | let containing_scope = get_namespace_for_item(cx, union_def_id); |
9e0c209e | 1388 | |
dfeec247 XL |
1389 | let union_metadata_stub = |
1390 | create_union_stub(cx, union_type, &union_name, unique_type_id, containing_scope); | |
9e0c209e SL |
1391 | |
1392 | create_and_register_recursive_type_forward_declaration( | |
1393 | cx, | |
1394 | union_type, | |
1395 | unique_type_id, | |
1396 | union_metadata_stub, | |
a1dfa0c6 | 1397 | union_metadata_stub, |
dfeec247 | 1398 | UnionMDF(UnionMemberDescriptionFactory { layout: cx.layout_of(union_type), variant, span }), |
9e0c209e SL |
1399 | ) |
1400 | } | |
1a4d82fc | 1401 | |
d9579d0f AL |
1402 | //=----------------------------------------------------------------------------- |
1403 | // Enums | |
1404 | //=----------------------------------------------------------------------------- | |
1a4d82fc | 1405 | |
ba9703b0 XL |
1406 | /// DWARF variant support is only available starting in LLVM 8, but |
1407 | /// on MSVC we have to use the fallback mode, because LLVM doesn't | |
1408 | /// lower variant parts to PDB. | |
9fa01778 | 1409 | fn use_enum_fallback(cx: &CodegenCx<'_, '_>) -> bool { |
29967ef6 | 1410 | cx.sess().target.is_like_msvc |
a1dfa0c6 XL |
1411 | } |
1412 | ||
60c5eb7d XL |
1413 | // FIXME(eddyb) maybe precompute this? Right now it's computed once |
1414 | // per generator monomorphization, but it doesn't depend on substs. | |
1415 | fn generator_layout_and_saved_local_names( | |
1416 | tcx: TyCtxt<'tcx>, | |
1417 | def_id: DefId, | |
f9f354fc | 1418 | ) -> (&'tcx GeneratorLayout<'tcx>, IndexVec<mir::GeneratorSavedLocal, Option<Symbol>>) { |
60c5eb7d | 1419 | let body = tcx.optimized_mir(def_id); |
6a06907d | 1420 | let generator_layout = body.generator_layout().unwrap(); |
dfeec247 | 1421 | let mut generator_saved_local_names = IndexVec::from_elem(None, &generator_layout.field_tys); |
60c5eb7d | 1422 | |
dfeec247 | 1423 | let state_arg = mir::Local::new(1); |
60c5eb7d | 1424 | for var in &body.var_debug_info { |
fc512014 XL |
1425 | let place = if let mir::VarDebugInfoContents::Place(p) = var.value { p } else { continue }; |
1426 | if place.local != state_arg { | |
60c5eb7d XL |
1427 | continue; |
1428 | } | |
fc512014 | 1429 | match place.projection[..] { |
60c5eb7d XL |
1430 | [ |
1431 | // Deref of the `Pin<&mut Self>` state argument. | |
1432 | mir::ProjectionElem::Field(..), | |
1433 | mir::ProjectionElem::Deref, | |
1434 | ||
1435 | // Field of a variant of the state. | |
1436 | mir::ProjectionElem::Downcast(_, variant), | |
1437 | mir::ProjectionElem::Field(field, _), | |
1438 | ] => { | |
1439 | let name = &mut generator_saved_local_names[ | |
1440 | generator_layout.variant_fields[variant][field] | |
1441 | ]; | |
1442 | if name.is_none() { | |
1443 | name.replace(var.name); | |
1444 | } | |
1445 | } | |
1446 | _ => {} | |
1447 | } | |
1448 | } | |
1449 | (generator_layout, generator_saved_local_names) | |
1450 | } | |
1451 | ||
1452 | /// Describes the members of an enum value; an enum is described as a union of | |
1453 | /// structs in DWARF. This `MemberDescriptionFactory` provides the description for | |
1454 | /// the members of this union; so for every variant of the given enum, this | |
1455 | /// factory will produce one `MemberDescription` (all with no name and a fixed | |
1456 | /// offset of zero bytes). | |
b7449926 | 1457 | struct EnumMemberDescriptionFactory<'ll, 'tcx> { |
d9579d0f | 1458 | enum_type: Ty<'tcx>, |
ba9703b0 | 1459 | layout: TyAndLayout<'tcx>, |
f035d41b | 1460 | tag_type_metadata: Option<&'ll DIType>, |
b7449926 | 1461 | containing_scope: &'ll DIScope, |
d9579d0f | 1462 | span: Span, |
1a4d82fc JJ |
1463 | } |
1464 | ||
b7449926 | 1465 | impl EnumMemberDescriptionFactory<'ll, 'tcx> { |
dfeec247 | 1466 | fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDescription<'ll>> { |
1b1a35ee | 1467 | let generator_variant_info_data = match *self.enum_type.kind() { |
60c5eb7d XL |
1468 | ty::Generator(def_id, ..) => { |
1469 | Some(generator_layout_and_saved_local_names(cx.tcx, def_id)) | |
1470 | } | |
1471 | _ => None, | |
1472 | }; | |
1473 | ||
1b1a35ee | 1474 | let variant_info_for = |index: VariantIdx| match *self.enum_type.kind() { |
dfeec247 | 1475 | ty::Adt(adt, _) => VariantInfo::Adt(&adt.variants[index]), |
f035d41b | 1476 | ty::Generator(def_id, _, _) => { |
dfeec247 XL |
1477 | let (generator_layout, generator_saved_local_names) = |
1478 | generator_variant_info_data.as_ref().unwrap(); | |
1479 | VariantInfo::Generator { | |
f035d41b | 1480 | def_id, |
dfeec247 XL |
1481 | generator_layout: *generator_layout, |
1482 | generator_saved_local_names, | |
1483 | variant_index: index, | |
48663c56 | 1484 | } |
48663c56 | 1485 | } |
dfeec247 | 1486 | _ => bug!(), |
48663c56 | 1487 | }; |
a1dfa0c6 XL |
1488 | |
1489 | // This will always find the metadata in the type map. | |
1490 | let fallback = use_enum_fallback(cx); | |
1491 | let self_metadata = if fallback { | |
1492 | self.containing_scope | |
1493 | } else { | |
1494 | type_metadata(cx, self.enum_type, self.span) | |
1495 | }; | |
1b1a35ee | 1496 | let flags = match self.enum_type.kind() { |
f035d41b XL |
1497 | ty::Generator(..) => DIFlags::FlagArtificial, |
1498 | _ => DIFlags::FlagZero, | |
1499 | }; | |
a1dfa0c6 | 1500 | |
ff7c6d11 | 1501 | match self.layout.variants { |
ba9703b0 | 1502 | Variants::Single { index } => { |
1b1a35ee | 1503 | if let ty::Adt(adt, _) = self.enum_type.kind() { |
48663c56 XL |
1504 | if adt.variants.is_empty() { |
1505 | return vec![]; | |
1506 | } | |
1507 | } | |
1508 | ||
1509 | let variant_info = variant_info_for(index); | |
dfeec247 XL |
1510 | let (variant_type_metadata, member_description_factory) = describe_enum_variant( |
1511 | cx, | |
1512 | self.layout, | |
1513 | variant_info, | |
f035d41b | 1514 | NoTag, |
dfeec247 XL |
1515 | self_metadata, |
1516 | self.span, | |
1517 | ); | |
1518 | ||
1519 | let member_descriptions = member_description_factory.create_member_descriptions(cx); | |
1520 | ||
1521 | set_members_of_composite_type( | |
1522 | cx, | |
1523 | self.enum_type, | |
1524 | variant_type_metadata, | |
1525 | member_descriptions, | |
1526 | ); | |
1527 | vec![MemberDescription { | |
1528 | name: if fallback { String::new() } else { variant_info.variant_name() }, | |
1529 | type_metadata: variant_type_metadata, | |
1530 | offset: Size::ZERO, | |
1531 | size: self.layout.size, | |
1532 | align: self.layout.align.abi, | |
f035d41b | 1533 | flags, |
dfeec247 | 1534 | discriminant: None, |
f035d41b | 1535 | source_info: variant_info.source_info(cx), |
dfeec247 | 1536 | }] |
ff7c6d11 | 1537 | } |
ba9703b0 | 1538 | Variants::Multiple { |
f035d41b XL |
1539 | tag_encoding: TagEncoding::Direct, |
1540 | tag_field, | |
532ac7d7 XL |
1541 | ref variants, |
1542 | .. | |
1543 | } => { | |
f035d41b XL |
1544 | let tag_info = if fallback { |
1545 | RegularTag { | |
1546 | tag_field: Field::from(tag_field), | |
1547 | tag_type_metadata: self.tag_type_metadata.unwrap(), | |
48663c56 | 1548 | } |
a1dfa0c6 XL |
1549 | } else { |
1550 | // This doesn't matter in this case. | |
f035d41b | 1551 | NoTag |
a1dfa0c6 | 1552 | }; |
dfeec247 XL |
1553 | variants |
1554 | .iter_enumerated() | |
1555 | .map(|(i, _)| { | |
1556 | let variant = self.layout.for_variant(cx, i); | |
1557 | let variant_info = variant_info_for(i); | |
1558 | let (variant_type_metadata, member_desc_factory) = describe_enum_variant( | |
1559 | cx, | |
1560 | variant, | |
1561 | variant_info, | |
f035d41b | 1562 | tag_info, |
dfeec247 XL |
1563 | self_metadata, |
1564 | self.span, | |
1565 | ); | |
1566 | ||
1567 | let member_descriptions = | |
1568 | member_desc_factory.create_member_descriptions(cx); | |
1569 | ||
1570 | set_members_of_composite_type( | |
1571 | cx, | |
1572 | self.enum_type, | |
1573 | variant_type_metadata, | |
1574 | member_descriptions, | |
1575 | ); | |
1576 | ||
1577 | MemberDescription { | |
1578 | name: if fallback { | |
1579 | String::new() | |
1580 | } else { | |
1581 | variant_info.variant_name() | |
1582 | }, | |
1583 | type_metadata: variant_type_metadata, | |
1584 | offset: Size::ZERO, | |
1585 | size: self.layout.size, | |
1586 | align: self.layout.align.abi, | |
f035d41b | 1587 | flags, |
dfeec247 XL |
1588 | discriminant: Some( |
1589 | self.layout.ty.discriminant_for_variant(cx.tcx, i).unwrap().val | |
1590 | as u64, | |
1591 | ), | |
f035d41b | 1592 | source_info: variant_info.source_info(cx), |
dfeec247 XL |
1593 | } |
1594 | }) | |
1595 | .collect() | |
ff7c6d11 | 1596 | } |
ba9703b0 | 1597 | Variants::Multiple { |
f035d41b XL |
1598 | tag_encoding: |
1599 | TagEncoding::Niche { ref niche_variants, niche_start, dataful_variant }, | |
1600 | ref tag, | |
a1dfa0c6 | 1601 | ref variants, |
f035d41b | 1602 | tag_field, |
a1dfa0c6 XL |
1603 | } => { |
1604 | if fallback { | |
1605 | let variant = self.layout.for_variant(cx, dataful_variant); | |
60c5eb7d | 1606 | // Create a description of the non-null variant. |
dfeec247 XL |
1607 | let (variant_type_metadata, member_description_factory) = describe_enum_variant( |
1608 | cx, | |
1609 | variant, | |
1610 | variant_info_for(dataful_variant), | |
f035d41b | 1611 | OptimizedTag, |
dfeec247 XL |
1612 | self.containing_scope, |
1613 | self.span, | |
1614 | ); | |
1a4d82fc | 1615 | |
a1dfa0c6 XL |
1616 | let variant_member_descriptions = |
1617 | member_description_factory.create_member_descriptions(cx); | |
1a4d82fc | 1618 | |
dfeec247 XL |
1619 | set_members_of_composite_type( |
1620 | cx, | |
1621 | self.enum_type, | |
1622 | variant_type_metadata, | |
1623 | variant_member_descriptions, | |
1624 | ); | |
a1dfa0c6 XL |
1625 | |
1626 | // Encode the information about the null variant in the union | |
1627 | // member's name. | |
1628 | let mut name = String::from("RUST$ENCODED$ENUM$"); | |
1629 | // Right now it's not even going to work for `niche_start > 0`, | |
1630 | // and for multiple niche variants it only supports the first. | |
dfeec247 XL |
1631 | fn compute_field_path<'a, 'tcx>( |
1632 | cx: &CodegenCx<'a, 'tcx>, | |
1633 | name: &mut String, | |
ba9703b0 | 1634 | layout: TyAndLayout<'tcx>, |
dfeec247 XL |
1635 | offset: Size, |
1636 | size: Size, | |
1637 | ) { | |
a1dfa0c6 XL |
1638 | for i in 0..layout.fields.count() { |
1639 | let field_offset = layout.fields.offset(i); | |
1640 | if field_offset > offset { | |
1641 | continue; | |
1642 | } | |
1643 | let inner_offset = offset - field_offset; | |
1644 | let field = layout.field(cx, i); | |
1645 | if inner_offset + size <= field.size { | |
1646 | write!(name, "{}$", i).unwrap(); | |
1647 | compute_field_path(cx, name, field, inner_offset, size); | |
1648 | } | |
ff7c6d11 XL |
1649 | } |
1650 | } | |
dfeec247 XL |
1651 | compute_field_path( |
1652 | cx, | |
1653 | &mut name, | |
1654 | self.layout, | |
f035d41b XL |
1655 | self.layout.fields.offset(tag_field), |
1656 | self.layout.field(cx, tag_field).size, | |
dfeec247 | 1657 | ); |
f035d41b XL |
1658 | let variant_info = variant_info_for(*niche_variants.start()); |
1659 | variant_info.map_struct_name(|variant_name| { | |
48663c56 XL |
1660 | name.push_str(variant_name); |
1661 | }); | |
a1dfa0c6 XL |
1662 | |
1663 | // Create the (singleton) list of descriptions of union members. | |
dfeec247 XL |
1664 | vec![MemberDescription { |
1665 | name, | |
1666 | type_metadata: variant_type_metadata, | |
1667 | offset: Size::ZERO, | |
1668 | size: variant.size, | |
1669 | align: variant.align.abi, | |
f035d41b | 1670 | flags, |
dfeec247 | 1671 | discriminant: None, |
f035d41b | 1672 | source_info: variant_info.source_info(cx), |
dfeec247 | 1673 | }] |
a1dfa0c6 | 1674 | } else { |
dfeec247 XL |
1675 | variants |
1676 | .iter_enumerated() | |
1677 | .map(|(i, _)| { | |
1678 | let variant = self.layout.for_variant(cx, i); | |
1679 | let variant_info = variant_info_for(i); | |
1680 | let (variant_type_metadata, member_desc_factory) = | |
1681 | describe_enum_variant( | |
1682 | cx, | |
1683 | variant, | |
1684 | variant_info, | |
f035d41b | 1685 | OptimizedTag, |
dfeec247 XL |
1686 | self_metadata, |
1687 | self.span, | |
1688 | ); | |
1689 | ||
1690 | let member_descriptions = | |
1691 | member_desc_factory.create_member_descriptions(cx); | |
1692 | ||
1693 | set_members_of_composite_type( | |
1694 | cx, | |
1695 | self.enum_type, | |
1696 | variant_type_metadata, | |
1697 | member_descriptions, | |
1698 | ); | |
1699 | ||
1700 | let niche_value = if i == dataful_variant { | |
1701 | None | |
1702 | } else { | |
1703 | let value = (i.as_u32() as u128) | |
1704 | .wrapping_sub(niche_variants.start().as_u32() as u128) | |
1705 | .wrapping_add(niche_start); | |
29967ef6 | 1706 | let value = tag.value.size(cx).truncate(value); |
dfeec247 XL |
1707 | // NOTE(eddyb) do *NOT* remove this assert, until |
1708 | // we pass the full 128-bit value to LLVM, otherwise | |
1709 | // truncation will be silent and remain undetected. | |
1710 | assert_eq!(value as u64 as u128, value); | |
1711 | Some(value as u64) | |
1712 | }; | |
1713 | ||
1714 | MemberDescription { | |
1715 | name: variant_info.variant_name(), | |
1716 | type_metadata: variant_type_metadata, | |
1717 | offset: Size::ZERO, | |
1718 | size: self.layout.size, | |
1719 | align: self.layout.align.abi, | |
f035d41b | 1720 | flags, |
dfeec247 | 1721 | discriminant: niche_value, |
f035d41b | 1722 | source_info: variant_info.source_info(cx), |
dfeec247 XL |
1723 | } |
1724 | }) | |
1725 | .collect() | |
ff7c6d11 | 1726 | } |
ff7c6d11 | 1727 | } |
1a4d82fc JJ |
1728 | } |
1729 | } | |
d9579d0f | 1730 | } |
1a4d82fc | 1731 | |
60c5eb7d | 1732 | // Creates `MemberDescription`s for the fields of a single enum variant. |
b7449926 | 1733 | struct VariantMemberDescriptionFactory<'ll, 'tcx> { |
60c5eb7d | 1734 | /// Cloned from the `layout::Struct` describing the variant. |
ba9703b0 | 1735 | offsets: Vec<Size>, |
d9579d0f | 1736 | args: Vec<(String, Ty<'tcx>)>, |
f035d41b | 1737 | tag_type_metadata: Option<&'ll DIType>, |
d9579d0f AL |
1738 | span: Span, |
1739 | } | |
1a4d82fc | 1740 | |
b7449926 | 1741 | impl VariantMemberDescriptionFactory<'ll, 'tcx> { |
dfeec247 XL |
1742 | fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec<MemberDescription<'ll>> { |
1743 | self.args | |
1744 | .iter() | |
1745 | .enumerate() | |
1746 | .map(|(i, &(ref name, ty))| { | |
f035d41b XL |
1747 | // Discriminant is always the first field of our variant |
1748 | // when using the enum fallback. | |
1749 | let is_artificial_discr = use_enum_fallback(cx) && i == 0; | |
dfeec247 XL |
1750 | let (size, align) = cx.size_and_align_of(ty); |
1751 | MemberDescription { | |
1752 | name: name.to_string(), | |
f035d41b XL |
1753 | type_metadata: if is_artificial_discr { |
1754 | self.tag_type_metadata.unwrap_or_else(|| type_metadata(cx, ty, self.span)) | |
dfeec247 XL |
1755 | } else { |
1756 | type_metadata(cx, ty, self.span) | |
1757 | }, | |
1758 | offset: self.offsets[i], | |
1759 | size, | |
1760 | align, | |
f035d41b XL |
1761 | flags: if is_artificial_discr { |
1762 | DIFlags::FlagArtificial | |
1763 | } else { | |
1764 | DIFlags::FlagZero | |
1765 | }, | |
dfeec247 | 1766 | discriminant: None, |
f035d41b | 1767 | source_info: None, |
dfeec247 XL |
1768 | } |
1769 | }) | |
1770 | .collect() | |
1a4d82fc | 1771 | } |
d9579d0f | 1772 | } |
1a4d82fc | 1773 | |
f035d41b XL |
1774 | // FIXME: terminology here should be aligned with `abi::TagEncoding`. |
1775 | // `OptimizedTag` is `TagEncoding::Niche`, `RegularTag` is `TagEncoding::Direct`. | |
1776 | // `NoTag` should be removed; users should use `Option<EnumTagInfo>` instead. | |
d9579d0f | 1777 | #[derive(Copy, Clone)] |
f035d41b XL |
1778 | enum EnumTagInfo<'ll> { |
1779 | RegularTag { tag_field: Field, tag_type_metadata: &'ll DIType }, | |
1780 | OptimizedTag, | |
1781 | NoTag, | |
d9579d0f | 1782 | } |
1a4d82fc | 1783 | |
48663c56 | 1784 | #[derive(Copy, Clone)] |
60c5eb7d | 1785 | enum VariantInfo<'a, 'tcx> { |
48663c56 | 1786 | Adt(&'tcx ty::VariantDef), |
60c5eb7d | 1787 | Generator { |
f035d41b | 1788 | def_id: DefId, |
60c5eb7d | 1789 | generator_layout: &'tcx GeneratorLayout<'tcx>, |
f9f354fc | 1790 | generator_saved_local_names: &'a IndexVec<mir::GeneratorSavedLocal, Option<Symbol>>, |
60c5eb7d XL |
1791 | variant_index: VariantIdx, |
1792 | }, | |
48663c56 XL |
1793 | } |
1794 | ||
60c5eb7d | 1795 | impl<'tcx> VariantInfo<'_, 'tcx> { |
48663c56 XL |
1796 | fn map_struct_name<R>(&self, f: impl FnOnce(&str) -> R) -> R { |
1797 | match self { | |
1798 | VariantInfo::Adt(variant) => f(&variant.ident.as_str()), | |
f035d41b XL |
1799 | VariantInfo::Generator { variant_index, .. } => { |
1800 | f(&GeneratorSubsts::variant_name(*variant_index)) | |
dfeec247 | 1801 | } |
48663c56 XL |
1802 | } |
1803 | } | |
1804 | ||
1805 | fn variant_name(&self) -> String { | |
1806 | match self { | |
1807 | VariantInfo::Adt(variant) => variant.ident.to_string(), | |
60c5eb7d | 1808 | VariantInfo::Generator { variant_index, .. } => { |
48663c56 XL |
1809 | // Since GDB currently prints out the raw discriminant along |
1810 | // with every variant, make each variant name be just the value | |
1811 | // of the discriminant. The struct name for the variant includes | |
1812 | // the actual variant description. | |
dc9dc135 | 1813 | format!("{}", variant_index.as_usize()) |
48663c56 XL |
1814 | } |
1815 | } | |
1816 | } | |
1817 | ||
1818 | fn field_name(&self, i: usize) -> String { | |
60c5eb7d | 1819 | let field_name = match *self { |
dfeec247 XL |
1820 | VariantInfo::Adt(variant) if variant.ctor_kind != CtorKind::Fn => { |
1821 | Some(variant.fields[i].ident.name) | |
1822 | } | |
60c5eb7d XL |
1823 | VariantInfo::Generator { |
1824 | generator_layout, | |
1825 | generator_saved_local_names, | |
1826 | variant_index, | |
1827 | .. | |
dfeec247 XL |
1828 | } => { |
1829 | generator_saved_local_names | |
1830 | [generator_layout.variant_fields[variant_index][i.into()]] | |
1831 | } | |
48663c56 XL |
1832 | _ => None, |
1833 | }; | |
60c5eb7d | 1834 | field_name.map(|name| name.to_string()).unwrap_or_else(|| format!("__{}", i)) |
48663c56 | 1835 | } |
f035d41b XL |
1836 | |
1837 | fn source_info(&self, cx: &CodegenCx<'ll, 'tcx>) -> Option<SourceInfo<'ll>> { | |
1838 | match self { | |
1839 | VariantInfo::Generator { def_id, variant_index, .. } => { | |
5869c6ff XL |
1840 | let span = cx.tcx.generator_layout(*def_id).unwrap().variant_source_info |
1841 | [*variant_index] | |
1842 | .span; | |
f035d41b XL |
1843 | if !span.is_dummy() { |
1844 | let loc = cx.lookup_debug_loc(span.lo()); | |
6a06907d | 1845 | return Some(SourceInfo { file: file_metadata(cx, &loc.file), line: loc.line }); |
f035d41b XL |
1846 | } |
1847 | } | |
1848 | _ => {} | |
1849 | } | |
1850 | None | |
1851 | } | |
1852 | ||
f035d41b XL |
1853 | fn is_artificial(&self) -> bool { |
1854 | match self { | |
1855 | VariantInfo::Generator { .. } => true, | |
1856 | VariantInfo::Adt(..) => false, | |
1857 | } | |
1858 | } | |
48663c56 XL |
1859 | } |
1860 | ||
60c5eb7d XL |
1861 | /// Returns a tuple of (1) `type_metadata_stub` of the variant, (2) a |
1862 | /// `MemberDescriptionFactory` for producing the descriptions of the | |
1863 | /// fields of the variant. This is a rudimentary version of a full | |
1864 | /// `RecursiveTypeDescription`. | |
b7449926 XL |
1865 | fn describe_enum_variant( |
1866 | cx: &CodegenCx<'ll, 'tcx>, | |
ba9703b0 | 1867 | layout: layout::TyAndLayout<'tcx>, |
60c5eb7d | 1868 | variant: VariantInfo<'_, 'tcx>, |
f035d41b | 1869 | discriminant_info: EnumTagInfo<'ll>, |
b7449926 XL |
1870 | containing_scope: &'ll DIScope, |
1871 | span: Span, | |
1872 | ) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) { | |
48663c56 | 1873 | let metadata_stub = variant.map_struct_name(|variant_name| { |
dfeec247 XL |
1874 | let unique_type_id = debug_context(cx) |
1875 | .type_map | |
1876 | .borrow_mut() | |
1877 | .get_unique_type_id_of_enum_variant(cx, layout.ty, &variant_name); | |
f035d41b XL |
1878 | create_struct_stub( |
1879 | cx, | |
1880 | layout.ty, | |
1881 | &variant_name, | |
1882 | unique_type_id, | |
1883 | Some(containing_scope), | |
1884 | // FIXME(tmandry): This doesn't seem to have any effect. | |
1885 | if variant.is_artificial() { DIFlags::FlagArtificial } else { DIFlags::FlagZero }, | |
1886 | ) | |
48663c56 | 1887 | }); |
1a4d82fc | 1888 | |
d9579d0f | 1889 | // Build an array of (field name, field type) pairs to be captured in the factory closure. |
a1dfa0c6 XL |
1890 | let (offsets, args) = if use_enum_fallback(cx) { |
1891 | // If this is not a univariant enum, there is also the discriminant field. | |
1892 | let (discr_offset, discr_arg) = match discriminant_info { | |
f035d41b | 1893 | RegularTag { tag_field, .. } => { |
a1dfa0c6 XL |
1894 | // We have the layout of an enum variant, we need the layout of the outer enum |
1895 | let enum_layout = cx.layout_of(layout.ty); | |
f035d41b | 1896 | let offset = enum_layout.fields.offset(tag_field.as_usize()); |
dfeec247 | 1897 | let args = |
f035d41b | 1898 | ("RUST$ENUM$DISR".to_owned(), enum_layout.field(cx, tag_field.as_usize()).ty); |
48663c56 | 1899 | (Some(offset), Some(args)) |
a1dfa0c6 XL |
1900 | } |
1901 | _ => (None, None), | |
ff7c6d11 | 1902 | }; |
a1dfa0c6 | 1903 | ( |
dfeec247 XL |
1904 | discr_offset |
1905 | .into_iter() | |
1906 | .chain((0..layout.fields.count()).map(|i| layout.fields.offset(i))) | |
1907 | .collect(), | |
1908 | discr_arg | |
1909 | .into_iter() | |
1910 | .chain( | |
1911 | (0..layout.fields.count()) | |
1912 | .map(|i| (variant.field_name(i), layout.field(cx, i).ty)), | |
1913 | ) | |
1914 | .collect(), | |
a1dfa0c6 XL |
1915 | ) |
1916 | } else { | |
1917 | ( | |
dfeec247 XL |
1918 | (0..layout.fields.count()).map(|i| layout.fields.offset(i)).collect(), |
1919 | (0..layout.fields.count()) | |
1920 | .map(|i| (variant.field_name(i), layout.field(cx, i).ty)) | |
1921 | .collect(), | |
a1dfa0c6 XL |
1922 | ) |
1923 | }; | |
1a4d82fc | 1924 | |
dfeec247 XL |
1925 | let member_description_factory = VariantMDF(VariantMemberDescriptionFactory { |
1926 | offsets, | |
1927 | args, | |
f035d41b XL |
1928 | tag_type_metadata: match discriminant_info { |
1929 | RegularTag { tag_type_metadata, .. } => Some(tag_type_metadata), | |
dfeec247 XL |
1930 | _ => None, |
1931 | }, | |
1932 | span, | |
1933 | }); | |
1a4d82fc | 1934 | |
ff7c6d11 | 1935 | (metadata_stub, member_description_factory) |
d9579d0f | 1936 | } |
1a4d82fc | 1937 | |
b7449926 XL |
1938 | fn prepare_enum_metadata( |
1939 | cx: &CodegenCx<'ll, 'tcx>, | |
1940 | enum_type: Ty<'tcx>, | |
1941 | enum_def_id: DefId, | |
1942 | unique_type_id: UniqueTypeId, | |
1943 | span: Span, | |
48663c56 | 1944 | outer_field_tys: Vec<Ty<'tcx>>, |
b7449926 | 1945 | ) -> RecursiveTypeDescription<'ll, 'tcx> { |
f035d41b XL |
1946 | let tcx = cx.tcx; |
1947 | let enum_name = compute_debuginfo_type_name(tcx, enum_type, false); | |
1948 | // FIXME(tmandry): This doesn't seem to have any effect. | |
1b1a35ee | 1949 | let enum_flags = match enum_type.kind() { |
f035d41b XL |
1950 | ty::Generator(..) => DIFlags::FlagArtificial, |
1951 | _ => DIFlags::FlagZero, | |
1952 | }; | |
1a4d82fc | 1953 | |
041b39d2 | 1954 | let containing_scope = get_namespace_for_item(cx, enum_def_id); |
e9174d1e SL |
1955 | // FIXME: This should emit actual file metadata for the enum, but we |
1956 | // currently can't get the necessary information when it comes to types | |
1957 | // imported from other crates. Formerly we violated the ODR when performing | |
1958 | // LTO because we emitted debuginfo for the same type with varying file | |
1959 | // metadata, so as a workaround we pretend that the type comes from | |
1960 | // <unknown> | |
1961 | let file_metadata = unknown_file_metadata(cx); | |
1a4d82fc | 1962 | |
ba9703b0 | 1963 | let discriminant_type_metadata = |discr: Primitive| { |
1b1a35ee | 1964 | let enumerators_metadata: Vec<_> = match enum_type.kind() { |
48663c56 | 1965 | ty::Adt(def, _) => def |
f035d41b | 1966 | .discriminants(tcx) |
48663c56 XL |
1967 | .zip(&def.variants) |
1968 | .map(|((_, discr), v)| { | |
74b04a01 | 1969 | let name = v.ident.as_str(); |
1b1a35ee | 1970 | let is_unsigned = match discr.ty.kind() { |
74b04a01 XL |
1971 | ty::Int(_) => false, |
1972 | ty::Uint(_) => true, | |
1973 | _ => bug!("non integer discriminant"), | |
1974 | }; | |
48663c56 XL |
1975 | unsafe { |
1976 | Some(llvm::LLVMRustDIBuilderCreateEnumerator( | |
1977 | DIB(cx), | |
74b04a01 XL |
1978 | name.as_ptr().cast(), |
1979 | name.len(), | |
48663c56 | 1980 | // FIXME: what if enumeration has i128 discriminant? |
74b04a01 XL |
1981 | discr.val as i64, |
1982 | is_unsigned, | |
dfeec247 | 1983 | )) |
48663c56 XL |
1984 | } |
1985 | }) | |
1986 | .collect(), | |
1987 | ty::Generator(_, substs, _) => substs | |
e74abb32 | 1988 | .as_generator() |
f035d41b | 1989 | .variant_range(enum_def_id, tcx) |
48663c56 | 1990 | .map(|variant_index| { |
f035d41b XL |
1991 | debug_assert_eq!(tcx.types.u32, substs.as_generator().discr_ty(tcx)); |
1992 | let name = GeneratorSubsts::variant_name(variant_index); | |
48663c56 XL |
1993 | unsafe { |
1994 | Some(llvm::LLVMRustDIBuilderCreateEnumerator( | |
1995 | DIB(cx), | |
74b04a01 XL |
1996 | name.as_ptr().cast(), |
1997 | name.len(), | |
f035d41b | 1998 | // Generators use u32 as discriminant type, verified above. |
74b04a01 XL |
1999 | variant_index.as_u32().into(), |
2000 | true, // IsUnsigned | |
dfeec247 | 2001 | )) |
48663c56 XL |
2002 | } |
2003 | }) | |
2004 | .collect(), | |
2005 | _ => bug!(), | |
2006 | }; | |
a1dfa0c6 | 2007 | |
ff7c6d11 | 2008 | let disr_type_key = (enum_def_id, discr); |
dfeec247 XL |
2009 | let cached_discriminant_type_metadata = |
2010 | debug_context(cx).created_enum_disr_types.borrow().get(&disr_type_key).cloned(); | |
d9579d0f AL |
2011 | match cached_discriminant_type_metadata { |
2012 | Some(discriminant_type_metadata) => discriminant_type_metadata, | |
2013 | None => { | |
dfeec247 | 2014 | let (discriminant_size, discriminant_align) = (discr.size(cx), discr.align(cx)); |
d9579d0f | 2015 | let discriminant_base_type_metadata = |
f035d41b | 2016 | type_metadata(cx, discr.to_ty(tcx), rustc_span::DUMMY_SP); |
1a4d82fc | 2017 | |
74b04a01 | 2018 | let item_name; |
1b1a35ee | 2019 | let discriminant_name = match enum_type.kind() { |
74b04a01 | 2020 | ty::Adt(..) => { |
f035d41b | 2021 | item_name = tcx.item_name(enum_def_id).as_str(); |
74b04a01 XL |
2022 | &*item_name |
2023 | } | |
2024 | ty::Generator(..) => enum_name.as_str(), | |
48663c56 XL |
2025 | _ => bug!(), |
2026 | }; | |
2027 | ||
d9579d0f | 2028 | let discriminant_type_metadata = unsafe { |
5bcae85e | 2029 | llvm::LLVMRustDIBuilderCreateEnumerationType( |
d9579d0f AL |
2030 | DIB(cx), |
2031 | containing_scope, | |
74b04a01 XL |
2032 | discriminant_name.as_ptr().cast(), |
2033 | discriminant_name.len(), | |
5bcae85e | 2034 | file_metadata, |
d9579d0f | 2035 | UNKNOWN_LINE_NUMBER, |
ff7c6d11 | 2036 | discriminant_size.bits(), |
a1dfa0c6 | 2037 | discriminant_align.abi.bits() as u32, |
d9579d0f | 2038 | create_DIArray(DIB(cx), &enumerators_metadata), |
dfeec247 XL |
2039 | discriminant_base_type_metadata, |
2040 | true, | |
2041 | ) | |
d9579d0f | 2042 | }; |
1a4d82fc | 2043 | |
dfeec247 XL |
2044 | debug_context(cx) |
2045 | .created_enum_disr_types | |
2046 | .borrow_mut() | |
2047 | .insert(disr_type_key, discriminant_type_metadata); | |
1a4d82fc | 2048 | |
d9579d0f | 2049 | discriminant_type_metadata |
1a4d82fc JJ |
2050 | } |
2051 | } | |
d9579d0f | 2052 | }; |
1a4d82fc | 2053 | |
ff7c6d11 | 2054 | let layout = cx.layout_of(enum_type); |
1a4d82fc | 2055 | |
ba9703b0 XL |
2056 | if let ( |
2057 | &Abi::Scalar(_), | |
f035d41b | 2058 | &Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, .. }, |
ba9703b0 XL |
2059 | ) = (&layout.abi, &layout.variants) |
2060 | { | |
f035d41b | 2061 | return FinalMetadata(discriminant_type_metadata(tag.value)); |
ff7c6d11 XL |
2062 | } |
2063 | ||
a1dfa0c6 XL |
2064 | if use_enum_fallback(cx) { |
2065 | let discriminant_type_metadata = match layout.variants { | |
ba9703b0 | 2066 | Variants::Single { .. } |
f035d41b XL |
2067 | | Variants::Multiple { tag_encoding: TagEncoding::Niche { .. }, .. } => None, |
2068 | Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, .. } => { | |
2069 | Some(discriminant_type_metadata(tag.value)) | |
ba9703b0 | 2070 | } |
a1dfa0c6 XL |
2071 | }; |
2072 | ||
74b04a01 XL |
2073 | let enum_metadata = { |
2074 | let type_map = debug_context(cx).type_map.borrow(); | |
2075 | let unique_type_id_str = type_map.get_unique_type_id_as_string(unique_type_id); | |
2076 | ||
2077 | unsafe { | |
2078 | llvm::LLVMRustDIBuilderCreateUnionType( | |
2079 | DIB(cx), | |
2080 | containing_scope, | |
2081 | enum_name.as_ptr().cast(), | |
2082 | enum_name.len(), | |
2083 | file_metadata, | |
2084 | UNKNOWN_LINE_NUMBER, | |
2085 | layout.size.bits(), | |
2086 | layout.align.abi.bits() as u32, | |
f035d41b | 2087 | enum_flags, |
74b04a01 XL |
2088 | None, |
2089 | 0, // RuntimeLang | |
2090 | unique_type_id_str.as_ptr().cast(), | |
2091 | unique_type_id_str.len(), | |
2092 | ) | |
2093 | } | |
a1dfa0c6 XL |
2094 | }; |
2095 | ||
2096 | return create_and_register_recursive_type_forward_declaration( | |
2097 | cx, | |
2098 | enum_type, | |
2099 | unique_type_id, | |
2100 | enum_metadata, | |
2101 | enum_metadata, | |
2102 | EnumMDF(EnumMemberDescriptionFactory { | |
2103 | enum_type, | |
2104 | layout, | |
f035d41b | 2105 | tag_type_metadata: discriminant_type_metadata, |
a1dfa0c6 XL |
2106 | containing_scope, |
2107 | span, | |
2108 | }), | |
2109 | ); | |
2110 | } | |
2111 | ||
1b1a35ee | 2112 | let discriminator_name = match enum_type.kind() { |
74b04a01 XL |
2113 | ty::Generator(..) => "__state", |
2114 | _ => "", | |
48663c56 | 2115 | }; |
532ac7d7 | 2116 | let discriminator_metadata = match layout.variants { |
a1dfa0c6 | 2117 | // A single-variant enum has no discriminant. |
ba9703b0 | 2118 | Variants::Single { .. } => None, |
a1dfa0c6 | 2119 | |
ba9703b0 | 2120 | Variants::Multiple { |
f035d41b | 2121 | tag_encoding: TagEncoding::Niche { .. }, ref tag, tag_field, .. |
532ac7d7 | 2122 | } => { |
a1dfa0c6 | 2123 | // Find the integer type of the correct size. |
f035d41b XL |
2124 | let size = tag.value.size(cx); |
2125 | let align = tag.value.align(cx); | |
a1dfa0c6 | 2126 | |
f035d41b | 2127 | let tag_type = match tag.value { |
ba9703b0 XL |
2128 | Int(t, _) => t, |
2129 | F32 => Integer::I32, | |
2130 | F64 => Integer::I64, | |
2131 | Pointer => cx.data_layout().ptr_sized_integer(), | |
dfeec247 XL |
2132 | } |
2133 | .to_ty(cx.tcx, false); | |
a1dfa0c6 | 2134 | |
f035d41b | 2135 | let tag_metadata = basic_type_metadata(cx, tag_type); |
a1dfa0c6 XL |
2136 | unsafe { |
2137 | Some(llvm::LLVMRustDIBuilderCreateMemberType( | |
2138 | DIB(cx), | |
2139 | containing_scope, | |
74b04a01 XL |
2140 | discriminator_name.as_ptr().cast(), |
2141 | discriminator_name.len(), | |
a1dfa0c6 XL |
2142 | file_metadata, |
2143 | UNKNOWN_LINE_NUMBER, | |
2144 | size.bits(), | |
2145 | align.abi.bits() as u32, | |
f035d41b | 2146 | layout.fields.offset(tag_field).bits(), |
a1dfa0c6 | 2147 | DIFlags::FlagArtificial, |
f035d41b | 2148 | tag_metadata, |
dfeec247 | 2149 | )) |
a1dfa0c6 | 2150 | } |
dfeec247 | 2151 | } |
a1dfa0c6 | 2152 | |
f035d41b XL |
2153 | Variants::Multiple { tag_encoding: TagEncoding::Direct, ref tag, tag_field, .. } => { |
2154 | let discr_type = tag.value.to_ty(cx.tcx); | |
a1dfa0c6 XL |
2155 | let (size, align) = cx.size_and_align_of(discr_type); |
2156 | ||
2157 | let discr_metadata = basic_type_metadata(cx, discr_type); | |
2158 | unsafe { | |
2159 | Some(llvm::LLVMRustDIBuilderCreateMemberType( | |
2160 | DIB(cx), | |
2161 | containing_scope, | |
74b04a01 XL |
2162 | discriminator_name.as_ptr().cast(), |
2163 | discriminator_name.len(), | |
a1dfa0c6 XL |
2164 | file_metadata, |
2165 | UNKNOWN_LINE_NUMBER, | |
2166 | size.bits(), | |
2167 | align.bits() as u32, | |
f035d41b | 2168 | layout.fields.offset(tag_field).bits(), |
a1dfa0c6 | 2169 | DIFlags::FlagArtificial, |
dfeec247 XL |
2170 | discr_metadata, |
2171 | )) | |
a1dfa0c6 | 2172 | } |
dfeec247 | 2173 | } |
a1dfa0c6 XL |
2174 | }; |
2175 | ||
48663c56 | 2176 | let mut outer_fields = match layout.variants { |
ba9703b0 XL |
2177 | Variants::Single { .. } => vec![], |
2178 | Variants::Multiple { .. } => { | |
48663c56 XL |
2179 | let tuple_mdf = TupleMemberDescriptionFactory { |
2180 | ty: enum_type, | |
2181 | component_types: outer_field_tys, | |
dfeec247 | 2182 | span, |
48663c56 XL |
2183 | }; |
2184 | tuple_mdf | |
2185 | .create_member_descriptions(cx) | |
2186 | .into_iter() | |
2187 | .map(|desc| Some(desc.into_metadata(cx, containing_scope))) | |
2188 | .collect() | |
2189 | } | |
2190 | }; | |
2191 | ||
74b04a01 XL |
2192 | let variant_part_unique_type_id_str = debug_context(cx) |
2193 | .type_map | |
2194 | .borrow_mut() | |
2195 | .get_unique_type_id_str_of_enum_variant_part(unique_type_id); | |
a1dfa0c6 | 2196 | let empty_array = create_DIArray(DIB(cx), &[]); |
74b04a01 | 2197 | let name = ""; |
a1dfa0c6 XL |
2198 | let variant_part = unsafe { |
2199 | llvm::LLVMRustDIBuilderCreateVariantPart( | |
2200 | DIB(cx), | |
2201 | containing_scope, | |
74b04a01 XL |
2202 | name.as_ptr().cast(), |
2203 | name.len(), | |
a1dfa0c6 XL |
2204 | file_metadata, |
2205 | UNKNOWN_LINE_NUMBER, | |
2206 | layout.size.bits(), | |
2207 | layout.align.abi.bits() as u32, | |
f035d41b | 2208 | enum_flags, |
a1dfa0c6 XL |
2209 | discriminator_metadata, |
2210 | empty_array, | |
74b04a01 XL |
2211 | variant_part_unique_type_id_str.as_ptr().cast(), |
2212 | variant_part_unique_type_id_str.len(), | |
dfeec247 | 2213 | ) |
a1dfa0c6 | 2214 | }; |
48663c56 | 2215 | outer_fields.push(Some(variant_part)); |
a1dfa0c6 | 2216 | |
74b04a01 XL |
2217 | let struct_wrapper = { |
2218 | // The variant part must be wrapped in a struct according to DWARF. | |
2219 | let type_array = create_DIArray(DIB(cx), &outer_fields); | |
2220 | ||
2221 | let type_map = debug_context(cx).type_map.borrow(); | |
2222 | let unique_type_id_str = type_map.get_unique_type_id_as_string(unique_type_id); | |
2223 | ||
2224 | unsafe { | |
2225 | llvm::LLVMRustDIBuilderCreateStructType( | |
2226 | DIB(cx), | |
2227 | Some(containing_scope), | |
2228 | enum_name.as_ptr().cast(), | |
2229 | enum_name.len(), | |
2230 | file_metadata, | |
2231 | UNKNOWN_LINE_NUMBER, | |
2232 | layout.size.bits(), | |
2233 | layout.align.abi.bits() as u32, | |
f035d41b | 2234 | enum_flags, |
74b04a01 XL |
2235 | None, |
2236 | type_array, | |
2237 | 0, | |
2238 | None, | |
2239 | unique_type_id_str.as_ptr().cast(), | |
2240 | unique_type_id_str.len(), | |
2241 | ) | |
2242 | } | |
d9579d0f | 2243 | }; |
1a4d82fc | 2244 | |
ba9703b0 | 2245 | create_and_register_recursive_type_forward_declaration( |
d9579d0f AL |
2246 | cx, |
2247 | enum_type, | |
2248 | unique_type_id, | |
a1dfa0c6 XL |
2249 | struct_wrapper, |
2250 | variant_part, | |
d9579d0f | 2251 | EnumMDF(EnumMemberDescriptionFactory { |
3b2f2976 | 2252 | enum_type, |
ff7c6d11 | 2253 | layout, |
f035d41b | 2254 | tag_type_metadata: None, |
3b2f2976 | 2255 | containing_scope, |
3b2f2976 | 2256 | span, |
d9579d0f | 2257 | }), |
ba9703b0 | 2258 | ) |
d9579d0f | 2259 | } |
1a4d82fc | 2260 | |
d9579d0f AL |
2261 | /// Creates debug information for a composite type, that is, anything that |
2262 | /// results in a LLVM struct. | |
2263 | /// | |
2264 | /// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums. | |
b7449926 XL |
2265 | fn composite_type_metadata( |
2266 | cx: &CodegenCx<'ll, 'tcx>, | |
2267 | composite_type: Ty<'tcx>, | |
2268 | composite_type_name: &str, | |
2269 | composite_type_unique_id: UniqueTypeId, | |
2270 | member_descriptions: Vec<MemberDescription<'ll>>, | |
2271 | containing_scope: Option<&'ll DIScope>, | |
2272 | ||
2273 | // Ignore source location information as long as it | |
2274 | // can't be reconstructed for non-local crates. | |
2275 | _file_metadata: &'ll DIFile, | |
2276 | _definition_span: Span, | |
2277 | ) -> &'ll DICompositeType { | |
d9579d0f | 2278 | // Create the (empty) struct metadata node ... |
dfeec247 XL |
2279 | let composite_type_metadata = create_struct_stub( |
2280 | cx, | |
2281 | composite_type, | |
2282 | composite_type_name, | |
2283 | composite_type_unique_id, | |
2284 | containing_scope, | |
f035d41b | 2285 | DIFlags::FlagZero, |
dfeec247 | 2286 | ); |
d9579d0f | 2287 | // ... and immediately create and add the member descriptions. |
dfeec247 | 2288 | set_members_of_composite_type(cx, composite_type, composite_type_metadata, member_descriptions); |
1a4d82fc | 2289 | |
0bf4aa26 | 2290 | composite_type_metadata |
d9579d0f | 2291 | } |
1a4d82fc | 2292 | |
dfeec247 XL |
2293 | fn set_members_of_composite_type( |
2294 | cx: &CodegenCx<'ll, 'tcx>, | |
2295 | composite_type: Ty<'tcx>, | |
2296 | composite_type_metadata: &'ll DICompositeType, | |
2297 | member_descriptions: Vec<MemberDescription<'ll>>, | |
2298 | ) { | |
d9579d0f AL |
2299 | // In some rare cases LLVM metadata uniquing would lead to an existing type |
2300 | // description being used instead of a new one created in | |
2301 | // create_struct_stub. This would cause a hard to trace assertion in | |
2302 | // DICompositeType::SetTypeArray(). The following check makes sure that we | |
2303 | // get a better error message if this should happen again due to some | |
2304 | // regression. | |
2305 | { | |
2306 | let mut composite_types_completed = | |
2307 | debug_context(cx).composite_types_completed.borrow_mut(); | |
e74abb32 | 2308 | if !composite_types_completed.insert(&composite_type_metadata) { |
dfeec247 XL |
2309 | bug!( |
2310 | "debuginfo::set_members_of_composite_type() - \ | |
2311 | Already completed forward declaration re-encountered." | |
2312 | ); | |
d9579d0f AL |
2313 | } |
2314 | } | |
1a4d82fc | 2315 | |
b7449926 XL |
2316 | let member_metadata: Vec<_> = member_descriptions |
2317 | .into_iter() | |
48663c56 | 2318 | .map(|desc| Some(desc.into_metadata(cx, composite_type_metadata))) |
d9579d0f | 2319 | .collect(); |
1a4d82fc | 2320 | |
a1dfa0c6 | 2321 | let type_params = compute_type_parameters(cx, composite_type); |
d9579d0f AL |
2322 | unsafe { |
2323 | let type_array = create_DIArray(DIB(cx), &member_metadata[..]); | |
a1dfa0c6 | 2324 | llvm::LLVMRustDICompositeTypeReplaceArrays( |
dfeec247 XL |
2325 | DIB(cx), |
2326 | composite_type_metadata, | |
2327 | Some(type_array), | |
5869c6ff | 2328 | Some(type_params), |
dfeec247 | 2329 | ); |
a1dfa0c6 XL |
2330 | } |
2331 | } | |
2332 | ||
60c5eb7d | 2333 | /// Computes the type parameters for a type, if any, for the given metadata. |
5869c6ff | 2334 | fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> &'ll DIArray { |
1b1a35ee | 2335 | if let ty::Adt(def, substs) = *ty.kind() { |
74b04a01 | 2336 | if substs.types().next().is_some() { |
a1dfa0c6 XL |
2337 | let generics = cx.tcx.generics_of(def.did); |
2338 | let names = get_parameter_names(cx, generics); | |
dfeec247 XL |
2339 | let template_params: Vec<_> = substs |
2340 | .iter() | |
2341 | .zip(names) | |
2342 | .filter_map(|(kind, name)| { | |
2343 | if let GenericArgKind::Type(ty) = kind.unpack() { | |
2344 | let actual_type = | |
2345 | cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); | |
2346 | let actual_type_metadata = | |
2347 | type_metadata(cx, actual_type, rustc_span::DUMMY_SP); | |
74b04a01 | 2348 | let name = &name.as_str(); |
dfeec247 XL |
2349 | Some(unsafe { |
2350 | Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( | |
2351 | DIB(cx), | |
2352 | None, | |
74b04a01 XL |
2353 | name.as_ptr().cast(), |
2354 | name.len(), | |
dfeec247 | 2355 | actual_type_metadata, |
dfeec247 XL |
2356 | )) |
2357 | }) | |
2358 | } else { | |
2359 | None | |
2360 | } | |
2361 | }) | |
2362 | .collect(); | |
a1dfa0c6 | 2363 | |
5869c6ff | 2364 | return create_DIArray(DIB(cx), &template_params[..]); |
a1dfa0c6 XL |
2365 | } |
2366 | } | |
5869c6ff | 2367 | return create_DIArray(DIB(cx), &[]); |
a1dfa0c6 | 2368 | |
dfeec247 XL |
2369 | fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec<Symbol> { |
2370 | let mut names = generics | |
2371 | .parent | |
6a06907d | 2372 | .map_or_else(Vec::new, |def_id| get_parameter_names(cx, cx.tcx.generics_of(def_id))); |
a1dfa0c6 XL |
2373 | names.extend(generics.params.iter().map(|param| param.name)); |
2374 | names | |
d9579d0f AL |
2375 | } |
2376 | } | |
1a4d82fc | 2377 | |
60c5eb7d XL |
2378 | /// A convenience wrapper around `LLVMRustDIBuilderCreateStructType()`. Does not do |
2379 | /// any caching, does not add any fields to the struct. This can be done later | |
2380 | /// with `set_members_of_composite_type()`. | |
b7449926 XL |
2381 | fn create_struct_stub( |
2382 | cx: &CodegenCx<'ll, 'tcx>, | |
2383 | struct_type: Ty<'tcx>, | |
2384 | struct_type_name: &str, | |
2385 | unique_type_id: UniqueTypeId, | |
2386 | containing_scope: Option<&'ll DIScope>, | |
f035d41b | 2387 | flags: DIFlags, |
b7449926 | 2388 | ) -> &'ll DICompositeType { |
ff7c6d11 | 2389 | let (struct_size, struct_align) = cx.size_and_align_of(struct_type); |
1a4d82fc | 2390 | |
74b04a01 XL |
2391 | let type_map = debug_context(cx).type_map.borrow(); |
2392 | let unique_type_id = type_map.get_unique_type_id_as_string(unique_type_id); | |
2393 | ||
d9579d0f | 2394 | let metadata_stub = unsafe { |
60c5eb7d | 2395 | // `LLVMRustDIBuilderCreateStructType()` wants an empty array. A null |
d9579d0f | 2396 | // pointer will lead to hard to trace and debug LLVM assertions |
60c5eb7d | 2397 | // later on in `llvm/lib/IR/Value.cpp`. |
d9579d0f | 2398 | let empty_array = create_DIArray(DIB(cx), &[]); |
1a4d82fc | 2399 | |
5bcae85e | 2400 | llvm::LLVMRustDIBuilderCreateStructType( |
d9579d0f AL |
2401 | DIB(cx), |
2402 | containing_scope, | |
74b04a01 XL |
2403 | struct_type_name.as_ptr().cast(), |
2404 | struct_type_name.len(), | |
5bcae85e | 2405 | unknown_file_metadata(cx), |
d9579d0f | 2406 | UNKNOWN_LINE_NUMBER, |
ff7c6d11 | 2407 | struct_size.bits(), |
a1dfa0c6 | 2408 | struct_align.bits() as u32, |
f035d41b | 2409 | flags, |
b7449926 | 2410 | None, |
d9579d0f AL |
2411 | empty_array, |
2412 | 0, | |
b7449926 | 2413 | None, |
74b04a01 XL |
2414 | unique_type_id.as_ptr().cast(), |
2415 | unique_type_id.len(), | |
dfeec247 | 2416 | ) |
d9579d0f | 2417 | }; |
1a4d82fc | 2418 | |
0bf4aa26 | 2419 | metadata_stub |
d9579d0f | 2420 | } |
1a4d82fc | 2421 | |
b7449926 XL |
2422 | fn create_union_stub( |
2423 | cx: &CodegenCx<'ll, 'tcx>, | |
2424 | union_type: Ty<'tcx>, | |
2425 | union_type_name: &str, | |
2426 | unique_type_id: UniqueTypeId, | |
2427 | containing_scope: &'ll DIScope, | |
2428 | ) -> &'ll DICompositeType { | |
ff7c6d11 | 2429 | let (union_size, union_align) = cx.size_and_align_of(union_type); |
9e0c209e | 2430 | |
74b04a01 XL |
2431 | let type_map = debug_context(cx).type_map.borrow(); |
2432 | let unique_type_id = type_map.get_unique_type_id_as_string(unique_type_id); | |
2433 | ||
9e0c209e | 2434 | let metadata_stub = unsafe { |
60c5eb7d | 2435 | // `LLVMRustDIBuilderCreateUnionType()` wants an empty array. A null |
9e0c209e | 2436 | // pointer will lead to hard to trace and debug LLVM assertions |
60c5eb7d | 2437 | // later on in `llvm/lib/IR/Value.cpp`. |
9e0c209e SL |
2438 | let empty_array = create_DIArray(DIB(cx), &[]); |
2439 | ||
2440 | llvm::LLVMRustDIBuilderCreateUnionType( | |
2441 | DIB(cx), | |
2442 | containing_scope, | |
74b04a01 XL |
2443 | union_type_name.as_ptr().cast(), |
2444 | union_type_name.len(), | |
9e0c209e SL |
2445 | unknown_file_metadata(cx), |
2446 | UNKNOWN_LINE_NUMBER, | |
ff7c6d11 | 2447 | union_size.bits(), |
a1dfa0c6 | 2448 | union_align.bits() as u32, |
476ff2be | 2449 | DIFlags::FlagZero, |
b7449926 | 2450 | Some(empty_array), |
9e0c209e | 2451 | 0, // RuntimeLang |
74b04a01 XL |
2452 | unique_type_id.as_ptr().cast(), |
2453 | unique_type_id.len(), | |
dfeec247 | 2454 | ) |
9e0c209e SL |
2455 | }; |
2456 | ||
0bf4aa26 | 2457 | metadata_stub |
9e0c209e SL |
2458 | } |
2459 | ||
d9579d0f AL |
2460 | /// Creates debug information for the given global variable. |
2461 | /// | |
2462 | /// Adds the created metadata nodes directly to the crate's IR. | |
dfeec247 | 2463 | pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global: &'ll Value) { |
2c00a5a8 | 2464 | if cx.dbg_cx.is_none() { |
d9579d0f AL |
2465 | return; |
2466 | } | |
1a4d82fc | 2467 | |
ba9703b0 XL |
2468 | // Only create type information if full debuginfo is enabled |
2469 | if cx.sess().opts.debuginfo != DebugInfo::Full { | |
2470 | return; | |
2471 | } | |
2472 | ||
2c00a5a8 | 2473 | let tcx = cx.tcx; |
0531ce1d | 2474 | |
60c5eb7d XL |
2475 | // We may want to remove the namespace scope if we're in an extern block (see |
2476 | // https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952). | |
0531ce1d XL |
2477 | let var_scope = get_namespace_for_item(cx, def_id); |
2478 | let span = tcx.def_span(def_id); | |
1a4d82fc | 2479 | |
8faf50e0 | 2480 | let (file_metadata, line_number) = if !span.is_dummy() { |
ba9703b0 | 2481 | let loc = cx.lookup_debug_loc(span.lo()); |
29967ef6 | 2482 | (file_metadata(cx, &loc.file), loc.line) |
d9579d0f | 2483 | } else { |
6a06907d | 2484 | (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) |
d9579d0f | 2485 | }; |
1a4d82fc | 2486 | |
0531ce1d | 2487 | let is_local_to_unit = is_node_local_to_unit(cx, def_id); |
3dfed10e | 2488 | let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx, ty::ParamEnv::reveal_all()); |
d9579d0f | 2489 | let type_metadata = type_metadata(cx, variable_type, span); |
74b04a01 | 2490 | let var_name = tcx.item_name(def_id).as_str(); |
3dfed10e | 2491 | let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id)).name; |
74b04a01 XL |
2492 | // When empty, linkage_name field is omitted, |
2493 | // which is what we want for no_mangle statics | |
f035d41b | 2494 | let linkage_name = if var_name == linkage_name { "" } else { linkage_name }; |
476ff2be | 2495 | |
cc61c64b | 2496 | let global_align = cx.align_of(variable_type); |
476ff2be | 2497 | |
d9579d0f | 2498 | unsafe { |
dfeec247 XL |
2499 | llvm::LLVMRustDIBuilderCreateStaticVariable( |
2500 | DIB(cx), | |
2501 | Some(var_scope), | |
74b04a01 XL |
2502 | var_name.as_ptr().cast(), |
2503 | var_name.len(), | |
2504 | linkage_name.as_ptr().cast(), | |
2505 | linkage_name.len(), | |
dfeec247 | 2506 | file_metadata, |
6a06907d | 2507 | line_number, |
dfeec247 XL |
2508 | type_metadata, |
2509 | is_local_to_unit, | |
2510 | global, | |
2511 | None, | |
2512 | global_align.bytes() as u32, | |
476ff2be | 2513 | ); |
d9579d0f AL |
2514 | } |
2515 | } | |
1a4d82fc | 2516 | |
abe05a73 XL |
2517 | /// Creates debug information for the given vtable, which is for the |
2518 | /// given type. | |
2519 | /// | |
2520 | /// Adds the created metadata nodes directly to the crate's IR. | |
dc9dc135 | 2521 | pub fn create_vtable_metadata(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, vtable: &'ll Value) { |
2c00a5a8 | 2522 | if cx.dbg_cx.is_none() { |
abe05a73 XL |
2523 | return; |
2524 | } | |
2525 | ||
ba9703b0 XL |
2526 | // Only create type information if full debuginfo is enabled |
2527 | if cx.sess().opts.debuginfo != DebugInfo::Full { | |
2528 | return; | |
2529 | } | |
2530 | ||
dfeec247 | 2531 | let type_metadata = type_metadata(cx, ty, rustc_span::DUMMY_SP); |
abe05a73 XL |
2532 | |
2533 | unsafe { | |
60c5eb7d | 2534 | // `LLVMRustDIBuilderCreateStructType()` wants an empty array. A null |
abe05a73 | 2535 | // pointer will lead to hard to trace and debug LLVM assertions |
60c5eb7d | 2536 | // later on in `llvm/lib/IR/Value.cpp`. |
abe05a73 | 2537 | let empty_array = create_DIArray(DIB(cx), &[]); |
74b04a01 | 2538 | let name = "vtable"; |
abe05a73 | 2539 | |
60c5eb7d | 2540 | // Create a new one each time. We don't want metadata caching |
abe05a73 XL |
2541 | // here, because each vtable will refer to a unique containing |
2542 | // type. | |
2543 | let vtable_type = llvm::LLVMRustDIBuilderCreateStructType( | |
2544 | DIB(cx), | |
2545 | NO_SCOPE_METADATA, | |
74b04a01 XL |
2546 | name.as_ptr().cast(), |
2547 | name.len(), | |
abe05a73 XL |
2548 | unknown_file_metadata(cx), |
2549 | UNKNOWN_LINE_NUMBER, | |
94b46f34 | 2550 | Size::ZERO.bits(), |
a1dfa0c6 | 2551 | cx.tcx.data_layout.pointer_align.abi.bits() as u32, |
abe05a73 | 2552 | DIFlags::FlagArtificial, |
b7449926 | 2553 | None, |
abe05a73 XL |
2554 | empty_array, |
2555 | 0, | |
b7449926 | 2556 | Some(type_metadata), |
74b04a01 XL |
2557 | name.as_ptr().cast(), |
2558 | name.len(), | |
abe05a73 XL |
2559 | ); |
2560 | ||
74b04a01 | 2561 | let linkage_name = ""; |
dfeec247 XL |
2562 | llvm::LLVMRustDIBuilderCreateStaticVariable( |
2563 | DIB(cx), | |
2564 | NO_SCOPE_METADATA, | |
74b04a01 XL |
2565 | name.as_ptr().cast(), |
2566 | name.len(), | |
2567 | linkage_name.as_ptr().cast(), | |
2568 | linkage_name.len(), | |
dfeec247 XL |
2569 | unknown_file_metadata(cx), |
2570 | UNKNOWN_LINE_NUMBER, | |
2571 | vtable_type, | |
2572 | true, | |
2573 | vtable, | |
2574 | None, | |
2575 | 0, | |
2576 | ); | |
abe05a73 XL |
2577 | } |
2578 | } | |
a1dfa0c6 | 2579 | |
60c5eb7d | 2580 | /// Creates an "extension" of an existing `DIScope` into another file. |
a1dfa0c6 XL |
2581 | pub fn extend_scope_to_file( |
2582 | cx: &CodegenCx<'ll, '_>, | |
2583 | scope_metadata: &'ll DIScope, | |
29967ef6 | 2584 | file: &SourceFile, |
a1dfa0c6 | 2585 | ) -> &'ll DILexicalBlock { |
29967ef6 | 2586 | let file_metadata = file_metadata(cx, file); |
dfeec247 | 2587 | unsafe { llvm::LLVMRustDIBuilderCreateLexicalBlockFile(DIB(cx), scope_metadata, file_metadata) } |
a1dfa0c6 | 2588 | } |