1
Fork 0

Rollup merge of #138674 - oli-obk:llvm-cleanups, r=compiler-errors

Various codegen_llvm cleanups

Mostly just adding safe wrappers and deduplicating code
This commit is contained in:
Matthias Krüger 2025-03-19 08:17:19 +01:00 committed by GitHub
commit 5661e98058
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 206 additions and 205 deletions

View file

@ -2,6 +2,7 @@ use std::borrow::Cow;
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::{iter, ptr}; use std::{iter, ptr};
use libc::{c_char, c_longlong, c_uint}; use libc::{c_char, c_longlong, c_uint};
@ -38,8 +39,8 @@ use crate::debuginfo::metadata::type_map::build_type_with_children;
use crate::debuginfo::utils::{WidePtrKind, wide_pointer_kind}; use crate::debuginfo::utils::{WidePtrKind, wide_pointer_kind};
use crate::llvm; use crate::llvm;
use crate::llvm::debuginfo::{ use crate::llvm::debuginfo::{
DIDescriptor, DIFile, DIFlags, DILexicalBlock, DIScope, DIType, DebugEmissionKind, DIBasicType, DIBuilder, DICompositeType, DIDescriptor, DIFile, DIFlags, DILexicalBlock,
DebugNameTableKind, DIScope, DIType, DebugEmissionKind, DebugNameTableKind,
}; };
use crate::value::Value; use crate::value::Value;
@ -68,7 +69,8 @@ pub(super) const UNKNOWN_COLUMN_NUMBER: c_uint = 0;
const NO_SCOPE_METADATA: Option<&DIScope> = None; const NO_SCOPE_METADATA: Option<&DIScope> = None;
/// A function that returns an empty list of generic parameter debuginfo nodes. /// A function that returns an empty list of generic parameter debuginfo nodes.
const NO_GENERICS: for<'ll> fn(&CodegenCx<'ll, '_>) -> SmallVec<&'ll DIType> = |_| SmallVec::new(); const NO_GENERICS: for<'ll> fn(&CodegenCx<'ll, '_>) -> SmallVec<Option<&'ll DIType>> =
|_| SmallVec::new();
// SmallVec is used quite a bit in this module, so create a shorthand. // SmallVec is used quite a bit in this module, so create a shorthand.
// The actual number of elements is not so important. // The actual number of elements is not so important.
@ -243,7 +245,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
cx, cx,
owner, owner,
addr_field_name, addr_field_name,
(addr_field.size, addr_field.align.abi), addr_field,
layout.fields.offset(WIDE_PTR_ADDR), layout.fields.offset(WIDE_PTR_ADDR),
DIFlags::FlagZero, DIFlags::FlagZero,
data_ptr_type_di_node, data_ptr_type_di_node,
@ -253,7 +255,7 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
cx, cx,
owner, owner,
extra_field_name, extra_field_name,
(extra_field.size, extra_field.align.abi), extra_field,
layout.fields.offset(WIDE_PTR_EXTRA), layout.fields.offset(WIDE_PTR_EXTRA),
DIFlags::FlagZero, DIFlags::FlagZero,
type_di_node(cx, extra_field.ty), type_di_node(cx, extra_field.ty),
@ -311,12 +313,7 @@ fn build_subroutine_type_di_node<'ll, 'tcx>(
debug_context(cx).type_map.unique_id_to_di_node.borrow_mut().remove(&unique_type_id); debug_context(cx).type_map.unique_id_to_di_node.borrow_mut().remove(&unique_type_id);
let fn_di_node = unsafe { let fn_di_node = create_subroutine_type(cx, create_DIArray(DIB(cx), &signature_di_nodes[..]));
llvm::LLVMRustDIBuilderCreateSubroutineType(
DIB(cx),
create_DIArray(DIB(cx), &signature_di_nodes[..]),
)
};
// This is actually a function pointer, so wrap it in pointer DI. // This is actually a function pointer, so wrap it in pointer DI.
let name = compute_debuginfo_type_name(cx.tcx, fn_ty, false); let name = compute_debuginfo_type_name(cx.tcx, fn_ty, false);
@ -340,6 +337,13 @@ fn build_subroutine_type_di_node<'ll, 'tcx>(
DINodeCreationResult::new(di_node, false) DINodeCreationResult::new(di_node, false)
} }
pub(super) fn create_subroutine_type<'ll>(
cx: &CodegenCx<'ll, '_>,
signature: &'ll DICompositeType,
) -> &'ll DICompositeType {
unsafe { llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(cx), signature) }
}
/// Create debuginfo for `dyn SomeTrait` types. Currently these are empty structs /// Create debuginfo for `dyn SomeTrait` types. Currently these are empty structs
/// we with the correct type name (e.g. "dyn SomeTrait<Foo, Item=u32> + Sync"). /// we with the correct type name (e.g. "dyn SomeTrait<Foo, Item=u32> + Sync").
fn build_dyn_type_di_node<'ll, 'tcx>( fn build_dyn_type_di_node<'ll, 'tcx>(
@ -487,26 +491,22 @@ pub(crate) fn type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) ->
// FIXME(mw): Cache this via a regular UniqueTypeId instead of an extra field in the debug context. // FIXME(mw): Cache this via a regular UniqueTypeId instead of an extra field in the debug context.
fn recursion_marker_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> &'ll DIType { fn recursion_marker_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> &'ll DIType {
*debug_context(cx).recursion_marker_type.get_or_init(move || { *debug_context(cx).recursion_marker_type.get_or_init(move || {
unsafe { // The choice of type here is pretty arbitrary -
// The choice of type here is pretty arbitrary - // anything reading the debuginfo for a recursive
// anything reading the debuginfo for a recursive // type is going to see *something* weird - the only
// type is going to see *something* weird - the only // question is what exactly it will see.
// question is what exactly it will see. //
// // FIXME: the name `<recur_type>` does not fit the naming scheme
// FIXME: the name `<recur_type>` does not fit the naming scheme // of other types.
// of other types. //
// // FIXME: it might make sense to use an actual pointer type here
// FIXME: it might make sense to use an actual pointer type here // so that debuggers can show the address.
// so that debuggers can show the address. create_basic_type(
let name = "<recur_type>"; cx,
llvm::LLVMRustDIBuilderCreateBasicType( "<recur_type>",
DIB(cx), cx.tcx.data_layout.pointer_size,
name.as_c_char_ptr(), dwarf_const::DW_ATE_unsigned,
name.len(), )
cx.tcx.data_layout.pointer_size.bits(),
dwarf_const::DW_ATE_unsigned,
)
}
}) })
} }
@ -620,42 +620,38 @@ pub(crate) fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFi
let source = let source =
cx.sess().opts.unstable_opts.embed_source.then_some(()).and(source_file.src.as_ref()); cx.sess().opts.unstable_opts.embed_source.then_some(()).and(source_file.src.as_ref());
unsafe { create_file(DIB(cx), &file_name, &directory, &hash_value, hash_kind, source)
llvm::LLVMRustDIBuilderCreateFile(
DIB(cx),
file_name.as_c_char_ptr(),
file_name.len(),
directory.as_c_char_ptr(),
directory.len(),
hash_kind,
hash_value.as_c_char_ptr(),
hash_value.len(),
source.map_or(ptr::null(), |x| x.as_c_char_ptr()),
source.map_or(0, |x| x.len()),
)
}
} }
} }
fn unknown_file_metadata<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile { fn unknown_file_metadata<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile {
debug_context(cx).created_files.borrow_mut().entry(None).or_insert_with(|| unsafe { debug_context(cx).created_files.borrow_mut().entry(None).or_insert_with(|| {
let file_name = "<unknown>"; create_file(DIB(cx), "<unknown>", "", "", llvm::ChecksumKind::None, None)
let directory = ""; })
let hash_value = ""; }
fn create_file<'ll>(
builder: &DIBuilder<'ll>,
file_name: &str,
directory: &str,
hash_value: &str,
hash_kind: llvm::ChecksumKind,
source: Option<&Arc<String>>,
) -> &'ll DIFile {
unsafe {
llvm::LLVMRustDIBuilderCreateFile( llvm::LLVMRustDIBuilderCreateFile(
DIB(cx), builder,
file_name.as_c_char_ptr(), file_name.as_c_char_ptr(),
file_name.len(), file_name.len(),
directory.as_c_char_ptr(), directory.as_c_char_ptr(),
directory.len(), directory.len(),
llvm::ChecksumKind::None, hash_kind,
hash_value.as_c_char_ptr(), hash_value.as_c_char_ptr(),
hash_value.len(), hash_value.len(),
ptr::null(), source.map_or(ptr::null(), |x| x.as_c_char_ptr()),
0, source.map_or(0, |x| x.len()),
) )
}) }
} }
trait MsvcBasicName { trait MsvcBasicName {
@ -742,7 +738,7 @@ fn build_cpp_f16_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> DINodeCreation
cx, cx,
float_di_node, float_di_node,
"bits", "bits",
cx.size_and_align_of(bits_ty), cx.layout_of(bits_ty),
Size::ZERO, Size::ZERO,
DIFlags::FlagZero, DIFlags::FlagZero,
type_di_node(cx, bits_ty), type_di_node(cx, bits_ty),
@ -788,15 +784,7 @@ fn build_basic_type_di_node<'ll, 'tcx>(
_ => bug!("debuginfo::build_basic_type_di_node - `t` is invalid type"), _ => bug!("debuginfo::build_basic_type_di_node - `t` is invalid type"),
}; };
let ty_di_node = unsafe { let ty_di_node = create_basic_type(cx, name, cx.size_of(t), encoding);
llvm::LLVMRustDIBuilderCreateBasicType(
DIB(cx),
name.as_c_char_ptr(),
name.len(),
cx.size_of(t).bits(),
encoding,
)
};
if !cpp_like_debuginfo { if !cpp_like_debuginfo {
return DINodeCreationResult::new(ty_di_node, false); return DINodeCreationResult::new(ty_di_node, false);
@ -824,6 +812,23 @@ fn build_basic_type_di_node<'ll, 'tcx>(
DINodeCreationResult::new(typedef_di_node, false) DINodeCreationResult::new(typedef_di_node, false)
} }
fn create_basic_type<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>,
name: &str,
size: Size,
encoding: u32,
) -> &'ll DIBasicType {
unsafe {
llvm::LLVMRustDIBuilderCreateBasicType(
DIB(cx),
name.as_c_char_ptr(),
name.len(),
size.bits(),
encoding,
)
}
}
fn build_foreign_type_di_node<'ll, 'tcx>( fn build_foreign_type_di_node<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>, cx: &CodegenCx<'ll, 'tcx>,
t: Ty<'tcx>, t: Ty<'tcx>,
@ -929,17 +934,13 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>(
}; };
unsafe { unsafe {
let compile_unit_file = llvm::LLVMRustDIBuilderCreateFile( let compile_unit_file = create_file(
debug_context.builder.as_ref(), debug_context.builder.as_ref(),
name_in_debuginfo.as_c_char_ptr(), &name_in_debuginfo,
name_in_debuginfo.len(), &work_dir,
work_dir.as_c_char_ptr(), "",
work_dir.len(),
llvm::ChecksumKind::None, llvm::ChecksumKind::None,
ptr::null(), None,
0,
ptr::null(),
0,
); );
let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit( let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit(
@ -971,7 +972,7 @@ fn build_field_di_node<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>, cx: &CodegenCx<'ll, 'tcx>,
owner: &'ll DIScope, owner: &'ll DIScope,
name: &str, name: &str,
size_and_align: (Size, Align), layout: TyAndLayout<'tcx>,
offset: Size, offset: Size,
flags: DIFlags, flags: DIFlags,
type_di_node: &'ll DIType, type_di_node: &'ll DIType,
@ -983,6 +984,30 @@ fn build_field_di_node<'ll, 'tcx>(
} else { } else {
(unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER) (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
}; };
create_member_type(
cx,
owner,
name,
file_metadata,
line_number,
layout,
offset,
flags,
type_di_node,
)
}
fn create_member_type<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>,
owner: &'ll DIScope,
name: &str,
file_metadata: &'ll DIType,
line_number: u32,
layout: TyAndLayout<'tcx>,
offset: Size,
flags: DIFlags,
type_di_node: &'ll DIType,
) -> &'ll DIType {
unsafe { unsafe {
llvm::LLVMRustDIBuilderCreateMemberType( llvm::LLVMRustDIBuilderCreateMemberType(
DIB(cx), DIB(cx),
@ -991,8 +1016,8 @@ fn build_field_di_node<'ll, 'tcx>(
name.len(), name.len(),
file_metadata, file_metadata,
line_number, line_number,
size_and_align.0.bits(), layout.size.bits(),
size_and_align.1.bits() as u32, layout.align.abi.bits() as u32,
offset.bits(), offset.bits(),
flags, flags,
type_di_node, type_di_node,
@ -1076,7 +1101,7 @@ fn build_struct_type_di_node<'ll, 'tcx>(
cx, cx,
owner, owner,
&field_name[..], &field_name[..],
(field_layout.size, field_layout.align.abi), field_layout,
struct_type_and_layout.fields.offset(i), struct_type_and_layout.fields.offset(i),
visibility_di_flags(cx, f.did, adt_def.did()), visibility_di_flags(cx, f.did, adt_def.did()),
type_di_node(cx, field_layout.ty), type_di_node(cx, field_layout.ty),
@ -1126,7 +1151,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>(
cx, cx,
closure_or_coroutine_di_node, closure_or_coroutine_di_node,
capture_name.as_str(), capture_name.as_str(),
cx.size_and_align_of(up_var_ty), cx.layout_of(up_var_ty),
layout.fields.offset(index), layout.fields.offset(index),
DIFlags::FlagZero, DIFlags::FlagZero,
type_di_node(cx, up_var_ty), type_di_node(cx, up_var_ty),
@ -1171,7 +1196,7 @@ fn build_tuple_type_di_node<'ll, 'tcx>(
cx, cx,
tuple_di_node, tuple_di_node,
&tuple_field_name(index), &tuple_field_name(index),
cx.size_and_align_of(component_type), cx.layout_of(component_type),
tuple_type_and_layout.fields.offset(index), tuple_type_and_layout.fields.offset(index),
DIFlags::FlagZero, DIFlags::FlagZero,
type_di_node(cx, component_type), type_di_node(cx, component_type),
@ -1269,7 +1294,7 @@ fn build_union_type_di_node<'ll, 'tcx>(
cx, cx,
owner, owner,
f.name.as_str(), f.name.as_str(),
size_and_align_of(field_layout), field_layout,
Size::ZERO, Size::ZERO,
DIFlags::FlagZero, DIFlags::FlagZero,
type_di_node(cx, field_layout.ty), type_di_node(cx, field_layout.ty),
@ -1287,32 +1312,33 @@ fn build_union_type_di_node<'ll, 'tcx>(
fn build_generic_type_param_di_nodes<'ll, 'tcx>( fn build_generic_type_param_di_nodes<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>, cx: &CodegenCx<'ll, 'tcx>,
ty: Ty<'tcx>, ty: Ty<'tcx>,
) -> SmallVec<&'ll DIType> { ) -> SmallVec<Option<&'ll DIType>> {
if let ty::Adt(def, args) = *ty.kind() { if let ty::Adt(def, args) = *ty.kind() {
if args.types().next().is_some() { let generics = cx.tcx.generics_of(def.did());
let generics = cx.tcx.generics_of(def.did()); return get_template_parameters(cx, generics, args);
let names = get_parameter_names(cx, generics); }
let template_params: SmallVec<_> = iter::zip(args, names)
.filter_map(|(kind, name)| {
kind.as_type().map(|ty| {
let actual_type = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty);
let actual_type_di_node = type_di_node(cx, actual_type);
let name = name.as_str();
unsafe {
llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
DIB(cx),
None,
name.as_c_char_ptr(),
name.len(),
actual_type_di_node,
)
}
})
})
.collect();
return template_params; return smallvec![];
} }
pub(super) fn get_template_parameters<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>,
generics: &ty::Generics,
args: ty::GenericArgsRef<'tcx>,
) -> SmallVec<Option<&'ll DIType>> {
if args.types().next().is_some() {
let names = get_parameter_names(cx, generics);
let template_params: SmallVec<_> = iter::zip(args, names)
.filter_map(|(kind, name)| {
kind.as_type().map(|ty| {
let actual_type = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty);
let actual_type_di_node = type_di_node(cx, actual_type);
Some(cx.create_template_type_parameter(name.as_str(), actual_type_di_node))
})
})
.collect();
return template_params;
} }
return smallvec![]; return smallvec![];
@ -1416,7 +1442,9 @@ fn build_vtable_type_di_node<'ll, 'tcx>(
let void_pointer_ty = Ty::new_imm_ptr(tcx, tcx.types.unit); let void_pointer_ty = Ty::new_imm_ptr(tcx, tcx.types.unit);
let void_pointer_type_di_node = type_di_node(cx, void_pointer_ty); let void_pointer_type_di_node = type_di_node(cx, void_pointer_ty);
let usize_di_node = type_di_node(cx, tcx.types.usize); let usize_di_node = type_di_node(cx, tcx.types.usize);
let (pointer_size, pointer_align) = cx.size_and_align_of(void_pointer_ty); let pointer_layout = cx.layout_of(void_pointer_ty);
let pointer_size = pointer_layout.size;
let pointer_align = pointer_layout.align.abi;
// If `usize` is not pointer-sized and -aligned then the size and alignment computations // If `usize` is not pointer-sized and -aligned then the size and alignment computations
// for the vtable as a whole would be wrong. Let's make sure this holds even on weird // for the vtable as a whole would be wrong. Let's make sure this holds even on weird
// platforms. // platforms.
@ -1472,7 +1500,7 @@ fn build_vtable_type_di_node<'ll, 'tcx>(
cx, cx,
vtable_type_di_node, vtable_type_di_node,
&field_name, &field_name,
(pointer_size, pointer_align), pointer_layout,
field_offset, field_offset,
DIFlags::FlagZero, DIFlags::FlagZero,
field_type_di_node, field_type_di_node,

View file

@ -17,8 +17,8 @@ use crate::debuginfo::metadata::enums::DiscrResult;
use crate::debuginfo::metadata::type_map::{self, Stub, UniqueTypeId}; use crate::debuginfo::metadata::type_map::{self, Stub, UniqueTypeId};
use crate::debuginfo::metadata::{ use crate::debuginfo::metadata::{
DINodeCreationResult, NO_GENERICS, NO_SCOPE_METADATA, SmallVec, UNKNOWN_LINE_NUMBER, DINodeCreationResult, NO_GENERICS, NO_SCOPE_METADATA, SmallVec, UNKNOWN_LINE_NUMBER,
build_field_di_node, file_metadata, file_metadata_from_def_id, size_and_align_of, type_di_node, build_field_di_node, create_member_type, file_metadata, file_metadata_from_def_id,
unknown_file_metadata, visibility_di_flags, size_and_align_of, type_di_node, unknown_file_metadata, visibility_di_flags,
}; };
use crate::debuginfo::utils::DIB; use crate::debuginfo::utils::DIB;
use crate::llvm::debuginfo::{DIFile, DIFlags, DIType}; use crate::llvm::debuginfo::{DIFile, DIFlags, DIType};
@ -370,9 +370,9 @@ fn build_single_variant_union_fields<'ll, 'tcx>(
cx, cx,
enum_type_di_node, enum_type_di_node,
&variant_union_field_name(variant_index), &variant_union_field_name(variant_index),
// NOTE: We use the size and align of the entire type, not from variant_layout // NOTE: We use the layout of the entire type, not from variant_layout
// since the later is sometimes smaller (if it has fewer fields). // since the later is sometimes smaller (if it has fewer fields).
size_and_align_of(enum_type_and_layout), enum_type_and_layout,
Size::ZERO, Size::ZERO,
visibility_flags, visibility_flags,
variant_struct_type_wrapper_di_node, variant_struct_type_wrapper_di_node,
@ -560,7 +560,7 @@ fn build_variant_struct_wrapper_type_di_node<'ll, 'tcx>(
cx, cx,
wrapper_struct_type_di_node, wrapper_struct_type_di_node,
"value", "value",
size_and_align_of(enum_or_coroutine_type_and_layout), enum_or_coroutine_type_and_layout,
Size::ZERO, Size::ZERO,
DIFlags::FlagZero, DIFlags::FlagZero,
variant_struct_type_di_node, variant_struct_type_di_node,
@ -820,7 +820,6 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
.unwrap_or_else(|| (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)); .unwrap_or_else(|| (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER));
let field_name = variant_union_field_name(variant_member_info.variant_index); let field_name = variant_union_field_name(variant_member_info.variant_index);
let (size, align) = size_and_align_of(enum_type_and_layout);
let variant_struct_type_wrapper = build_variant_struct_wrapper_type_di_node( let variant_struct_type_wrapper = build_variant_struct_wrapper_type_di_node(
cx, cx,
@ -840,27 +839,23 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
}, },
); );
// We use LLVMRustDIBuilderCreateMemberType() member type directly because // We use create_member_type() member type directly because
// the build_field_di_node() function does not support specifying a source location, // the build_field_di_node() function does not support specifying a source location,
// which is something that we don't do anywhere else. // which is something that we don't do anywhere else.
unsafe { create_member_type(
llvm::LLVMRustDIBuilderCreateMemberType( cx,
DIB(cx), enum_type_di_node,
enum_type_di_node, &field_name,
field_name.as_c_char_ptr(), file_di_node,
field_name.len(), line_number,
file_di_node, // NOTE: We use the layout of the entire type, not from variant_layout
line_number, // since the later is sometimes smaller (if it has fewer fields).
// NOTE: We use the size and align of the entire type, not from variant_layout enum_type_and_layout,
// since the later is sometimes smaller (if it has fewer fields). // Union fields are always at offset zero
size.bits(), Size::ZERO,
align.bits() as u32, di_flags,
// Union fields are always at offset zero variant_struct_type_wrapper,
Size::ZERO.bits(), )
di_flags,
variant_struct_type_wrapper,
)
}
})); }));
assert_eq!( assert_eq!(
@ -874,7 +869,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
if is_128_bits { if is_128_bits {
let type_di_node = type_di_node(cx, cx.tcx.types.u64); let type_di_node = type_di_node(cx, cx.tcx.types.u64);
let size_and_align = cx.size_and_align_of(cx.tcx.types.u64); let u64_layout = cx.layout_of(cx.tcx.types.u64);
let (lo_offset, hi_offset) = match cx.tcx.data_layout.endian { let (lo_offset, hi_offset) = match cx.tcx.data_layout.endian {
Endian::Little => (0, 8), Endian::Little => (0, 8),
@ -889,7 +884,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
cx, cx,
enum_type_di_node, enum_type_di_node,
TAG_FIELD_NAME_128_LO, TAG_FIELD_NAME_128_LO,
size_and_align, u64_layout,
lo_offset, lo_offset,
di_flags, di_flags,
type_di_node, type_di_node,
@ -900,7 +895,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
cx, cx,
enum_type_di_node, enum_type_di_node,
TAG_FIELD_NAME_128_HI, TAG_FIELD_NAME_128_HI,
size_and_align, u64_layout,
hi_offset, hi_offset,
DIFlags::FlagZero, DIFlags::FlagZero,
type_di_node, type_di_node,
@ -911,7 +906,7 @@ fn build_union_fields_for_direct_tag_enum_or_coroutine<'ll, 'tcx>(
cx, cx,
enum_type_di_node, enum_type_di_node,
TAG_FIELD_NAME, TAG_FIELD_NAME,
cx.size_and_align_of(enum_type_and_layout.field(cx, tag_field).ty), enum_type_and_layout.field(cx, tag_field),
enum_type_and_layout.fields.offset(tag_field), enum_type_and_layout.fields.offset(tag_field),
di_flags, di_flags,
tag_base_type_di_node, tag_base_type_di_node,

View file

@ -249,7 +249,7 @@ fn build_enum_variant_struct_type_di_node<'ll, 'tcx>(
cx, cx,
struct_type_di_node, struct_type_di_node,
&field_name, &field_name,
(field_layout.size, field_layout.align.abi), field_layout,
variant_layout.fields.offset(field_index), variant_layout.fields.offset(field_index),
di_flags, di_flags,
type_di_node(cx, field_layout.ty), type_di_node(cx, field_layout.ty),
@ -332,7 +332,7 @@ fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>(
cx, cx,
variant_struct_type_di_node, variant_struct_type_di_node,
&field_name, &field_name,
cx.size_and_align_of(field_type), cx.layout_of(field_type),
variant_layout.fields.offset(field_index), variant_layout.fields.offset(field_index),
DIFlags::FlagZero, DIFlags::FlagZero,
type_di_node(cx, field_type), type_di_node(cx, field_type),
@ -352,7 +352,7 @@ fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>(
cx, cx,
variant_struct_type_di_node, variant_struct_type_di_node,
upvar_name.as_str(), upvar_name.as_str(),
cx.size_and_align_of(upvar_ty), cx.layout_of(upvar_ty),
coroutine_type_and_layout.fields.offset(index), coroutine_type_and_layout.fields.offset(index),
DIFlags::FlagZero, DIFlags::FlagZero,
type_di_node(cx, upvar_ty), type_di_node(cx, upvar_ty),
@ -363,6 +363,7 @@ fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>(
state_specific_fields.into_iter().chain(common_fields).collect() state_specific_fields.into_iter().chain(common_fields).collect()
}, },
// FIXME: this is a no-op. `build_generic_type_param_di_nodes` only works for Adts.
|cx| build_generic_type_param_di_nodes(cx, coroutine_type_and_layout.ty), |cx| build_generic_type_param_di_nodes(cx, coroutine_type_and_layout.ty),
) )
.di_node .di_node

View file

@ -13,9 +13,9 @@ use smallvec::smallvec;
use crate::common::{AsCCharPtr, CodegenCx}; use crate::common::{AsCCharPtr, CodegenCx};
use crate::debuginfo::metadata::type_map::{self, Stub, StubInfo, UniqueTypeId}; use crate::debuginfo::metadata::type_map::{self, Stub, StubInfo, UniqueTypeId};
use crate::debuginfo::metadata::{ use crate::debuginfo::metadata::{
DINodeCreationResult, NO_GENERICS, SmallVec, UNKNOWN_LINE_NUMBER, file_metadata, DINodeCreationResult, NO_GENERICS, SmallVec, UNKNOWN_LINE_NUMBER, create_member_type,
file_metadata_from_def_id, size_and_align_of, type_di_node, unknown_file_metadata, file_metadata, file_metadata_from_def_id, size_and_align_of, type_di_node,
visibility_di_flags, unknown_file_metadata, visibility_di_flags,
}; };
use crate::debuginfo::utils::{DIB, create_DIArray, get_namespace_for_item}; use crate::debuginfo::utils::{DIB, create_DIArray, get_namespace_for_item};
use crate::llvm::debuginfo::{DIFile, DIFlags, DIType}; use crate::llvm::debuginfo::{DIFile, DIFlags, DIType};
@ -363,23 +363,22 @@ fn build_discr_member_di_node<'ll, 'tcx>(
&Variants::Multiple { tag_field, .. } => { &Variants::Multiple { tag_field, .. } => {
let tag_base_type = tag_base_type(cx.tcx, enum_or_coroutine_type_and_layout); let tag_base_type = tag_base_type(cx.tcx, enum_or_coroutine_type_and_layout);
let (size, align) = cx.size_and_align_of(tag_base_type); let ty = type_di_node(cx, tag_base_type);
let file = unknown_file_metadata(cx);
unsafe { let layout = cx.layout_of(tag_base_type);
Some(llvm::LLVMRustDIBuilderCreateMemberType(
DIB(cx), Some(create_member_type(
containing_scope, cx,
tag_name.as_c_char_ptr(), containing_scope,
tag_name.len(), &tag_name,
unknown_file_metadata(cx), file,
UNKNOWN_LINE_NUMBER, UNKNOWN_LINE_NUMBER,
size.bits(), layout,
align.bits() as u32, enum_or_coroutine_type_and_layout.fields.offset(tag_field),
enum_or_coroutine_type_and_layout.fields.offset(tag_field).bits(), DIFlags::FlagArtificial,
DIFlags::FlagArtificial, ty,
type_di_node(cx, tag_base_type), ))
))
}
} }
} }
} }

View file

@ -257,7 +257,7 @@ pub(super) fn build_type_with_children<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>, cx: &CodegenCx<'ll, 'tcx>,
stub_info: StubInfo<'ll, 'tcx>, stub_info: StubInfo<'ll, 'tcx>,
members: impl FnOnce(&CodegenCx<'ll, 'tcx>, &'ll DIType) -> SmallVec<&'ll DIType>, members: impl FnOnce(&CodegenCx<'ll, 'tcx>, &'ll DIType) -> SmallVec<&'ll DIType>,
generics: impl FnOnce(&CodegenCx<'ll, 'tcx>) -> SmallVec<&'ll DIType>, generics: impl FnOnce(&CodegenCx<'ll, 'tcx>) -> SmallVec<Option<&'ll DIType>>,
) -> DINodeCreationResult<'ll> { ) -> DINodeCreationResult<'ll> {
assert_eq!(debug_context(cx).type_map.di_node_for_unique_id(stub_info.unique_type_id), None); assert_eq!(debug_context(cx).type_map.di_node_for_unique_id(stub_info.unique_type_id), None);
@ -265,8 +265,7 @@ pub(super) fn build_type_with_children<'ll, 'tcx>(
let members: SmallVec<_> = let members: SmallVec<_> =
members(cx, stub_info.metadata).into_iter().map(|node| Some(node)).collect(); members(cx, stub_info.metadata).into_iter().map(|node| Some(node)).collect();
let generics: SmallVec<Option<&'ll DIType>> = let generics = generics(cx);
generics(cx).into_iter().map(|node| Some(node)).collect();
if !(members.is_empty() && generics.is_empty()) { if !(members.is_empty() && generics.is_empty()) {
unsafe { unsafe {

View file

@ -2,10 +2,11 @@
use std::cell::{OnceCell, RefCell}; use std::cell::{OnceCell, RefCell};
use std::ops::Range; use std::ops::Range;
use std::ptr;
use std::sync::Arc; use std::sync::Arc;
use std::{iter, ptr};
use libc::c_uint; use libc::c_uint;
use metadata::create_subroutine_type;
use rustc_abi::Size; use rustc_abi::Size;
use rustc_codegen_ssa::debuginfo::type_names; use rustc_codegen_ssa::debuginfo::type_names;
use rustc_codegen_ssa::mir::debuginfo::VariableKind::*; use rustc_codegen_ssa::mir::debuginfo::VariableKind::*;
@ -34,8 +35,8 @@ use crate::builder::Builder;
use crate::common::{AsCCharPtr, CodegenCx}; use crate::common::{AsCCharPtr, CodegenCx};
use crate::llvm; use crate::llvm;
use crate::llvm::debuginfo::{ use crate::llvm::debuginfo::{
DIArray, DIBuilderBox, DIFile, DIFlags, DILexicalBlock, DILocation, DISPFlags, DIScope, DIType, DIArray, DIBuilderBox, DIFile, DIFlags, DILexicalBlock, DILocation, DISPFlags, DIScope,
DIVariable, DITemplateTypeParameter, DIType, DIVariable,
}; };
use crate::value::Value; use crate::value::Value;
@ -251,7 +252,7 @@ struct DebugLoc {
col: u32, col: u32,
} }
impl CodegenCx<'_, '_> { impl<'ll> CodegenCx<'ll, '_> {
/// Looks up debug source information about a `BytePos`. /// Looks up debug source information about a `BytePos`.
// FIXME(eddyb) rename this to better indicate it's a duplicate of // FIXME(eddyb) rename this to better indicate it's a duplicate of
// `lookup_char_pos` rather than `dbg_loc`, perhaps by making // `lookup_char_pos` rather than `dbg_loc`, perhaps by making
@ -279,6 +280,22 @@ impl CodegenCx<'_, '_> {
DebugLoc { file, line, col } DebugLoc { file, line, col }
} }
} }
fn create_template_type_parameter(
&self,
name: &str,
actual_type_metadata: &'ll DIType,
) -> &'ll DITemplateTypeParameter {
unsafe {
llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
DIB(self),
None,
name.as_c_char_ptr(),
name.len(),
actual_type_metadata,
)
}
}
} }
impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
@ -325,10 +342,8 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
let loc = self.lookup_debug_loc(span.lo()); let loc = self.lookup_debug_loc(span.lo());
let file_metadata = file_metadata(self, &loc.file); let file_metadata = file_metadata(self, &loc.file);
let function_type_metadata = unsafe { let function_type_metadata =
let fn_signature = get_function_signature(self, fn_abi); create_subroutine_type(self, get_function_signature(self, fn_abi));
llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(self), fn_signature)
};
let mut name = String::with_capacity(64); let mut name = String::with_capacity(64);
type_names::push_item_name(tcx, def_id, false, &mut name); type_names::push_item_name(tcx, def_id, false, &mut name);
@ -471,46 +486,10 @@ impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
generics: &ty::Generics, generics: &ty::Generics,
args: GenericArgsRef<'tcx>, args: GenericArgsRef<'tcx>,
) -> &'ll DIArray { ) -> &'ll DIArray {
if args.types().next().is_none() { let template_params = metadata::get_template_parameters(cx, generics, args);
return create_DIArray(DIB(cx), &[]);
}
// Again, only create type information if full debuginfo is enabled
let template_params: Vec<_> = if cx.sess().opts.debuginfo == DebugInfo::Full {
let names = get_parameter_names(cx, generics);
iter::zip(args, names)
.filter_map(|(kind, name)| {
kind.as_type().map(|ty| {
let actual_type = cx.tcx.normalize_erasing_regions(cx.typing_env(), ty);
let actual_type_metadata = type_di_node(cx, actual_type);
let name = name.as_str();
unsafe {
Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
DIB(cx),
None,
name.as_c_char_ptr(),
name.len(),
actual_type_metadata,
))
}
})
})
.collect()
} else {
vec![]
};
create_DIArray(DIB(cx), &template_params) create_DIArray(DIB(cx), &template_params)
} }
fn get_parameter_names(cx: &CodegenCx<'_, '_>, generics: &ty::Generics) -> Vec<Symbol> {
let mut names = generics.parent.map_or_else(Vec::new, |def_id| {
get_parameter_names(cx, cx.tcx.generics_of(def_id))
});
names.extend(generics.own_params.iter().map(|param| param.name));
names
}
/// Returns a scope, plus `true` if that's a type scope for "class" methods, /// Returns a scope, plus `true` if that's a type scope for "class" methods,
/// otherwise `false` for plain namespace scopes. /// otherwise `false` for plain namespace scopes.
fn get_containing_scope<'ll, 'tcx>( fn get_containing_scope<'ll, 'tcx>(