Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 8 pull requests #131665

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
1f718f9
uefi: Implement getcwd and chdir
Ayush1325 Aug 30, 2024
82b4d0d
std::fs::get_path freebsd update.
devnexen Aug 11, 2024
65532e7
update libc version
devnexen Oct 3, 2024
0b00a54
library: Stabilize const `MaybeUninit::assume_init_mut`
workingjubilee Oct 5, 2024
2c38ecf
emscripten: Use the latest emsdk 3.1.68
workingjubilee Oct 11, 2024
559de74
compiler: Move impl of ToJson for abi::Endian
workingjubilee Oct 9, 2024
255bdd2
compiler: Empty out rustc_target::abi
workingjubilee Oct 9, 2024
1072190
compiler: Wire `{TyAnd,}Layout` into `rustc_abi`
workingjubilee Oct 9, 2024
bc4366b
miri: avoid cloning AllocExtra
RalfJung Oct 12, 2024
1ebfd97
merge const_ipv4 / const_ipv6 feature gate into 'ip' feature gate
RalfJung Oct 12, 2024
725d1f7
core/net: add Ipv[46]Addr::from_octets, Ipv6Addr::from_segments
Dirbaio Oct 7, 2024
0b7e399
core/net: use hex for ipv6 doctests for consistency.
Dirbaio Oct 13, 2024
665e9c6
Rollup merge of #128967 - devnexen:get_path_fbsd_upd, r=joboet
matthiaskrgr Oct 13, 2024
c3c3000
Rollup merge of #129794 - Ayush1325:uefi-os-expand, r=joboet
matthiaskrgr Oct 13, 2024
c0b6c59
Rollup merge of #130629 - Dirbaio:net-from-octets, r=tgross35
matthiaskrgr Oct 13, 2024
75e3ba4
Rollup merge of #131274 - workingjubilee:stabilize-the-one-that-got-a…
matthiaskrgr Oct 13, 2024
6eef63c
Rollup merge of #131473 - workingjubilee:move-that-abi-up, r=saethlin
matthiaskrgr Oct 13, 2024
42f6103
Rollup merge of #131533 - workingjubilee:update-emscripten-version, r…
matthiaskrgr Oct 13, 2024
03a5943
Rollup merge of #131593 - RalfJung:alloc-no-clone, r=saethlin
matthiaskrgr Oct 13, 2024
06462e1
Rollup merge of #131616 - RalfJung:const_ip, r=tgross35
matthiaskrgr Oct 13, 2024
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
254 changes: 254 additions & 0 deletions compiler/rustc_abi/src/callconv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
mod abi {
pub(crate) use crate::Primitive::*;
pub(crate) use crate::Variants;
}

use rustc_macros::HashStable_Generic;

use crate::{Abi, Align, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout};

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
pub enum RegKind {
Integer,
Float,
Vector,
}

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
pub struct Reg {
pub kind: RegKind,
pub size: Size,
}

macro_rules! reg_ctor {
($name:ident, $kind:ident, $bits:expr) => {
pub fn $name() -> Reg {
Reg { kind: RegKind::$kind, size: Size::from_bits($bits) }
}
};
}

impl Reg {
reg_ctor!(i8, Integer, 8);
reg_ctor!(i16, Integer, 16);
reg_ctor!(i32, Integer, 32);
reg_ctor!(i64, Integer, 64);
reg_ctor!(i128, Integer, 128);

reg_ctor!(f32, Float, 32);
reg_ctor!(f64, Float, 64);
}

impl Reg {
pub fn align<C: HasDataLayout>(&self, cx: &C) -> Align {
let dl = cx.data_layout();
match self.kind {
RegKind::Integer => match self.size.bits() {
1 => dl.i1_align.abi,
2..=8 => dl.i8_align.abi,
9..=16 => dl.i16_align.abi,
17..=32 => dl.i32_align.abi,
33..=64 => dl.i64_align.abi,
65..=128 => dl.i128_align.abi,
_ => panic!("unsupported integer: {self:?}"),
},
RegKind::Float => match self.size.bits() {
16 => dl.f16_align.abi,
32 => dl.f32_align.abi,
64 => dl.f64_align.abi,
128 => dl.f128_align.abi,
_ => panic!("unsupported float: {self:?}"),
},
RegKind::Vector => dl.vector_align(self.size).abi,
}
}
}

