Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions compiler/rustc_borrowck/src/polonius/dump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -543,13 +543,15 @@ fn emit_loan_reachability(
// It's useful to know whether the region we're reaching is live at this point.
let node_liveness =
if liveness.is_live_at(node.region, location) { "live" } else { "not live" };
writeln!(out, "<span class='trace-suffix'>")?;
writeln!(
out,
"/ at <code>{:?}</code>: <code>'{}</code> is {}",
location,
node.region.index(),
node_liveness,
)?;
writeln!(out, "</span>")?;
writeln!(out, "</li>")?;
}
writeln!(out, "</ul>")?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
<head>
<title>Polonius MIR dump</title>
<style>
.hidden {
display: none;
pre {
margin-top: 0;
white-space: pre-wrap;
}

.section + .section {
Expand All @@ -13,8 +14,8 @@
padding-top: 10px;
}

.traces .section-header {
margin-bottom: 10px;
.section-header {
margin-bottom: 6px;
}

.trace + .trace {
Expand All @@ -25,43 +26,63 @@
margin: 5px 0px;
padding-left: 15px;
}

.trace-suffix {
opacity: 0.8;
margin-left: 10px;
}

.hidden {
display: none;
}
</style>
</head>

<body>

<!-- The NLL + Polonius MIR -->
<!-- Links to the other sections -->
<div class="section">
<div class="section-header">Quick links</div>
<a href="#mir">Polonius MIR</a>
<a href="#polonius-region-graph">Polonius constraint graph</a>
<a href="#loan-traces">Loan traces</a>
<a href="#cfg-graph">Control-flow graph</a>
<a href="#nll-region-graph">NLL region graph</a>
<a href="#nll-scc-graph">NLL SCC graph</a>
</div>

<!-- The NLL + Polonius MIR -->
<div class="section" id="mir">
<div class="section-header">Raw MIR dump</div>
<pre><code>$SECTION_MIR</code></pre>
</div>

<!-- Mermaid visualization of the polonius constraint graph -->
<div class="section">
<div class="section" id="polonius-region-graph">
<div class="section-header">Polonius constraint graph</div>
<pre class='mermaid'>$SECTION_POLONIUS_CONSTRAINTS</pre>
</div>

<!-- The reachability of loans while traversing the polonius constraint graph -->
<div class="section traces">
<div class="section traces" id="loan-traces">
<div class="section-header">Loan Traces</div>
$SECTION_POLONIUS_REACHABILITY
</div>

<!-- Mermaid visualization of the CFG -->
<div class="section">
<div class="section" id="cfg-graph">
<div class="section-header">Control-flow graph</div>
<pre class='mermaid'>$SECTION_CFG</pre>
</div>

<!-- Mermaid visualization of the NLL region graph -->
<div class="section">
<div class="section" id="nll-region-graph">
<div class="section-header">NLL regions</div>
<pre class='mermaid'>$SECTION_NLL_CONSTRAINTS</pre>
</div>

<!-- Mermaid visualization of the NLL SCC graph -->
<div class="section">
<div class="section" id="nll-scc-graph">
<div class="section-header">NLL SCCs</div>
<pre class='mermaid'>$SECTION_NLL_SCCS</pre>
</div>
Expand Down
38 changes: 20 additions & 18 deletions compiler/rustc_borrowck/src/type_check/liveness/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use rustc_infer::infer::canonical::QueryRegionConstraints;
use rustc_infer::traits::TraitErrors;
use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location};
use rustc_middle::traits::query::DropckOutlivesResult;
use rustc_middle::ty::{GenericArg, Ty, TypeVisitable, TypeVisitableExt};
use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt};
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex};
use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex};
Expand Down Expand Up @@ -553,8 +553,17 @@ impl<'tcx> LivenessContext<'_, '_, 'tcx> {
/// points `live_at`.
fn add_use_live_facts_for(&mut self, value: Ty<'tcx>, live_at: &IntervalSet<PointIndex>) {
debug!("add_use_live_facts_for(value={:?})", value);
Self::record_region_variance(self.typeck, value.into());
Self::make_all_regions_live(self.location_map, self.typeck, value.into(), live_at);
Self::make_all_regions_live(self.location_map, self.typeck, value, live_at);

// When using `-Zpolonius=next`, we also record the variance of regions in this live type.
if let Some(polonius_context) = self.typeck.polonius_context.as_mut() {
record_live_region_variance(
self.typeck.infcx.tcx,
&mut polonius_context.live_region_variances,
self.typeck.universal_regions,
value,
);
}
}

/// Some variable with type `live_ty` is "drop live" at `location`
Expand Down Expand Up @@ -595,9 +604,6 @@ impl<'tcx> LivenessContext<'_, '_, 'tcx> {
}
}

// Since the entire dropped local is live, record the variance of its regions.
Self::record_region_variance(self.typeck, dropped_ty.into());

// All things in the `outlives` array may be touched by
// the destructor and must be live at this point.
for &kind in &drop_data.dropck_result.kinds {
Expand All @@ -610,27 +616,24 @@ impl<'tcx> LivenessContext<'_, '_, 'tcx> {
self.typeck.polonius_facts,
);
}
}

