1
Fork 0

make rustc_target usable outside of rustc

This commit is contained in:
hkalbasi 2022-10-28 18:45:55 +03:30
parent 1dda298ad3
commit 09a384643e
11 changed files with 163 additions and 77 deletions

View file

@ -7,6 +7,10 @@ edition = "2021"
[dependencies] [dependencies]
arrayvec = { version = "0.7", default-features = false } arrayvec = { version = "0.7", default-features = false }
rustc_serialize = { path = "../rustc_serialize" } rustc_serialize = { path = "../rustc_serialize", optional = true }
rustc_macros = { path = "../rustc_macros" } rustc_macros = { path = "../rustc_macros", optional = true }
smallvec = "1.8.1" smallvec = "1.8.1"
[features]
default = ["nightly"]
nightly = ["rustc_serialize", "rustc_macros"]

View file

@ -1,17 +1,20 @@
#![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)] #![deny(rustc::diagnostic_outside_of_impl)]
#![feature(allow_internal_unstable)] #![cfg_attr(feature = "nightly", feature(allow_internal_unstable))]
#![feature(extend_one)] #![cfg_attr(feature = "nightly", feature(extend_one))]
#![feature(min_specialization)] #![cfg_attr(feature = "nightly", feature(min_specialization))]
#![feature(new_uninit)] #![cfg_attr(feature = "nightly", feature(new_uninit))]
#![feature(step_trait)] #![cfg_attr(feature = "nightly", feature(step_trait))]
#![feature(stmt_expr_attributes)] #![cfg_attr(feature = "nightly", feature(stmt_expr_attributes))]
#![feature(test)] #![cfg_attr(feature = "nightly", feature(test))]
#[cfg(feature = "nightly")]
pub mod bit_set; pub mod bit_set;
#[cfg(feature = "nightly")]
pub mod interval; pub mod interval;
pub mod vec; pub mod vec;
#[cfg(feature = "rustc_macros")]
pub use rustc_macros::newtype_index; pub use rustc_macros::newtype_index;
/// Type size assertion. The first argument is a type and the second argument is its expected size. /// Type size assertion. The first argument is a type and the second argument is its expected size.

View file