/// Return value from the `homogeneous_aggregate` test function.
#[derive(Copy, Clone, Debug)]
pub enum HomogeneousAggregate {
/// Yes, all the "leaf fields" of this struct are passed in the
/// same way (specified in the `Reg` value).
Homogeneous(Reg),

/// There are no leaf fields at all.
NoData,
}

/// Error from the `homogeneous_aggregate` test function, indicating
/// there are distinct leaf fields passed in different ways,
/// or this is uninhabited.
#[derive(Copy, Clone, Debug)]
pub struct Heterogeneous;

impl HomogeneousAggregate {
/// If this is a homogeneous aggregate, returns the homogeneous
/// unit, else `None`.
pub fn unit(self) -> Option<Reg> {
match self {
HomogeneousAggregate::Homogeneous(reg) => Some(reg),
HomogeneousAggregate::NoData => None,
}
}

/// Try to combine two `HomogeneousAggregate`s, e.g. from two fields in
/// the same `struct`. Only succeeds if only one of them has any data,
/// or both units are identical.
fn merge(self, other: HomogeneousAggregate) -> Result<HomogeneousAggregate, Heterogeneous> {
match (self, other) {
(x, HomogeneousAggregate::NoData) | (HomogeneousAggregate::NoData, x) => Ok(x),

(HomogeneousAggregate::Homogeneous(a), HomogeneousAggregate::Homogeneous(b)) => {
if a != b {
return Err(Heterogeneous);
}
Ok(self)
}
}
}
}