/// `live_kind` is the type of a (use- or drop-) live local.
/// Record the variance of any region(s) appearing in it for Polonius. Does
/// nothing if Polonius is not active.
fn record_region_variance(typeck: &mut TypeChecker<'_, 'tcx>, live_kind: GenericArg<'tcx>) {
// When using `-Zpolonius=next`, we record the variance of each live region.
if let Some(polonius_context) = typeck.polonius_context.as_mut() {
// For polonius: since the local is drop live, record the variance of the regions in its
// type, not the ones in the type's live components seen in the dropck results above. See
// issue #160670.
if let Some(polonius_context) = self.typeck.polonius_context.as_mut() {
record_live_region_variance(
typeck.infcx.tcx,
self.typeck.infcx.tcx,
&mut polonius_context.live_region_variances,
typeck.universal_regions,
live_kind,
self.typeck.universal_regions,
dropped_ty,
);
}
}

fn make_all_regions_live(
location_map: &DenseLocationMap,
typeck: &mut TypeChecker<'_, 'tcx>,
value: GenericArg<'tcx>,
value: impl TypeVisitable<TyCtxt<'tcx>>,
live_at: &IntervalSet<PointIndex>,
) {
debug!("make_all_regions_live(value={:?})", value);
Expand All @@ -647,7 +650,6 @@ impl<'tcx> LivenessContext<'_, '_, 'tcx> {
typeck.constraints.liveness_constraints.add_points(live_region_vid, live_at);
},
});
Self::record_region_variance(typeck, value);
}
}

Expand Down
101 changes: 51 additions & 50 deletions compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::path::PathBuf;
use std::{assert_matches, iter, ptr};

use libc::{c_longlong, c_uint};
use rustc_abi::{Align, Layout, NumScalableVectors, Size};
use rustc_abi::{Align, Endian, Layout, NumScalableVectors, Size};
use rustc_codegen_ssa::debuginfo::type_names::{VTableNameKind, cpp_like_debuginfo};
use rustc_codegen_ssa::traits::*;
use rustc_hir::def::{CtorKind, DefKind};
Expand All @@ -21,7 +21,7 @@ use rustc_span::{
DUMMY_SP, FileName, RemapPathScopeComponents, SourceFile, Span, Symbol, bug, hygiene,
};
use rustc_symbol_mangling::typeid_for_trait_ref;
use rustc_target::spec::{Arch, DebuginfoKind};
use rustc_target::spec::{Arch, DebuginfoKind, HasTargetSpec};
use smallvec::smallvec;
use tracing::{debug, instrument};

Expand Down Expand Up @@ -693,66 +693,56 @@ impl MsvcBasicName for ty::UintTy {
}
}

impl MsvcBasicName for ty::FloatTy {
fn msvc_basic_name(self) -> &'static str {
// FIXME(f128): `f128` has no MSVC representation. We could improve the debuginfo.
// See: <https://github.com/rust-lang/rust/issues/121837>
match self {
ty::FloatTy::F16 => {
bug!("`f16` should have been handled in `build_basic_type_di_node`")
}
ty::FloatTy::F32 => "float",
ty::FloatTy::F64 => "double",
ty::FloatTy::F128 => "fp128",
}
}
}