@ -1,3 +1,4 @@
#[cfg(feature = "rustc_serialize")]
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use std::fmt; use std::fmt;
@ -61,12 +62,14 @@ pub struct IndexVec<I: Idx, T> {
// not the phantom data. // not the phantom data.
unsafe impl<I: Idx, T> Send for IndexVec<I, T> where T: Send {} unsafe impl<I: Idx, T> Send for IndexVec<I, T> where T: Send {}
#[cfg(feature = "rustc_serialize")]
impl<S: Encoder, I: Idx, T: Encodable<S>> Encodable<S> for IndexVec<I, T> { impl<S: Encoder, I: Idx, T: Encodable<S>> Encodable<S> for IndexVec<I, T> {
fn encode(&self, s: &mut S) { fn encode(&self, s: &mut S) {
Encodable::encode(&self.raw, s); Encodable::encode(&self.raw, s);
} }
} }
#[cfg(feature = "rustc_serialize")]
impl<D: Decoder, I: Idx, T: Decodable<D>> Decodable<D> for IndexVec<I, T> { impl<D: Decoder, I: Idx, T: Decodable<D>> Decodable<D> for IndexVec<I, T> {
fn decode(d: &mut D) -> Self { fn decode(d: &mut D) -> Self {
IndexVec { raw: Decodable::decode(d), _marker: PhantomData } IndexVec { raw: Decodable::decode(d), _marker: PhantomData }
@ -359,11 +362,13 @@ impl<I: Idx, T> Extend<T> for IndexVec<I, T> {
} }
#[inline] #[inline]
#[cfg(feature = "nightly")]
fn extend_one(&mut self, item: T) { fn extend_one(&mut self, item: T) {
self.raw.push(item); self.raw.push(item);
} }
#[inline] #[inline]
#[cfg(feature = "nightly")]
fn extend_reserve(&mut self, additional: usize) { fn extend_reserve(&mut self, additional: usize) {
self.raw.reserve(additional); self.raw.reserve(additional);
} }

View file

@ -6,7 +6,7 @@
macro_rules! arena_types { macro_rules! arena_types {
($macro:path) => ( ($macro:path) => (
$macro!([ $macro!([
[] layout: rustc_target::abi::LayoutS<'tcx>, [] layout: rustc_target::abi::LayoutS<rustc_target::abi::VariantIdx>,
[] fn_abi: rustc_target::abi::call::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>, [] fn_abi: rustc_target::abi::call::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>,
// AdtDef are interned and compared by address // AdtDef are interned and compared by address
[decode] adt_def: rustc_middle::ty::AdtDefData, [decode] adt_def: rustc_middle::ty::AdtDefData,

View file

@ -148,7 +148,7 @@ pub struct CtxtInterners<'tcx> {
const_: InternedSet<'tcx, ConstS<'tcx>>, const_: InternedSet<'tcx, ConstS<'tcx>>,
const_allocation: InternedSet<'tcx, Allocation>, const_allocation: InternedSet<'tcx, Allocation>,
bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>, bound_variable_kinds: InternedSet<'tcx, List<ty::BoundVariableKind>>,
layout: InternedSet<'tcx, LayoutS<'tcx>>, layout: InternedSet<'tcx, LayoutS<VariantIdx>>,
adt_def: InternedSet<'tcx, AdtDefData>, adt_def: InternedSet<'tcx, AdtDefData>,
} }
@ -2244,7 +2244,7 @@ direct_interners! {
region: mk_region(RegionKind<'tcx>): Region -> Region<'tcx>, region: mk_region(RegionKind<'tcx>): Region -> Region<'tcx>,
const_: mk_const_internal(ConstS<'tcx>): Const -> Const<'tcx>, const_: mk_const_internal(ConstS<'tcx>): Const -> Const<'tcx>,
const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>, const_allocation: intern_const_alloc(Allocation): ConstAllocation -> ConstAllocation<'tcx>,
layout: intern_layout(LayoutS<'tcx>): Layout -> Layout<'tcx>, layout: intern_layout(LayoutS<VariantIdx>): Layout -> Layout<'tcx>,
adt_def: intern_adt_def(AdtDefData): AdtDef -> AdtDef<'tcx>, adt_def: intern_adt_def(AdtDefData): AdtDef -> AdtDef<'tcx>,
} }

View file

@ -610,7 +610,7 @@ where
}) })
} }
Variants::Multiple { ref variants, .. } => variants[variant_index], Variants::Multiple { ref variants, .. } => cx.tcx().intern_layout(variants[variant_index].clone()),
}; };
assert_eq!(*layout.variants(), Variants::Single { index: variant_index }); assert_eq!(*layout.variants(), Variants::Single { index: variant_index });

View file

@ -7,9 +7,20 @@ edition = "2021"
bitflags = "1.2.1" bitflags = "1.2.1"
tracing = "0.1" tracing = "0.1"
serde_json = "1.0.59" serde_json = "1.0.59"
rustc_data_structures = { path = "../rustc_data_structures" } rustc_data_structures = { path = "../rustc_data_structures", optional = true }
rustc_feature = { path = "../rustc_feature" } rustc_feature = { path = "../rustc_feature", optional = true }
rustc_index = { path = "../rustc_index" } rustc_index = { path = "../rustc_index", default-features = false }
rustc_macros = { path = "../rustc_macros" } rustc_macros = { path = "../rustc_macros", optional = true }
rustc_serialize = { path = "../rustc_serialize" } rustc_serialize = { path = "../rustc_serialize", optional = true }
rustc_span = { path = "../rustc_span" } rustc_span = { path = "../rustc_span", optional = true }
[features]
default = ["nightly"]
nightly = [
"rustc_data_structures",
"rustc_feature",
"rustc_index/nightly",
"rustc_macros",
"rustc_serialize",
"rustc_span",
]

View file

@ -2,23 +2,29 @@ pub use Integer::*;
pub use Primitive::*; pub use Primitive::*;
use crate::json::{Json, ToJson}; use crate::json::{Json, ToJson};
#[cfg(feature = "nightly")]
use crate::spec::Target; use crate::spec::Target;
use std::convert::{TryFrom, TryInto}; use std::convert::{TryFrom, TryInto};
use std::fmt; use std::fmt;
#[cfg(feature = "nightly")]
use std::iter::Step; use std::iter::Step;
use std::num::{NonZeroUsize, ParseIntError}; use std::num::{NonZeroUsize, ParseIntError};
use std::ops::{Add, AddAssign, Deref, Mul, RangeInclusive, Sub}; use std::ops::{Add, AddAssign, Deref, Mul, RangeInclusive, Sub};
use std::str::FromStr; use std::str::FromStr;
#[cfg(feature = "nightly")]
use rustc_data_structures::intern::Interned; use rustc_data_structures::intern::Interned;
use rustc_index::vec::{Idx, IndexVec}; use rustc_index::vec::{Idx, IndexVec};
#[cfg(feature = "nightly")]
use rustc_macros::HashStable_Generic; use rustc_macros::HashStable_Generic;
#[cfg(feature = "nightly")]
pub mod call; pub mod call;
/// Parsed [Data layout](https://llvm.org/docs/LangRef.html#data-layout) /// Parsed [Data layout](https://llvm.org/docs/LangRef.html#data-layout)
/// for a target, which contains everything needed to compute layouts. /// for a target, which contains everything needed to compute layouts.
#[derive(Debug, PartialEq, Eq)]
pub struct TargetDataLayout { pub struct TargetDataLayout {
pub endian: Endian, pub endian: Endian,
pub i1_align: AbiAndPrefAlign, pub i1_align: AbiAndPrefAlign,
@ -80,6 +86,7 @@ pub enum TargetDataLayoutErrors<'a> {
} }
impl TargetDataLayout { impl TargetDataLayout {
#[cfg(feature = "nightly")]
pub fn parse<'a>(target: &'a Target) -> Result<TargetDataLayout, TargetDataLayoutErrors<'a>> { pub fn parse<'a>(target: &'a Target) -> Result<TargetDataLayout, TargetDataLayoutErrors<'a>> {
// Parse an address space index from a string. // Parse an address space index from a string.
let parse_address_space = |s: &'a str, cause: &'a str| { let parse_address_space = |s: &'a str, cause: &'a str| {
@ -248,7 +255,7 @@ impl HasDataLayout for TargetDataLayout {
} }
/// Endianness of the target, which must match cfg(target-endian). /// Endianness of the target, which must match cfg(target-endian).
#[derive(Copy, Clone, PartialEq)] #[derive(Copy, Clone, PartialEq, Eq)]
pub enum Endian { pub enum Endian {
Little, Little,
Big, Big,
@ -288,8 +295,8 @@ impl ToJson for Endian {
} }
/// Size of a type in bytes. /// Size of a type in bytes.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(HashStable_Generic)] #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
pub struct Size { pub struct Size {
raw: u64, raw: u64,
} }
@ -466,6 +473,7 @@ impl AddAssign for Size {
} }
} }
#[cfg(feature = "nightly")]
impl Step for Size { impl Step for Size {
#[inline] #[inline]
fn steps_between(start: &Self, end: &Self) -> Option<usize> { fn steps_between(start: &Self, end: &Self) -> Option<usize> {
@ -504,8 +512,8 @@ impl Step for Size {
} }
/// Alignment of a type in bytes (always a power of two). /// Alignment of a type in bytes (always a power of two).
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(HashStable_Generic)] #[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_Generic))]
pub struct Align { pub struct Align {
pow2: u8, pow2: u8,
} }
@ -588,7 +596,8 @@ impl Align {
/// A pair of alignments, ABI-mandated and preferred. /// A pair of alignments, ABI-mandated and preferred.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
#[derive(HashStable_Generic)] #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
pub struct AbiAndPrefAlign { pub struct AbiAndPrefAlign {
pub abi: Align, pub abi: Align,
pub pref: Align, pub pref: Align,
@ -612,7 +621,9 @@ impl AbiAndPrefAlign {
} }
/// Integers, also used for enum discriminants. /// Integers, also used for enum discriminants.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, HashStable_Generic)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
pub enum Integer { pub enum Integer {
I8, I8,
I16, I16,
@ -710,7 +721,8 @@ impl Integer {
} }
/// Fundamental unit of memory access and layout. /// Fundamental unit of memory access and layout.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)] #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
pub enum Primitive { pub enum Primitive {
/// The `bool` is the signedness of the `Integer` type. /// The `bool` is the signedness of the `Integer` type.
/// ///
@ -777,7 +789,7 @@ impl Primitive {
/// ///
/// This is intended specifically to mirror LLVMs `!range` metadata semantics. /// This is intended specifically to mirror LLVMs `!range` metadata semantics.
#[derive(Clone, Copy, PartialEq, Eq, Hash)] #[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[derive(HashStable_Generic)] #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
pub struct WrappingRange { pub struct WrappingRange {
pub start: u128, pub start: u128,
pub end: u128, pub end: u128,
@ -834,7 +846,7 @@ impl fmt::Debug for WrappingRange {
/// Information about one scalar component of a Rust type. /// Information about one scalar component of a Rust type.
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
#[derive(HashStable_Generic)] #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
pub enum Scalar { pub enum Scalar {
Initialized { Initialized {
value: Primitive, value: Primitive,
@ -924,7 +936,8 @@ impl Scalar {
} }
/// Describes how the fields of a type are located in memory. /// Describes how the fields of a type are located in memory.
#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] #[derive(PartialEq, Eq, Hash, Clone, Debug)]
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
pub enum FieldsShape { pub enum FieldsShape {
/// Scalar primitives and `!`, which never have fields. /// Scalar primitives and `!`, which never have fields.
Primitive, Primitive,
@ -1058,7 +1071,9 @@ impl AddressSpace {
/// Describes how values of the type are passed by target ABIs, /// Describes how values of the type are passed by target ABIs,
/// in terms of categories of C types there are ABI rules for. /// in terms of categories of C types there are ABI rules for.
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)] #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
pub enum Abi { pub enum Abi {
Uninhabited, Uninhabited,
Scalar(Scalar), Scalar(Scalar),
@ -1113,16 +1128,18 @@ impl Abi {
} }
} }
#[cfg(feature = "nightly")]
rustc_index::newtype_index! { rustc_index::newtype_index! {
pub struct VariantIdx { pub struct VariantIdx {
derive [HashStable_Generic] derive [HashStable_Generic]
} }
} }
#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] #[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub enum Variants<'a> { #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
pub enum Variants<V: Idx> {
/// Single enum variants, structs/tuples, unions, and all non-ADTs. /// Single enum variants, structs/tuples, unions, and all non-ADTs.
Single { index: VariantIdx }, Single { index: V },
/// Enum-likes with more than one inhabited variant: each variant comes with /// Enum-likes with more than one inhabited variant: each variant comes with
/// a *discriminant* (usually the same as the variant index but the user can /// a *discriminant* (usually the same as the variant index but the user can
@ -1132,14 +1149,15 @@ pub enum Variants<'a> {
/// For enums, the tag is the sole field of the layout. /// For enums, the tag is the sole field of the layout.
Multiple { Multiple {
tag: Scalar, tag: Scalar,
tag_encoding: TagEncoding, tag_encoding: TagEncoding<V>,
tag_field: usize, tag_field: usize,
variants: IndexVec<VariantIdx, Layout<'a>>, variants: IndexVec<V, LayoutS<V>>,
}, },
} }
#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] #[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub enum TagEncoding { #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
pub enum TagEncoding<V: Idx> {
/// The tag directly stores the discriminant, but possibly with a smaller layout /// The tag directly stores the discriminant, but possibly with a smaller layout
/// (so converting the tag to the discriminant can require sign extension). /// (so converting the tag to the discriminant can require sign extension).
Direct, Direct,
@ -1155,13 +1173,15 @@ pub enum TagEncoding {
/// `None` has a null pointer for the second tuple field, and /// `None` has a null pointer for the second tuple field, and
/// `Some` is the identity function (with a non-null reference). /// `Some` is the identity function (with a non-null reference).
Niche { Niche {
untagged_variant: VariantIdx, untagged_variant: V,
niche_variants: RangeInclusive<VariantIdx>, #[cfg(feature = "nightly")]
niche_variants: RangeInclusive<V>,
niche_start: u128, niche_start: u128,
}, },
} }
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)] #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
pub struct Niche { pub struct Niche {
pub offset: Size, pub offset: Size,
pub value: Primitive, pub value: Primitive,
@ -1244,8 +1264,9 @@ impl Niche {
} }
} }
#[derive(PartialEq, Eq, Hash, HashStable_Generic)] #[derive(PartialEq, Eq, Hash, Clone)]
pub struct LayoutS<'a> { #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
pub struct LayoutS<V: Idx> {
/// Says where the fields are located within the layout. /// Says where the fields are located within the layout.
pub fields: FieldsShape, pub fields: FieldsShape,
@ -1256,7 +1277,7 @@ pub struct LayoutS<'a> {
/// ///
/// To access all fields of this layout, both `fields` and the fields of the active variant /// To access all fields of this layout, both `fields` and the fields of the active variant
/// must be taken into account. /// must be taken into account.
pub variants: Variants<'a>, pub variants: Variants<V>,
/// The `abi` defines how this data is passed between functions, and it defines /// The `abi` defines how this data is passed between functions, and it defines
/// value restrictions via `valid_range`. /// value restrictions via `valid_range`.
@ -1275,13 +1296,13 @@ pub struct LayoutS<'a> {
pub size: Size, pub size: Size,
} }
impl<'a> LayoutS<'a> { impl<V: Idx> LayoutS<V> {
pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self { pub fn scalar<C: HasDataLayout>(cx: &C, scalar: Scalar) -> Self {
let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar); let largest_niche = Niche::from_scalar(cx, Size::ZERO, scalar);
let size = scalar.size(cx); let size = scalar.size(cx);
let align = scalar.align(cx); let align = scalar.align(cx);
LayoutS { LayoutS {
variants: Variants::Single { index: VariantIdx::new(0) }, variants: Variants::Single { index: V::new(0) },
fields: FieldsShape::Primitive, fields: FieldsShape::Primitive,
abi: Abi::Scalar(scalar), abi: Abi::Scalar(scalar),
largest_niche, largest_niche,
@ -1289,9 +1310,39 @@ impl<'a> LayoutS<'a> {
align, align,
} }
} }
#[inline]
pub fn fields(&self) -> &FieldsShape {
&self.fields
}
#[inline]
pub fn variants(&self) -> &Variants<V> {
&self.variants
}
#[inline]
pub fn abi(&self) -> Abi {
self.abi
}
#[inline]
pub fn largest_niche(&self) -> Option<Niche> {
self.largest_niche
}
#[inline]
pub fn align(&self) -> AbiAndPrefAlign {
self.align
}
#[inline]
pub fn size(&self) -> Size {
self.size
}
} }
impl<'a> fmt::Debug for LayoutS<'a> { impl<V: Idx> fmt::Debug for LayoutS<V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// This is how `Layout` used to print before it become // This is how `Layout` used to print before it become
// `Interned<LayoutS>`. We print it like this to avoid having to update // `Interned<LayoutS>`. We print it like this to avoid having to update
@ -1308,10 +1359,12 @@ impl<'a> fmt::Debug for LayoutS<'a> {
} }
} }
#[cfg(feature = "nightly")]
#[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)] #[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)]
#[rustc_pass_by_value] #[rustc_pass_by_value]
pub struct Layout<'a>(pub Interned<'a, LayoutS<'a>>); pub struct Layout<'a>(pub Interned<'a, LayoutS<VariantIdx>>);
#[cfg(feature = "nightly")]
impl<'a> fmt::Debug for Layout<'a> { impl<'a> fmt::Debug for Layout<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// See comment on `<LayoutS as Debug>::fmt` above. // See comment on `<LayoutS as Debug>::fmt` above.
@ -1319,12 +1372,13 @@ impl<'a> fmt::Debug for Layout<'a> {
} }
} }
#[cfg(feature = "nightly")]
impl<'a> Layout<'a> { impl<'a> Layout<'a> {
pub fn fields(self) -> &'a FieldsShape { pub fn fields(self) -> &'a FieldsShape {
&self.0.0.fields &self.0.0.fields
} }
pub fn variants(self) -> &'a Variants<'a> { pub fn variants(self) -> &'a Variants<VariantIdx> {
&self.0.0.variants &self.0.0.variants
} }
@ -1352,15 +1406,18 @@ impl<'a> Layout<'a> {
/// to that obtained from `layout_of(ty)`, as we need to produce /// to that obtained from `layout_of(ty)`, as we need to produce
/// layouts for which Rust types do not exist, such as enum variants /// layouts for which Rust types do not exist, such as enum variants
/// or synthetic fields of enums (i.e., discriminants) and fat pointers. /// or synthetic fields of enums (i.e., discriminants) and fat pointers.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable_Generic)] #[cfg(feature = "nightly")]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
pub struct TyAndLayout<'a, Ty> { pub struct TyAndLayout<'a, Ty> {
pub ty: Ty, pub ty: Ty,
pub layout: Layout<'a>, pub layout: Layout<'a>,
} }
#[cfg(feature = "nightly")]
impl<'a, Ty> Deref for TyAndLayout<'a, Ty> { impl<'a, Ty> Deref for TyAndLayout<'a, Ty> {
type Target = &'a LayoutS<'a>; type Target = &'a LayoutS<VariantIdx>;
fn deref(&self) -> &&'a LayoutS<'a> { fn deref(&self) -> &&'a LayoutS<VariantIdx> {
&self.layout.0.0 &self.layout.0.0
} }
} }
@ -1402,6 +1459,7 @@ pub enum InitKind {
/// Trait that needs to be implemented by the higher-level type representation /// Trait that needs to be implemented by the higher-level type representation
/// (e.g. `rustc_middle::ty::Ty`), to provide `rustc_target::abi` functionality. /// (e.g. `rustc_middle::ty::Ty`), to provide `rustc_target::abi` functionality.
#[cfg(feature = "nightly")]
pub trait TyAbiInterface<'a, C>: Sized { pub trait TyAbiInterface<'a, C>: Sized {
fn ty_and_layout_for_variant( fn ty_and_layout_for_variant(
this: TyAndLayout<'a, Self>, this: TyAndLayout<'a, Self>,
@ -1420,6 +1478,7 @@ pub trait TyAbiInterface<'a, C>: Sized {
fn is_unit(this: TyAndLayout<'a, Self>) -> bool; fn is_unit(this: TyAndLayout<'a, Self>) -> bool;
} }
#[cfg(feature = "nightly")]
impl<'a, Ty> TyAndLayout<'a, Ty> { impl<'a, Ty> TyAndLayout<'a, Ty> {
pub fn for_variant<C>(self, cx: &C, variant_index: VariantIdx) -> Self pub fn for_variant<C>(self, cx: &C, variant_index: VariantIdx) -> Self
where where
@ -1489,7 +1548,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
} }
} }
impl<'a, Ty> TyAndLayout<'a, Ty> { impl<V: Idx> LayoutS<V> {
/// Returns `true` if the layout corresponds to an unsized type. /// Returns `true` if the layout corresponds to an unsized type.
pub fn is_unsized(&self) -> bool { pub fn is_unsized(&self) -> bool {
self.abi.is_unsized() self.abi.is_unsized()

View file

@ -8,13 +8,13 @@
//! LLVM. //! LLVM.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(assert_matches)] #![cfg_attr(feature = "nightly", feature(assert_matches))]
#![feature(associated_type_bounds)] #![cfg_attr(feature = "nightly", feature(associated_type_bounds))]
#![feature(exhaustive_patterns)] #![cfg_attr(feature = "nightly", feature(exhaustive_patterns))]
#![feature(min_specialization)] #![cfg_attr(feature = "nightly", feature(min_specialization))]
#![feature(never_type)] #![cfg_attr(feature = "nightly", feature(never_type))]
#![feature(rustc_attrs)] #![cfg_attr(feature = "nightly", feature(rustc_attrs))]
#![feature(step_trait)] #![cfg_attr(feature = "nightly", feature(step_trait))]
#![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)] #![deny(rustc::diagnostic_outside_of_impl)]
@ -22,14 +22,18 @@ use std::iter::FromIterator;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
#[macro_use] #[macro_use]
#[cfg(feature = "nightly")]
extern crate rustc_macros; extern crate rustc_macros;
#[macro_use] #[macro_use]
#[cfg(feature = "nightly")]
extern crate tracing; extern crate tracing;
pub mod abi; pub mod abi;
#[cfg(feature = "nightly")]
pub mod asm; pub mod asm;
pub mod json; pub mod json;
#[cfg(feature = "nightly")]
pub mod spec; pub mod spec;
#[cfg(test)] #[cfg(test)]

View file

@ -89,7 +89,11 @@ fn invert_mapping(map: &[u32]) -> Vec<u32> {
inverse inverse
} }
fn scalar_pair<'tcx>(cx: &LayoutCx<'tcx, TyCtxt<'tcx>>, a: Scalar, b: Scalar) -> LayoutS<'tcx> { fn scalar_pair<'tcx>(
cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
a: Scalar,
b: Scalar,
) -> LayoutS<VariantIdx> {
let dl = cx.data_layout(); let dl = cx.data_layout();
let b_align = b.align(dl); let b_align = b.align(dl);
let align = a.align(dl).max(b_align).max(dl.aggregate_align); let align = a.align(dl).max(b_align).max(dl.aggregate_align);
@ -122,7 +126,7 @@ fn univariant_uninterned<'tcx>(
fields: &[TyAndLayout<'_>], fields: &[TyAndLayout<'_>],
repr: &ReprOptions, repr: &ReprOptions,
kind: StructKind, kind: StructKind,
) -> Result<LayoutS<'tcx>, LayoutError<'tcx>> { ) -> Result<LayoutS<VariantIdx>, LayoutError<'tcx>> {
let dl = cx.data_layout(); let dl = cx.data_layout();
let pack = repr.pack; let pack = repr.pack;
if pack.is_some() && repr.align.is_some() { if pack.is_some() && repr.align.is_some() {
@ -864,13 +868,13 @@ fn layout_of_uncached<'tcx>(
// variant layouts, so we can't store them in the // variant layouts, so we can't store them in the
// overall LayoutS. Store the overall LayoutS // overall LayoutS. Store the overall LayoutS
// and the variant LayoutSs here until then. // and the variant LayoutSs here until then.
struct TmpLayout<'tcx> { struct TmpLayout {
layout: LayoutS<'tcx>, layout: LayoutS<VariantIdx>,
variants: IndexVec<VariantIdx, LayoutS<'tcx>>, variants: IndexVec<VariantIdx, LayoutS<VariantIdx>>,
} }
let calculate_niche_filling_layout = let calculate_niche_filling_layout =
|| -> Result<Option<TmpLayout<'tcx>>, LayoutError<'tcx>> { || -> Result<Option<TmpLayout>, LayoutError<'tcx>> {
// The current code for niche-filling relies on variant indices // The current code for niche-filling relies on variant indices
// instead of actual discriminants, so enums with // instead of actual discriminants, so enums with
// explicit discriminants (RFC #2363) would misbehave. // explicit discriminants (RFC #2363) would misbehave.
@ -1317,7 +1321,7 @@ fn layout_of_uncached<'tcx>(
// pick the layout with the larger niche; otherwise, // pick the layout with the larger niche; otherwise,
// pick tagged as it has simpler codegen. // pick tagged as it has simpler codegen.
use Ordering::*; use Ordering::*;
let niche_size = |tmp_l: &TmpLayout<'_>| { let niche_size = |tmp_l: &TmpLayout| {
tmp_l.layout.largest_niche.map_or(0, |n| n.available(dl)) tmp_l.layout.largest_niche.map_or(0, |n| n.available(dl))
}; };
match ( match (
@ -1338,11 +1342,7 @@ fn layout_of_uncached<'tcx>(
tag, tag,
tag_encoding, tag_encoding,
tag_field, tag_field,
variants: best_layout variants: best_layout.variants,
.variants
.into_iter()
.map(|layout| tcx.intern_layout(layout))
.collect(),
}, },
_ => bug!(), _ => bug!(),
}; };
@ -1657,7 +1657,7 @@ fn generator_layout<'tcx>(
size = size.max(variant.size); size = size.max(variant.size);
align = align.max(variant.align); align = align.max(variant.align);
Ok(tcx.intern_layout(variant)) Ok(variant)
}) })
.collect::<Result<IndexVec<VariantIdx, _>, _>>()?; .collect::<Result<IndexVec<VariantIdx, _>, _>>()?;

View file

@ -10,7 +10,7 @@ use rustc_middle::ty::layout::LayoutError;
use rustc_middle::ty::{self, Adt, TyCtxt}; use rustc_middle::ty::{self, Adt, TyCtxt};
use rustc_span::hygiene::MacroKind; use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::symbol::{kw, sym, Symbol};
use rustc_target::abi::{Layout, Primitive, TagEncoding, Variants}; use rustc_target::abi::{LayoutS, Primitive, TagEncoding, VariantIdx, Variants};
use std::cmp::Ordering; use std::cmp::Ordering;
use std::fmt; use std::fmt;
use std::rc::Rc; use std::rc::Rc;
@ -1892,7 +1892,7 @@ fn document_non_exhaustive(w: &mut Buffer, item: &clean::Item) {
} }
fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) {
fn write_size_of_layout(w: &mut Buffer, layout: Layout<'_>, tag_size: u64) { fn write_size_of_layout(w: &mut Buffer, layout: &LayoutS<VariantIdx>, tag_size: u64) {
if layout.abi().is_unsized() { if layout.abi().is_unsized() {
write!(w, "(unsized)"); write!(w, "(unsized)");
} else { } else {
@ -1927,7 +1927,7 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) {
chapter for details on type layout guarantees.</p></div>" chapter for details on type layout guarantees.</p></div>"
); );
w.write_str("<p><strong>Size:</strong> "); w.write_str("<p><strong>Size:</strong> ");
write_size_of_layout(w, ty_layout.layout, 0); write_size_of_layout(w, &ty_layout.layout.0, 0);
writeln!(w, "</p>"); writeln!(w, "</p>");
if let Variants::Multiple { variants, tag, tag_encoding, .. } = if let Variants::Multiple { variants, tag, tag_encoding, .. } =
&ty_layout.layout.variants() &ty_layout.layout.variants()
@ -1953,7 +1953,7 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) {
for (index, layout) in variants.iter_enumerated() { for (index, layout) in variants.iter_enumerated() {
let name = adt.variant(index).name; let name = adt.variant(index).name;
write!(w, "<li><code>{name}</code>: ", name = name); write!(w, "<li><code>{name}</code>: ", name = name);
write_size_of_layout(w, *layout, tag_size); write_size_of_layout(w, layout, tag_size);
writeln!(w, "</li>"); writeln!(w, "</li>");
} }
w.write_str("</ul>"); w.write_str("</ul>");