impl<'a, Ty> TyAndLayout<'a, Ty> {
/// Returns `true` if this is an aggregate type (including a ScalarPair!)
pub fn is_aggregate(&self) -> bool {
match self.abi {
Abi::Uninhabited | Abi::Scalar(_) | Abi::Vector { .. } => false,
Abi::ScalarPair(..) | Abi::Aggregate { .. } => true,
}
}

/// Returns `Homogeneous` if this layout is an aggregate containing fields of
/// only a single type (e.g., `(u32, u32)`). Such aggregates are often
/// special-cased in ABIs.
///
/// Note: We generally ignore 1-ZST fields when computing this value (see #56877).
///
/// This is public so that it can be used in unit tests, but
/// should generally only be relevant to the ABI details of
/// specific targets.
pub fn homogeneous_aggregate<C>(&self, cx: &C) -> Result<HomogeneousAggregate, Heterogeneous>
where
Ty: TyAbiInterface<'a, C> + Copy,
{
match self.abi {
Abi::Uninhabited => Err(Heterogeneous),

// The primitive for this algorithm.
Abi::Scalar(scalar) => {
let kind = match scalar.primitive() {
abi::Int(..) | abi::Pointer(_) => RegKind::Integer,
abi::Float(_) => RegKind::Float,
};
Ok(HomogeneousAggregate::Homogeneous(Reg { kind, size: self.size }))
}

Abi::Vector { .. } => {
assert!(!self.is_zst());
Ok(HomogeneousAggregate::Homogeneous(Reg {
kind: RegKind::Vector,
size: self.size,
}))
}

Abi::ScalarPair(..) | Abi::Aggregate { sized: true } => {
// Helper for computing `homogeneous_aggregate`, allowing a custom
// starting offset (used below for handling variants).
let from_fields_at =
|layout: Self,
start: Size|
-> Result<(HomogeneousAggregate, Size), Heterogeneous> {
let is_union = match layout.fields {
FieldsShape::Primitive => {
unreachable!("aggregates can't have `FieldsShape::Primitive`")
}
FieldsShape::Array { count, .. } => {
assert_eq!(start, Size::ZERO);

let result = if count > 0 {
layout.field(cx, 0).homogeneous_aggregate(cx)?
} else {
HomogeneousAggregate::NoData
};
return Ok((result, layout.size));
}
FieldsShape::Union(_) => true,
FieldsShape::Arbitrary { .. } => false,
};

let mut result = HomogeneousAggregate::NoData;
let mut total = start;

for i in 0..layout.fields.count() {
let field = layout.field(cx, i);
if field.is_1zst() {
// No data here and no impact on layout, can be ignored.
// (We might be able to also ignore all aligned ZST but that's less clear.)
continue;
}

if !is_union && total != layout.fields.offset(i) {
// This field isn't just after the previous one we considered, abort.
return Err(Heterogeneous);
}

result = result.merge(field.homogeneous_aggregate(cx)?)?;

// Keep track of the offset (without padding).
let size = field.size;
if is_union {
total = total.max(size);
} else {
total += size;
}
}

Ok((result, total))
};

let (mut result, mut total) = from_fields_at(*self, Size::ZERO)?;

match &self.variants {
abi::Variants::Single { .. } => {}
abi::Variants::Multiple { variants, .. } => {
// Treat enum variants like union members.
// HACK(eddyb) pretend the `enum` field (discriminant)
// is at the start of every variant (otherwise the gap
// at the start of all variants would disqualify them).
//
// NB: for all tagged `enum`s (which include all non-C-like
// `enum`s with defined FFI representation), this will
// match the homogeneous computation on the equivalent
// `struct { tag; union { variant1; ... } }` and/or
// `union { struct { tag; variant1; } ... }`
// (the offsets of variant fields should be identical
// between the two for either to be a homogeneous aggregate).
let variant_start = total;
for variant_idx in variants.indices() {
let (variant_result, variant_total) =
from_fields_at(self.for_variant(cx, variant_idx), variant_start)?;

result = result.merge(variant_result)?;
total = total.max(variant_total);
}
}
}

// There needs to be no padding.
if total != self.size {
Err(Heterogeneous)
} else {
match result {
HomogeneousAggregate::Homogeneous(_) => {
assert_ne!(total, Size::ZERO);
}
HomogeneousAggregate::NoData => {
assert_eq!(total, Size::ZERO);
}
}
Ok(result)
}
}
Abi::Aggregate { sized: false } => Err(Heterogeneous),
}
}
}
4 changes: 4 additions & 0 deletions compiler/rustc_abi/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ use crate::{
Variants, WrappingRange,
};

mod ty;

pub use ty::{FIRST_VARIANT, FieldIdx, Layout, TyAbiInterface, TyAndLayout, VariantIdx};

// A variant is absent if it's uninhabited and only has ZST fields.
// Present uninhabited variants only require space for their fields,
// but *not* an encoding of the discriminant (e.g., a tag value).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,8 @@ use Primitive::*;
use rustc_data_structures::intern::Interned;
use rustc_macros::HashStable_Generic;

use crate::json::{Json, ToJson};

pub mod call;

// Explicitly import `Float` to avoid ambiguity with `Primitive::Float`.
pub use rustc_abi::{Float, *};

impl ToJson for Endian {
fn to_json(&self) -> Json {
self.as_str().to_json()
}
}
use crate::{Float, *};