fn build_cpp_f16_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> DINodeCreationResult<'ll> {
// MSVC has no native support for `f16`. Instead, emit `struct f16 { bits: u16 }` to allow the
// `f16`'s value to be displayed using a Natvis visualiser in `intrinsic.natvis`.
let float_ty = cx.tcx.types.f16;
let bits_ty = cx.tcx.types.u16;
let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
match float_ty.kind() {
ty::Adt(def, _) => Some(file_metadata_from_def_id(cx, Some(def.did()))),
_ => None,
}
/// `float_ty` must be a [`ty::Float`] and `bits_ty` must be a [`ty::Uint`].
/// `cx.size_of(bits_ty) * bits_names.len()` must equal `cx.size_of(float_ty)`.
fn build_cpp_float_struct_di_node<'ll, 'tcx>(
cx: &CodegenCx<'ll, 'tcx>,
float_ty: Ty<'tcx>,
bits_ty: Ty<'tcx>,
bits_names: &[&str],
) -> DINodeCreationResult<'ll> {
debug_assert!(matches!(bits_ty.kind(), ty::Uint(_)));
debug_assert_eq!(cx.size_of(bits_ty) * (bits_names.len() as u64), cx.size_of(float_ty));
// MSVC has no native support for `f16` or `f128`. Instead, emit a struct containing the bits as
// field(s) to allow the value to be displayed using a Natvis visualiser in `intrinsic.natvis`.
let name = if let ty::Float(f) = float_ty.kind() {
f.name_str()
} else {
None
bug!("{float_ty:?} was not a float");
};
type_map::build_type_with_children(
cx,
type_map::stub(
cx,
Stub::Struct,
UniqueTypeId::for_ty(cx.tcx, float_ty),
"f16",
def_location,
name,
None,
cx.size_and_align_of(float_ty),
NO_SCOPE_METADATA,
DIFlags::FlagZero,
),
// Fields:
|cx, float_di_node| {
let def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
match bits_ty.kind() {
ty::Adt(def, _) => Some(def.did()),
_ => None,
}
} else {
None
};
smallvec![build_field_di_node(
cx,
float_di_node,
"bits",
cx.layout_of(bits_ty),
Size::ZERO,
DIFlags::FlagZero,
type_di_node(cx, bits_ty),
def_id,
)]
let bits_layout = cx.layout_of(bits_ty);
let bits_node = type_di_node(cx, bits_ty);
bits_names
.iter()
.copied()
.enumerate()
.map(|(i, field_name)| {
build_field_di_node(
cx,
float_di_node,
field_name,
bits_layout,
bits_layout.size * (i as u64),
DIFlags::FlagZero,
bits_node,
None,
)
})
.collect()
},
NO_GENERICS,
)
Expand Down Expand Up @@ -784,9 +774,20 @@ fn build_basic_type_di_node<'ll, 'tcx>(
ty::Int(int_ty) if cpp_like_debuginfo => (int_ty.msvc_basic_name(), DW_ATE_signed),
ty::Uint(uint_ty) if cpp_like_debuginfo => (uint_ty.msvc_basic_name(), DW_ATE_unsigned),
ty::Float(ty::FloatTy::F16) if cpp_like_debuginfo => {
return build_cpp_f16_di_node(cx);
return build_cpp_float_struct_di_node(cx, t, cx.tcx.types.u16, &["bits"]);
}
ty::Float(ty::FloatTy::F128) if cpp_like_debuginfo => {
// All MSVC architectures are little endian.
assert_eq!(cx.target_spec().endian, Endian::Little);
return build_cpp_float_struct_di_node(
cx,
t,
cx.tcx.types.u64,
&["low_bits", "high_bits"],
);
}
ty::Float(float_ty) if cpp_like_debuginfo => (float_ty.msvc_basic_name(), DW_ATE_float),
ty::Float(ty::FloatTy::F32) if cpp_like_debuginfo => ("float", DW_ATE_float),
ty::Float(ty::FloatTy::F64) if cpp_like_debuginfo => ("double", DW_ATE_float),
ty::Int(int_ty) => (int_ty.name_str(), DW_ATE_signed),
ty::Uint(uint_ty) => (uint_ty.name_str(), DW_ATE_unsigned),
ty::Float(float_ty) => (float_ty.name_str(), DW_ATE_float),
Expand Down
21 changes: 14 additions & 7 deletions library/core/src/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::ffi::c_char;
use crate::intrinsics::const_eval_select;
use crate::iter::FusedIterator;
use crate::marker::PhantomData;
use crate::num::niche_types::UsizeNoHighBitMinusOne;
use crate::ptr::NonNull;
use crate::slice::memchr;
use crate::{fmt, ops, range, slice, str};
Expand Down Expand Up @@ -262,7 +263,12 @@ impl CStr {
// means the call to `from_bytes_with_nul_unchecked` is correct.
//
// The cast from c_char to u8 is ok because a c_char is always one byte.
unsafe { Self::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr.cast(), len + 1)) }
unsafe {
Self::from_bytes_with_nul_unchecked(slice::from_raw_parts(
ptr.cast(),
len.as_inner() + 1,
))
}
}

/// Creates a C string wrapper from a byte slice with any number of nuls.
Expand Down Expand Up @@ -750,9 +756,9 @@ const impl AsRef<CStr> for CStr {
#[inline]
#[unstable(feature = "cstr_internals", issue = "none")]
#[rustc_allow_const_fn_unstable(const_eval_select)]
const unsafe fn strlen(ptr: *const c_char) -> usize {
const unsafe fn strlen(ptr: *const c_char) -> UsizeNoHighBitMinusOne {
const_eval_select!(
@capture { s: *const c_char = ptr } -> usize:
@capture { s: *const c_char = ptr } -> UsizeNoHighBitMinusOne:
if const {
let mut len = 0;

Expand All @@ -761,15 +767,16 @@ const unsafe fn strlen(ptr: *const c_char) -> usize {
len += 1;
}

len
UsizeNoHighBitMinusOne::new(len).unwrap()
} else {
unsafe extern "C" {
/// Provided by libc or compiler_builtins.
fn strlen(s: *const c_char) -> usize;
}

// SAFETY: Outer caller has provided a pointer to a valid C string.
unsafe { strlen(s) }
// SAFETY: Outer caller has provided a pointer to a valid C string,
// and its length is within bounds.
unsafe { UsizeNoHighBitMinusOne::new_unchecked(strlen(s)) }
}
)
}
Expand Down Expand Up @@ -841,7 +848,7 @@ impl Iterator for Bytes<'_> {
#[inline]
fn count(self) -> usize {
// SAFETY: We always hold a valid pointer to a C string
unsafe { strlen(self.ptr.as_ptr().cast()) }
unsafe { strlen(self.ptr.as_ptr().cast()) }.as_inner()
}
}

Expand Down
Loading
Loading