Auto merge of #135140 - jhpratt:rollup-pn2gi84, r=jhpratt
Rollup of 3 pull requests Successful merges: - #135115 (cg_llvm: Use constants for DWARF opcodes, instead of FFI calls) - #135118 (Clarified the documentation on `core::iter::from_fn` and `core::iter::successors`) - #135121 (Mark `slice::reverse` unstably const) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
56f9e6f935
11 changed files with 72 additions and 51 deletions
|
@ -3499,6 +3499,7 @@ name = "rustc_codegen_llvm"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
|
"gimli 0.30.0",
|
||||||
"itertools",
|
"itertools",
|
||||||
"libc",
|
"libc",
|
||||||
"measureme",
|
"measureme",
|
||||||
|
|
|
@ -9,6 +9,7 @@ test = false
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# tidy-alphabetical-start
|
# tidy-alphabetical-start
|
||||||
bitflags = "2.4.1"
|
bitflags = "2.4.1"
|
||||||
|
gimli = "0.30"
|
||||||
itertools = "0.12"
|
itertools = "0.12"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
measureme = "11"
|
measureme = "11"
|
||||||
|
|
37
compiler/rustc_codegen_llvm/src/debuginfo/dwarf_const.rs
Normal file
37
compiler/rustc_codegen_llvm/src/debuginfo/dwarf_const.rs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
//! Definitions of various DWARF-related constants.
|
||||||
|
|
||||||
|
use libc::c_uint;
|
||||||
|
|
||||||
|
/// Helper macro to let us redeclare gimli's constants as our own constants
|
||||||
|
/// with a different type, with less risk of copy-paste errors.
|
||||||
|
macro_rules! declare_constant {
|
||||||
|
(
|
||||||
|
$name:ident : $type:ty
|
||||||
|
) => {
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
pub(crate) const $name: $type = ::gimli::constants::$name.0 as $type;
|
||||||
|
|
||||||
|
// Assert that as-cast probably hasn't changed the value.
|
||||||
|
const _: () = assert!($name as i128 == ::gimli::constants::$name.0 as i128);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
declare_constant!(DW_TAG_const_type: c_uint);
|
||||||
|
|
||||||
|
// DWARF languages.
|
||||||
|
declare_constant!(DW_LANG_Rust: c_uint);
|
||||||
|
|
||||||
|
// DWARF attribute type encodings.
|
||||||
|
declare_constant!(DW_ATE_boolean: c_uint);
|
||||||
|
declare_constant!(DW_ATE_float: c_uint);
|
||||||
|
declare_constant!(DW_ATE_signed: c_uint);
|
||||||
|
declare_constant!(DW_ATE_unsigned: c_uint);
|
||||||
|
declare_constant!(DW_ATE_UTF: c_uint);
|
||||||
|
|
||||||
|
// DWARF expression operators.
|
||||||
|
declare_constant!(DW_OP_deref: u64);
|
||||||
|
declare_constant!(DW_OP_plus_uconst: u64);
|
||||||
|
/// Defined by LLVM in `llvm/include/llvm/BinaryFormat/Dwarf.h`.
|
||||||
|
/// Double-checked by a static assertion in `RustWrapper.cpp`.
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
pub(crate) const DW_OP_LLVM_fragment: u64 = 0x1000;
|
|
@ -22,6 +22,7 @@ use rustc_target::spec::DebuginfoKind;
|
||||||
use smallvec::smallvec;
|
use smallvec::smallvec;
|
||||||
use tracing::{debug, instrument};
|
use tracing::{debug, instrument};
|
||||||
|
|
||||||
|
pub(crate) use self::type_map::TypeMap;
|
||||||
use self::type_map::{DINodeCreationResult, Stub, UniqueTypeId};
|
use self::type_map::{DINodeCreationResult, Stub, UniqueTypeId};
|
||||||
use super::CodegenUnitDebugContext;
|
use super::CodegenUnitDebugContext;
|
||||||
use super::namespace::mangled_name_of_instance;
|
use super::namespace::mangled_name_of_instance;
|
||||||
|
@ -30,6 +31,7 @@ use super::utils::{
|
||||||
DIB, create_DIArray, debug_context, get_namespace_for_item, is_node_local_to_unit,
|
DIB, create_DIArray, debug_context, get_namespace_for_item, is_node_local_to_unit,
|
||||||
};
|
};
|
||||||
use crate::common::{AsCCharPtr, CodegenCx};
|
use crate::common::{AsCCharPtr, CodegenCx};
|
||||||
|
use crate::debuginfo::dwarf_const;
|
||||||
use crate::debuginfo::metadata::type_map::build_type_with_children;
|
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::debuginfo::{
|
use crate::llvm::debuginfo::{
|
||||||
|
@ -59,23 +61,6 @@ impl fmt::Debug for llvm::Metadata {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// From DWARF 5.
|
|
||||||
// See http://www.dwarfstd.org/ShowIssue.php?issue=140129.1.
|
|
||||||
const DW_LANG_RUST: c_uint = 0x1c;
|
|
||||||
#[allow(non_upper_case_globals)]
|
|
||||||
const DW_ATE_boolean: c_uint = 0x02;
|
|
||||||
#[allow(non_upper_case_globals)]
|
|
||||||
const DW_ATE_float: c_uint = 0x04;
|
|
||||||
#[allow(non_upper_case_globals)]
|
|
||||||
const DW_ATE_signed: c_uint = 0x05;
|
|
||||||
#[allow(non_upper_case_globals)]
|
|
||||||
const DW_ATE_unsigned: c_uint = 0x07;
|
|
||||||
#[allow(non_upper_case_globals)]
|
|
||||||
const DW_ATE_UTF: c_uint = 0x10;
|
|
||||||
|
|
||||||
#[allow(non_upper_case_globals)]
|
|
||||||
const DW_TAG_const_type: c_uint = 0x26;
|
|
||||||
|
|
||||||
pub(super) const UNKNOWN_LINE_NUMBER: c_uint = 0;
|
pub(super) const UNKNOWN_LINE_NUMBER: c_uint = 0;
|
||||||
pub(super) const UNKNOWN_COLUMN_NUMBER: c_uint = 0;
|
pub(super) const UNKNOWN_COLUMN_NUMBER: c_uint = 0;
|
||||||
|
|
||||||
|
@ -90,8 +75,6 @@ type SmallVec<T> = smallvec::SmallVec<[T; 16]>;
|
||||||
mod enums;
|
mod enums;
|
||||||
mod type_map;
|
mod type_map;
|
||||||
|
|
||||||
pub(crate) use type_map::TypeMap;
|
|
||||||
|
|
||||||
/// Returns from the enclosing function if the type debuginfo node with the given
|
/// Returns from the enclosing function if the type debuginfo node with the given
|
||||||
/// unique ID can be found in the type map.
|
/// unique ID can be found in the type map.
|
||||||
macro_rules! return_if_di_node_created_in_meantime {
|
macro_rules! return_if_di_node_created_in_meantime {
|
||||||
|
@ -522,7 +505,7 @@ fn recursion_marker_type_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> &'ll D
|
||||||
name.as_c_char_ptr(),
|
name.as_c_char_ptr(),
|
||||||
name.len(),
|
name.len(),
|
||||||
cx.tcx.data_layout.pointer_size.bits(),
|
cx.tcx.data_layout.pointer_size.bits(),
|
||||||
DW_ATE_unsigned,
|
dwarf_const::DW_ATE_unsigned,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -781,6 +764,8 @@ fn build_basic_type_di_node<'ll, 'tcx>(
|
||||||
// .natvis visualizers (and perhaps other existing native debuggers?)
|
// .natvis visualizers (and perhaps other existing native debuggers?)
|
||||||
let cpp_like_debuginfo = cpp_like_debuginfo(cx.tcx);
|
let cpp_like_debuginfo = cpp_like_debuginfo(cx.tcx);
|
||||||
|
|
||||||
|
use dwarf_const::{DW_ATE_UTF, DW_ATE_boolean, DW_ATE_float, DW_ATE_signed, DW_ATE_unsigned};
|
||||||
|
|
||||||
let (name, encoding) = match t.kind() {
|
let (name, encoding) = match t.kind() {
|
||||||
ty::Never => ("!", DW_ATE_unsigned),
|
ty::Never => ("!", DW_ATE_unsigned),
|
||||||
ty::Tuple(elements) if elements.is_empty() => {
|
ty::Tuple(elements) if elements.is_empty() => {
|
||||||
|
@ -961,7 +946,7 @@ pub(crate) fn build_compile_unit_di_node<'ll, 'tcx>(
|
||||||
|
|
||||||
let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit(
|
let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit(
|
||||||
debug_context.builder,
|
debug_context.builder,
|
||||||
DW_LANG_RUST,
|
dwarf_const::DW_LANG_Rust,
|
||||||
compile_unit_file,
|
compile_unit_file,
|
||||||
producer.as_c_char_ptr(),
|
producer.as_c_char_ptr(),
|
||||||
producer.len(),
|
producer.len(),
|
||||||
|
|
|
@ -12,12 +12,13 @@ use rustc_middle::ty::{self, AdtDef, CoroutineArgs, CoroutineArgsExt, Ty};
|
||||||
use smallvec::smallvec;
|
use smallvec::smallvec;
|
||||||
|
|
||||||
use crate::common::{AsCCharPtr, CodegenCx};
|
use crate::common::{AsCCharPtr, CodegenCx};
|
||||||
|
use crate::debuginfo::dwarf_const::DW_TAG_const_type;
|
||||||
use crate::debuginfo::metadata::enums::DiscrResult;
|
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, DW_TAG_const_type, NO_GENERICS, NO_SCOPE_METADATA, SmallVec,
|
DINodeCreationResult, NO_GENERICS, NO_SCOPE_METADATA, SmallVec, UNKNOWN_LINE_NUMBER,
|
||||||
UNKNOWN_LINE_NUMBER, build_field_di_node, file_metadata, file_metadata_from_def_id,
|
build_field_di_node, file_metadata, file_metadata_from_def_id, size_and_align_of, type_di_node,
|
||||||
size_and_align_of, type_di_node, unknown_file_metadata, visibility_di_flags,
|
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};
|
||||||
|
|
|
@ -39,6 +39,7 @@ use crate::llvm::debuginfo::{
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
|
|
||||||
mod create_scope_map;
|
mod create_scope_map;
|
||||||
|
mod dwarf_const;
|
||||||
mod gdb;
|
mod gdb;
|
||||||
pub(crate) mod metadata;
|
pub(crate) mod metadata;
|
||||||
mod namespace;
|
mod namespace;
|
||||||
|
@ -47,6 +48,10 @@ mod utils;
|
||||||
use self::create_scope_map::compute_mir_scopes;
|
use self::create_scope_map::compute_mir_scopes;
|
||||||
pub(crate) use self::metadata::build_global_var_di_node;
|
pub(crate) use self::metadata::build_global_var_di_node;
|
||||||
|
|
||||||
|
// FIXME(Zalathar): These `DW_TAG_*` constants are fake values that were
|
||||||
|
// removed from LLVM in 2015, and are only used by our own `RustWrapper.cpp`
|
||||||
|
// to decide which C++ API to call. Instead, we should just have two separate
|
||||||
|
// FFI functions and choose the correct one on the Rust side.
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
const DW_TAG_auto_variable: c_uint = 0x100;
|
const DW_TAG_auto_variable: c_uint = 0x100;
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
|
@ -152,29 +157,26 @@ impl<'ll> DebugInfoBuilderMethods for Builder<'_, 'll, '_> {
|
||||||
indirect_offsets: &[Size],
|
indirect_offsets: &[Size],
|
||||||
fragment: Option<Range<Size>>,
|
fragment: Option<Range<Size>>,
|
||||||
) {
|
) {
|
||||||
|
use dwarf_const::{DW_OP_LLVM_fragment, DW_OP_deref, DW_OP_plus_uconst};
|
||||||
|
|
||||||
// Convert the direct and indirect offsets and fragment byte range to address ops.
|
// Convert the direct and indirect offsets and fragment byte range to address ops.
|
||||||
// FIXME(eddyb) use `const`s instead of getting the values via FFI,
|
|
||||||
// the values should match the ones in the DWARF standard anyway.
|
|
||||||
let op_deref = || unsafe { llvm::LLVMRustDIBuilderCreateOpDeref() };
|
|
||||||
let op_plus_uconst = || unsafe { llvm::LLVMRustDIBuilderCreateOpPlusUconst() };
|
|
||||||
let op_llvm_fragment = || unsafe { llvm::LLVMRustDIBuilderCreateOpLLVMFragment() };
|
|
||||||
let mut addr_ops = SmallVec::<[u64; 8]>::new();
|
let mut addr_ops = SmallVec::<[u64; 8]>::new();
|
||||||
|
|
||||||
if direct_offset.bytes() > 0 {
|
if direct_offset.bytes() > 0 {
|
||||||
addr_ops.push(op_plus_uconst());
|
addr_ops.push(DW_OP_plus_uconst);
|
||||||
addr_ops.push(direct_offset.bytes() as u64);
|
addr_ops.push(direct_offset.bytes() as u64);
|
||||||
}
|
}
|
||||||
for &offset in indirect_offsets {
|
for &offset in indirect_offsets {
|
||||||
addr_ops.push(op_deref());
|
addr_ops.push(DW_OP_deref);
|
||||||
if offset.bytes() > 0 {
|
if offset.bytes() > 0 {
|
||||||
addr_ops.push(op_plus_uconst());
|
addr_ops.push(DW_OP_plus_uconst);
|
||||||
addr_ops.push(offset.bytes() as u64);
|
addr_ops.push(offset.bytes() as u64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(fragment) = fragment {
|
if let Some(fragment) = fragment {
|
||||||
// `DW_OP_LLVM_fragment` takes as arguments the fragment's
|
// `DW_OP_LLVM_fragment` takes as arguments the fragment's
|
||||||
// offset and size, both of them in bits.
|
// offset and size, both of them in bits.
|
||||||
addr_ops.push(op_llvm_fragment());
|
addr_ops.push(DW_OP_LLVM_fragment);
|
||||||
addr_ops.push(fragment.start.bits() as u64);
|
addr_ops.push(fragment.start.bits() as u64);
|
||||||
addr_ops.push((fragment.end - fragment.start).bits() as u64);
|
addr_ops.push((fragment.end - fragment.start).bits() as u64);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2177,9 +2177,6 @@ unsafe extern "C" {
|
||||||
Location: &'a DILocation,
|
Location: &'a DILocation,
|
||||||
BD: c_uint,
|
BD: c_uint,
|
||||||
) -> Option<&'a DILocation>;
|
) -> Option<&'a DILocation>;
|
||||||
pub fn LLVMRustDIBuilderCreateOpDeref() -> u64;
|
|
||||||
pub fn LLVMRustDIBuilderCreateOpPlusUconst() -> u64;
|
|
||||||
pub fn LLVMRustDIBuilderCreateOpLLVMFragment() -> u64;
|
|
||||||
|
|
||||||
pub fn LLVMRustWriteTypeToString(Type: &Type, s: &RustString);
|
pub fn LLVMRustWriteTypeToString(Type: &Type, s: &RustString);
|
||||||
pub fn LLVMRustWriteValueToString(value_ref: &Value, s: &RustString);
|
pub fn LLVMRustWriteValueToString(value_ref: &Value, s: &RustString);
|
||||||
|
|
|
@ -54,6 +54,10 @@ using namespace llvm;
|
||||||
using namespace llvm::sys;
|
using namespace llvm::sys;
|
||||||
using namespace llvm::object;
|
using namespace llvm::object;
|
||||||
|
|
||||||
|
// This opcode is an LLVM detail that could hypothetically change (?), so
|
||||||
|
// verify that the hard-coded value in `dwarf_const.rs` still agrees with LLVM.
|
||||||
|
static_assert(dwarf::DW_OP_LLVM_fragment == 0x1000);
|
||||||
|
|
||||||
// LLVMAtomicOrdering is already an enum - don't create another
|
// LLVMAtomicOrdering is already an enum - don't create another
|
||||||
// one.
|
// one.
|
||||||
static AtomicOrdering fromRust(LLVMAtomicOrdering Ordering) {
|
static AtomicOrdering fromRust(LLVMAtomicOrdering Ordering) {
|
||||||
|
@ -1397,18 +1401,6 @@ LLVMRustDILocationCloneWithBaseDiscriminator(LLVMMetadataRef Location,
|
||||||
return wrap(NewLoc.has_value() ? NewLoc.value() : nullptr);
|
return wrap(NewLoc.has_value() ? NewLoc.value() : nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" uint64_t LLVMRustDIBuilderCreateOpDeref() {
|
|
||||||
return dwarf::DW_OP_deref;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" uint64_t LLVMRustDIBuilderCreateOpPlusUconst() {
|
|
||||||
return dwarf::DW_OP_plus_uconst;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" uint64_t LLVMRustDIBuilderCreateOpLLVMFragment() {
|
|
||||||
return dwarf::DW_OP_LLVM_fragment;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
|
extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
|
||||||
auto OS = RawRustStringOstream(Str);
|
auto OS = RawRustStringOstream(Str);
|
||||||
unwrap<llvm::Type>(Ty)->print(OS);
|
unwrap<llvm::Type>(Ty)->print(OS);
|
||||||
|
|
|
@ -3,6 +3,8 @@ use crate::fmt;
|
||||||
/// Creates a new iterator where each iteration calls the provided closure
|
/// Creates a new iterator where each iteration calls the provided closure
|
||||||
/// `F: FnMut() -> Option<T>`.
|
/// `F: FnMut() -> Option<T>`.
|
||||||
///
|
///
|
||||||
|
/// The iterator will yield the `T`s returned from the closure.
|
||||||
|
///
|
||||||
/// This allows creating a custom iterator with any behavior
|
/// This allows creating a custom iterator with any behavior
|
||||||
/// without using the more verbose syntax of creating a dedicated type
|
/// without using the more verbose syntax of creating a dedicated type
|
||||||
/// and implementing the [`Iterator`] trait for it.
|
/// and implementing the [`Iterator`] trait for it.
|
||||||
|
|
|
@ -5,6 +5,7 @@ use crate::iter::FusedIterator;
|
||||||
///
|
///
|
||||||
/// The iterator starts with the given first item (if any)
|
/// The iterator starts with the given first item (if any)
|
||||||
/// and calls the given `FnMut(&T) -> Option<T>` closure to compute each item’s successor.
|
/// and calls the given `FnMut(&T) -> Option<T>` closure to compute each item’s successor.
|
||||||
|
/// The iterator will yield the `T`s returned from the closure.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::iter::successors;
|
/// use std::iter::successors;
|
||||||
|
|
|
@ -987,8 +987,9 @@ impl<T> [T] {
|
||||||
/// assert!(v == [3, 2, 1]);
|
/// assert!(v == [3, 2, 1]);
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[rustc_const_unstable(feature = "const_slice_reverse", issue = "135120")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn reverse(&mut self) {
|
pub const fn reverse(&mut self) {
|
||||||
let half_len = self.len() / 2;
|
let half_len = self.len() / 2;
|
||||||
let Range { start, end } = self.as_mut_ptr_range();
|
let Range { start, end } = self.as_mut_ptr_range();
|
||||||
|
|
||||||
|
@ -1011,7 +1012,7 @@ impl<T> [T] {
|
||||||
revswap(front_half, back_half, half_len);
|
revswap(front_half, back_half, half_len);
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn revswap<T>(a: &mut [T], b: &mut [T], n: usize) {
|
const fn revswap<T>(a: &mut [T], b: &mut [T], n: usize) {
|
||||||
debug_assert!(a.len() == n);
|
debug_assert!(a.len() == n);
|
||||||
debug_assert!(b.len() == n);
|
debug_assert!(b.len() == n);
|
||||||
|
|
||||||
|
@ -1019,7 +1020,8 @@ impl<T> [T] {
|
||||||
// this check tells LLVM that the indexing below is
|
// this check tells LLVM that the indexing below is
|
||||||
// in-bounds. Then after inlining -- once the actual
|
// in-bounds. Then after inlining -- once the actual
|
||||||
// lengths of the slices are known -- it's removed.
|
// lengths of the slices are known -- it's removed.
|
||||||
let (a, b) = (&mut a[..n], &mut b[..n]);
|
let (a, _) = a.split_at_mut(n);
|
||||||
|
let (b, _) = b.split_at_mut(n);
|
||||||
|
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < n {
|
while i < n {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue