rustc_codegen_llvm/debuginfo/metadata/enums/
native.rs1use std::borrow::Cow;
2
3use libc::c_uint;
4use rustc_abi::{Size, TagEncoding, VariantIdx, Variants};
5use rustc_codegen_ssa::debuginfo::type_names::compute_debuginfo_type_name;
6use rustc_codegen_ssa::debuginfo::{tag_base_type, wants_c_like_enum_debuginfo};
7use rustc_codegen_ssa::traits::{ConstCodegenMethods, MiscCodegenMethods};
8use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
9use rustc_middle::{bug, ty};
10use smallvec::smallvec;
11
12use crate::common::{AsCCharPtr, CodegenCx};
13use crate::debuginfo::metadata::type_map::{self, Stub, StubInfo, UniqueTypeId};
14use crate::debuginfo::metadata::{
15 DINodeCreationResult, NO_GENERICS, SmallVec, UNKNOWN_LINE_NUMBER, create_member_type,
16 file_metadata, file_metadata_from_def_id, size_and_align_of, type_di_node,
17 unknown_file_metadata, visibility_di_flags,
18};
19use crate::debuginfo::utils::{DIB, create_DIArray, get_namespace_for_item};
20use crate::llvm;
21use crate::llvm::debuginfo::{DIFile, DIFlags, DIType};
22
23pub(super) fn build_enum_type_di_node<'ll, 'tcx>(
42 cx: &CodegenCx<'ll, 'tcx>,
43 unique_type_id: UniqueTypeId<'tcx>,
44) -> DINodeCreationResult<'ll> {
45 let enum_type = unique_type_id.expect_ty();
46 let &ty::Adt(enum_adt_def, _) = enum_type.kind() else {
47 ::rustc_middle::util::bug::bug_fmt(format_args!("build_enum_type_di_node() called with non-enum type: `{0:?}`",
enum_type))bug!("build_enum_type_di_node() called with non-enum type: `{:?}`", enum_type)
48 };
49
50 let containing_scope = get_namespace_for_item(cx, enum_adt_def.did());
51 let enum_type_and_layout = cx.layout_of(enum_type);
52 let enum_type_name = compute_debuginfo_type_name(cx.tcx, enum_type, false);
53
54 let visibility_flags = visibility_di_flags(cx, enum_adt_def.did(), enum_adt_def.did());
55
56 if !!wants_c_like_enum_debuginfo(cx.tcx, enum_type_and_layout) {
::core::panicking::panic("assertion failed: !wants_c_like_enum_debuginfo(cx.tcx, enum_type_and_layout)")
};assert!(!wants_c_like_enum_debuginfo(cx.tcx, enum_type_and_layout));
57
58 let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
59 Some(file_metadata_from_def_id(cx, Some(enum_adt_def.did())))
60 } else {
61 None
62 };
63
64 type_map::build_type_with_children(
65 cx,
66 type_map::stub(
67 cx,
68 Stub::Struct,
69 unique_type_id,
70 &enum_type_name,
71 def_location,
72 size_and_align_of(enum_type_and_layout),
73 Some(containing_scope),
74 visibility_flags,
75 ),
76 |cx, enum_type_di_node| {
77 let variant_member_infos: SmallVec<_> = enum_adt_def
81 .variant_range()
82 .map(|variant_index| VariantMemberInfo {
83 variant_index,
84 variant_name: Cow::from(enum_adt_def.variant(variant_index).name.as_str()),
85 variant_struct_type_di_node: super::build_enum_variant_struct_type_di_node(
86 cx,
87 enum_type_and_layout,
88 enum_type_di_node,
89 variant_index,
90 enum_adt_def.variant(variant_index),
91 enum_type_and_layout.for_variant(cx, variant_index),
92 visibility_flags,
93 ),
94 source_info: if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
95 Some(file_metadata_from_def_id(
96 cx,
97 Some(enum_adt_def.variant(variant_index).def_id),
98 ))
99 } else {
100 None
101 },
102 })
103 .collect();
104
105 let enum_adt_def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
106 Some(enum_adt_def.did())
107 } else {
108 None
109 };
110 {
let count = 0usize + 1usize;
let mut vec = ::smallvec::SmallVec::new();
if count <= vec.inline_size() {
vec.push(build_enum_variant_part_di_node(cx, enum_type_and_layout,
enum_type_di_node, enum_adt_def_id,
&variant_member_infos[..]));
vec
} else {
::smallvec::SmallVec::from_vec(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[build_enum_variant_part_di_node(cx, enum_type_and_layout,
enum_type_di_node, enum_adt_def_id,
&variant_member_infos[..])])))
}
}smallvec![build_enum_variant_part_di_node(
111 cx,
112 enum_type_and_layout,
113 enum_type_di_node,
114 enum_adt_def_id,
115 &variant_member_infos[..],
116 )]
117 },
118 NO_GENERICS,
121 )
122}
123
124pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
142 cx: &CodegenCx<'ll, 'tcx>,
143 unique_type_id: UniqueTypeId<'tcx>,
144) -> DINodeCreationResult<'ll> {
145 let coroutine_type = unique_type_id.expect_ty();
146 let &ty::Coroutine(coroutine_def_id, coroutine_args) = coroutine_type.kind() else {
147 ::rustc_middle::util::bug::bug_fmt(format_args!("build_coroutine_di_node() called with non-coroutine type: `{0:?}`",
coroutine_type))bug!("build_coroutine_di_node() called with non-coroutine type: `{:?}`", coroutine_type)
148 };
149
150 let containing_scope = get_namespace_for_item(cx, coroutine_def_id);
151 let coroutine_type_and_layout = cx.layout_of(coroutine_type);
152
153 if !!wants_c_like_enum_debuginfo(cx.tcx, coroutine_type_and_layout) {
::core::panicking::panic("assertion failed: !wants_c_like_enum_debuginfo(cx.tcx, coroutine_type_and_layout)")
};assert!(!wants_c_like_enum_debuginfo(cx.tcx, coroutine_type_and_layout));
154
155 let coroutine_type_name = compute_debuginfo_type_name(cx.tcx, coroutine_type, false);
156
157 let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
158 Some(file_metadata_from_def_id(cx, Some(coroutine_def_id)))
159 } else {
160 None
161 };
162
163 type_map::build_type_with_children(
164 cx,
165 type_map::stub(
166 cx,
167 Stub::Struct,
168 unique_type_id,
169 &coroutine_type_name,
170 def_location,
171 size_and_align_of(coroutine_type_and_layout),
172 Some(containing_scope),
173 DIFlags::FlagZero,
174 ),
175 |cx, coroutine_type_di_node| {
176 let coroutine_layout =
177 cx.tcx.coroutine_layout(coroutine_def_id, coroutine_args).unwrap();
178
179 let Variants::Multiple { tag_encoding: TagEncoding::Direct, ref variants, .. } =
180 coroutine_type_and_layout.variants
181 else {
182 ::rustc_middle::util::bug::bug_fmt(format_args!("Encountered coroutine with non-direct-tag layout: {0:?}",
coroutine_type_and_layout))bug!(
183 "Encountered coroutine with non-direct-tag layout: {:?}",
184 coroutine_type_and_layout
185 )
186 };
187
188 let common_upvar_names =
189 cx.tcx.closure_saved_names_of_captured_variables(coroutine_def_id);
190
191 let variant_struct_type_di_nodes: SmallVec<_> = variants
193 .indices()
194 .map(|variant_index| {
195 let variant_name = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", variant_index.as_usize()))
})format!("{}", variant_index.as_usize()).into();
199
200 let span = coroutine_layout.variant_source_info[variant_index].span;
201 let source_info = if !span.is_dummy() {
202 let loc = cx.lookup_debug_loc(span.lo());
203 Some((file_metadata(cx, &loc.file), loc.line))
204 } else {
205 None
206 };
207
208 VariantMemberInfo {
209 variant_index,
210 variant_name,
211 variant_struct_type_di_node:
212 super::build_coroutine_variant_struct_type_di_node(
213 cx,
214 variant_index,
215 coroutine_type_and_layout,
216 coroutine_type_di_node,
217 coroutine_layout,
218 common_upvar_names,
219 ),
220 source_info,
221 }
222 })
223 .collect();
224
225 let coroutine_def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
226 Some(coroutine_def_id)
227 } else {
228 None
229 };
230 {
let count = 0usize + 1usize;
let mut vec = ::smallvec::SmallVec::new();
if count <= vec.inline_size() {
vec.push(build_enum_variant_part_di_node(cx,
coroutine_type_and_layout, coroutine_type_di_node,
coroutine_def_id, &variant_struct_type_di_nodes[..]));
vec
} else {
::smallvec::SmallVec::from_vec(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[build_enum_variant_part_di_node(cx,
coroutine_type_and_layout, coroutine_type_di_node,
coroutine_def_id, &variant_struct_type_di_nodes[..])])))
}
}smallvec![build_enum_variant_part_di_node(
231 cx,
232 coroutine_type_and_layout,
233 coroutine_type_di_node,
234 coroutine_def_id,
235 &variant_struct_type_di_nodes[..],
236 )]
237 },
238 NO_GENERICS,
241 )
242}
243
244fn build_enum_variant_part_di_node<'ll, 'tcx>(
259 cx: &CodegenCx<'ll, 'tcx>,
260 enum_type_and_layout: TyAndLayout<'tcx>,
261 enum_type_di_node: &'ll DIType,
262 enum_type_def_id: Option<rustc_span::def_id::DefId>,
263 variant_member_infos: &[VariantMemberInfo<'_, 'll>],
264) -> &'ll DIType {
265 let tag_member_di_node =
266 build_discr_member_di_node(cx, enum_type_and_layout, enum_type_di_node);
267
268 let variant_part_unique_type_id =
269 UniqueTypeId::for_enum_variant_part(cx.tcx, enum_type_and_layout.ty);
270
271 let (file_metadata, line_number) = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers
272 {
273 file_metadata_from_def_id(cx, enum_type_def_id)
274 } else {
275 (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
276 };
277
278 let stub = StubInfo::new(
279 cx,
280 variant_part_unique_type_id,
281 |cx, variant_part_unique_type_id_str| unsafe {
282 let variant_part_name = "";
283 llvm::LLVMRustDIBuilderCreateVariantPart(
284 DIB(cx),
285 enum_type_di_node,
286 variant_part_name.as_c_char_ptr(),
287 variant_part_name.len(),
288 file_metadata,
289 line_number,
290 enum_type_and_layout.size.bits(),
291 enum_type_and_layout.align.bits() as u32,
292 DIFlags::FlagZero,
293 tag_member_di_node,
294 create_DIArray(DIB(cx), &[]),
295 variant_part_unique_type_id_str.as_c_char_ptr(),
296 variant_part_unique_type_id_str.len(),
297 )
298 },
299 );
300
301 type_map::build_type_with_children(
302 cx,
303 stub,
304 |cx, variant_part_di_node| {
305 variant_member_infos
306 .iter()
307 .map(|variant_member_info| {
308 build_enum_variant_member_di_node(
309 cx,
310 enum_type_and_layout,
311 variant_part_di_node,
312 variant_member_info,
313 )
314 })
315 .collect()
316 },
317 NO_GENERICS,
318 )
319 .di_node
320}
321
322fn build_discr_member_di_node<'ll, 'tcx>(
340 cx: &CodegenCx<'ll, 'tcx>,
341 enum_or_coroutine_type_and_layout: TyAndLayout<'tcx>,
342 enum_or_coroutine_type_di_node: &'ll DIType,
343) -> Option<&'ll DIType> {
344 let tag_name = match enum_or_coroutine_type_and_layout.ty.kind() {
345 ty::Coroutine(..) => "__state",
346 _ => "",
347 };
348
349 let containing_scope = enum_or_coroutine_type_di_node;
356
357 match enum_or_coroutine_type_and_layout.layout.variants() {
358 &Variants::Single { .. } | &Variants::Empty => None,
360
361 &Variants::Multiple { tag_field, .. } => {
362 let tag_base_type = tag_base_type(cx.tcx, enum_or_coroutine_type_and_layout);
363 let ty = type_di_node(cx, tag_base_type);
364 let file = unknown_file_metadata(cx);
365
366 let layout = cx.layout_of(tag_base_type);
367
368 Some(create_member_type(
369 cx,
370 containing_scope,
371 &tag_name,
372 file,
373 UNKNOWN_LINE_NUMBER,
374 layout,
375 enum_or_coroutine_type_and_layout.fields.offset(tag_field.as_usize()),
376 DIFlags::FlagArtificial,
377 ty,
378 ))
379 }
380 }
381}
382
383fn build_enum_variant_member_di_node<'ll, 'tcx>(
424 cx: &CodegenCx<'ll, 'tcx>,
425 enum_type_and_layout: TyAndLayout<'tcx>,
426 variant_part_di_node: &'ll DIType,
427 variant_member_info: &VariantMemberInfo<'_, 'll>,
428) -> &'ll DIType {
429 let variant_index = variant_member_info.variant_index;
430 let discr_value = super::compute_discriminant_value(cx, enum_type_and_layout, variant_index);
431
432 let (file_di_node, line_number) = variant_member_info
433 .source_info
434 .unwrap_or_else(|| (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER));
435
436 let discr = discr_value.opt_single_val().map(|value| {
437 let tag_base_type = tag_base_type(cx.tcx, enum_type_and_layout);
438 let size = cx.size_of(tag_base_type);
439 cx.const_uint_big(cx.type_ix(size.bits()), value)
440 });
441
442 unsafe {
443 llvm::LLVMRustDIBuilderCreateVariantMemberType(
444 DIB(cx),
445 variant_part_di_node,
446 variant_member_info.variant_name.as_c_char_ptr(),
447 variant_member_info.variant_name.len(),
448 file_di_node,
449 line_number,
450 enum_type_and_layout.size.bits(),
451 enum_type_and_layout.align.bits() as u32,
452 Size::ZERO.bits(),
453 discr,
454 DIFlags::FlagZero,
455 variant_member_info.variant_struct_type_di_node,
456 )
457 }
458}
459
460struct VariantMemberInfo<'a, 'll> {
475 variant_index: VariantIdx,
476 variant_name: Cow<'a, str>,
477 variant_struct_type_di_node: &'ll DIType,
478 source_info: Option<(&'ll DIFile, c_uint)>,
479}