rustc_index::newtype_index! {
/// The *source-order* index of a field in a variant.
Expand Down
8 changes: 7 additions & 1 deletion compiler/rustc_abi/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// tidy-alphabetical-start
#![cfg_attr(feature = "nightly", allow(internal_features))]
#![cfg_attr(feature = "nightly", doc(rust_logo))]
#![cfg_attr(feature = "nightly", feature(rustc_attrs))]
#![cfg_attr(feature = "nightly", feature(rustdoc_internals))]
#![cfg_attr(feature = "nightly", feature(step_trait))]
#![warn(unreachable_pub)]
Expand All @@ -22,11 +23,16 @@ use rustc_macros::HashStable_Generic;
#[cfg(feature = "nightly")]
use rustc_macros::{Decodable_Generic, Encodable_Generic};

mod callconv;
mod layout;
#[cfg(test)]
mod tests;

pub use layout::{LayoutCalculator, LayoutCalculatorError};
pub use callconv::{Heterogeneous, HomogeneousAggregate, Reg, RegKind};
pub use layout::{
FIRST_VARIANT, FieldIdx, Layout, LayoutCalculator, LayoutCalculatorError, TyAbiInterface,
TyAndLayout, VariantIdx,
};

/// Requirements for a `StableHashingContext` to be used in this crate.
/// This is a hack to allow using the `HashStable_Generic` derive macro
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/const_eval/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxIndexMap<K, V> {

#[inline(always)]
fn filter_map_collect<T>(&self, mut f: impl FnMut(&K, &V) -> Option<T>) -> Vec<T> {
self.iter().filter_map(move |(k, v)| f(k, &*v)).collect()
self.iter().filter_map(move |(k, v)| f(k, v)).collect()
}

#[inline(always)]
Expand Down
31 changes: 18 additions & 13 deletions compiler/rustc_const_eval/src/interpret/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -993,11 +993,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
bytes
}

/// Find leaked allocations. Allocations reachable from `static_roots` or a `Global` allocation
/// are not considered leaked, as well as leaks whose kind's `may_leak()` returns true.
pub fn find_leaked_allocations(
&self,
static_roots: &[AllocId],
/// Find leaked allocations, remove them from memory and return them. Allocations reachable from
/// `static_roots` or a `Global` allocation are not considered leaked, as well as leaks whose
/// kind's `may_leak()` returns true.
///
/// This is highly destructive, no more execution can happen after this!
pub fn take_leaked_allocations(
&mut self,
static_roots: impl FnOnce(&Self) -> &[AllocId],
) -> Vec<(AllocId, MemoryKind<M::MemoryKind>, Allocation<M::Provenance, M::AllocExtra, M::Bytes>)>
{
// Collect the set of allocations that are *reachable* from `Global` allocations.
Expand All @@ -1008,7 +1011,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
self.memory.alloc_map.filter_map_collect(move |&id, &(kind, _)| {
if Some(kind) == global_kind { Some(id) } else { None }
});
todo.extend(static_roots);
todo.extend(static_roots(self));
while let Some(id) = todo.pop() {
if reachable.insert(id) {
// This is a new allocation, add the allocation it points to `todo`.
Expand All @@ -1023,13 +1026,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
};

// All allocations that are *not* `reachable` and *not* `may_leak` are considered leaking.
self.memory.alloc_map.filter_map_collect(|id, (kind, alloc)| {
if kind.may_leak() || reachable.contains(id) {
None
} else {
Some((*id, *kind, alloc.clone()))
}
})
let leaked: Vec<_> = self.memory.alloc_map.filter_map_collect(|&id, &(kind, _)| {
if kind.may_leak() || reachable.contains(&id) { None } else { Some(id) }
});
let mut result = Vec::new();
for &id in leaked.iter() {
let (kind, alloc) = self.memory.alloc_map.remove(&id).unwrap();
result.push((id, kind, alloc));
}
result
}

/// Runs the closure in "validation" mode, which means the machine's memory read hooks will be
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use std::marker::PhantomData;
use std::ops::{Bound, Deref};
use std::{fmt, iter, mem};

use rustc_abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx};
use rustc_ast::{self as ast, attr};
use rustc_data_structures::defer;
use rustc_data_structures::fingerprint::Fingerprint;
Expand Down Expand Up @@ -48,7 +49,6 @@ use rustc_session::{Limit, MetadataKind, Session};
use rustc_span::def_id::{CRATE_DEF_ID, DefPathHash, StableCrateId};
use rustc_span::symbol::{Ident, Symbol, kw, sym};
use rustc_span::{DUMMY_SP, Span};
use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx};
use rustc_target::spec::abi;
use rustc_type_ir::TyKind::*;
use rustc_type_ir::fold::TypeFoldable;
Expand Down
Loading
Loading