1
Fork 0

move things from rustc_target::abi to rustc_abi

This commit is contained in:
hkalbasi 2022-11-07 00:36:11 +03:30
parent 27fb904d68
commit 390a637e29
21 changed files with 1700 additions and 1673 deletions

View file

@ -3202,6 +3202,20 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "rustc_abi"
version = "0.0.0"
dependencies = [
"bitflags",
"rand 0.8.5",
"rand_xoshiro",
"rustc_data_structures",
"rustc_index",
"rustc_macros",
"rustc_serialize",
"tracing",
]
[[package]] [[package]]
name = "rustc_apfloat" name = "rustc_apfloat"
version = "0.0.0" version = "0.0.0"
@ -4281,8 +4295,7 @@ name = "rustc_target"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"rand 0.8.5", "rustc_abi",
"rand_xoshiro",
"rustc_data_structures", "rustc_data_structures",
"rustc_feature", "rustc_feature",
"rustc_index", "rustc_index",
@ -4363,8 +4376,6 @@ dependencies = [
name = "rustc_ty_utils" name = "rustc_ty_utils"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"rand 0.8.5",
"rand_xoshiro",
"rustc_data_structures", "rustc_data_structures",
"rustc_errors", "rustc_errors",
"rustc_hir", "rustc_hir",

View file

@ -0,0 +1,24 @@
[package]
name = "rustc_abi"
version = "0.0.0"
edition = "2021"
[dependencies]
bitflags = "1.2.1"
tracing = "0.1"
rand = { version = "0.8.4", default-features = false, optional = true }
rand_xoshiro = { version = "0.6.0", optional = true }
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
rustc_index = { path = "../rustc_index", default-features = false }
rustc_macros = { path = "../rustc_macros", optional = true }
rustc_serialize = { path = "../rustc_serialize", optional = true }
[features]
default = ["nightly", "randomize"]
randomize = ["rand", "rand_xoshiro"]
nightly = [
"rustc_data_structures",
"rustc_index/nightly",
"rustc_macros",
"rustc_serialize",
]

View file

@ -7,7 +7,9 @@ use std::{
ops::{Bound, Deref}, ops::{Bound, Deref},
}; };
#[cfg(feature = "randomize")]
use rand::{seq::SliceRandom, SeedableRng}; use rand::{seq::SliceRandom, SeedableRng};
#[cfg(feature = "randomize")]
use rand_xoshiro::Xoshiro128StarStar; use rand_xoshiro::Xoshiro128StarStar;
use tracing::debug; use tracing::debug;
@ -91,14 +93,16 @@ pub trait LayoutCalculator {
// If `-Z randomize-layout` was enabled for the type definition we can shuffle // If `-Z randomize-layout` was enabled for the type definition we can shuffle
// the field ordering to try and catch some code making assumptions about layouts // the field ordering to try and catch some code making assumptions about layouts
// we don't guarantee // we don't guarantee
if repr.can_randomize_type_layout() { if repr.can_randomize_type_layout() && cfg!(feature = "randomize") {
// `ReprOptions.layout_seed` is a deterministic seed that we can use to #[cfg(feature = "randomize")]
// randomize field ordering with {
let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed); // `ReprOptions.layout_seed` is a deterministic seed that we can use to
// randomize field ordering with
// Shuffle the ordering of the fields let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed);
optimizing.shuffle(&mut rng);
// Shuffle the ordering of the fields
optimizing.shuffle(&mut rng);
}
// Otherwise we just leave things alone and actually optimize the type's fields // Otherwise we just leave things alone and actually optimize the type's fields
} else { } else {
match kind { match kind {
@ -900,7 +904,7 @@ pub trait LayoutCalculator {
let mut abi = Abi::Aggregate { sized: true }; let mut abi = Abi::Aggregate { sized: true };
let index = V::new(0); let index = V::new(0);
for field in &variants[index] { for field in &variants[index] {
assert!(!field.is_unsized()); assert!(field.is_sized());
align = align.max(field.align); align = align.max(field.align);
// If all non-ZST fields have the same ABI, forward this ABI // If all non-ZST fields have the same ABI, forward this ABI

File diff suppressed because it is too large Load diff

View file

@ -32,7 +32,6 @@ use rustc_middle::hir::nested_filter;
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
use rustc_middle::mir::mono::Linkage; use rustc_middle::mir::mono::Linkage;
use rustc_middle::ty::query::Providers; use rustc_middle::ty::query::Providers;
use rustc_middle::ty::repr_options_of_def;
use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::util::{Discr, IntTypeExt};
use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, IsSuggestable, Ty, TyCtxt}; use rustc_middle::ty::{self, AdtKind, Const, DefIdTree, IsSuggestable, Ty, TyCtxt};
use rustc_session::lint; use rustc_session::lint;
@ -860,7 +859,7 @@ fn adt_def<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::AdtDef<'tcx> {
bug!(); bug!();
}; };
let repr = repr_options_of_def(tcx, def_id.to_def_id()); let repr = tcx.repr_options_of_def(def_id.to_def_id());
let (kind, variants) = match item.kind { let (kind, variants) = match item.kind {
ItemKind::Enum(ref def, _) => { ItemKind::Enum(ref def, _) => {
let mut distance_from_explicit = 0; let mut distance_from_explicit = 0;

View file

@ -1,12 +1,17 @@
#![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)] #![deny(rustc::diagnostic_outside_of_impl)]
#![cfg_attr(feature = "nightly", feature(allow_internal_unstable))] #![cfg_attr(
#![cfg_attr(feature = "nightly", feature(extend_one))] feature = "nightly",
#![cfg_attr(feature = "nightly", feature(min_specialization))] feature(
#![cfg_attr(feature = "nightly", feature(new_uninit))] allow_internal_unstable,
#![cfg_attr(feature = "nightly", feature(step_trait))] extend_one,
#![cfg_attr(feature = "nightly", feature(stmt_expr_attributes))] min_specialization,
#![cfg_attr(feature = "nightly", feature(test))] new_uninit,
step_trait,
stmt_expr_attributes,
test
)
)]
#[cfg(feature = "nightly")] #[cfg(feature = "nightly")]
pub mod bit_set; pub mod bit_set;

View file

@ -1378,7 +1378,7 @@ impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences {
let (largest, slargest, largest_index) = iter::zip(enum_definition.variants, variants) let (largest, slargest, largest_index) = iter::zip(enum_definition.variants, variants)
.map(|(variant, variant_layout)| { .map(|(variant, variant_layout)| {
// Subtract the size of the enum tag. // Subtract the size of the enum tag.
let bytes = variant_layout.size().bytes().saturating_sub(tag_size); let bytes = variant_layout.size.bytes().saturating_sub(tag_size);
debug!("- variant `{}` is {} bytes large", variant.ident, bytes); debug!("- variant `{}` is {} bytes large", variant.ident, bytes);
bytes bytes

View file

@ -1233,7 +1233,7 @@ impl<'tcx> TyCtxt<'tcx> {
global_ctxt: untracked_resolutions, global_ctxt: untracked_resolutions,
ast_lowering: untracked_resolver_for_lowering, ast_lowering: untracked_resolver_for_lowering,
} = resolver_outputs; } = resolver_outputs;
let data_layout = TargetDataLayout::parse(&s.target).unwrap_or_else(|err| { let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| {
s.emit_fatal(err); s.emit_fatal(err);
}); });
let interners = CtxtInterners::new(arena); let interners = CtxtInterners::new(arena);

View file

@ -1995,78 +1995,6 @@ impl Hash for FieldDef {
} }
} }
pub fn repr_options_of_def(tcx: TyCtxt<'_>, did: DefId) -> ReprOptions {
let mut flags = ReprFlags::empty();
let mut size = None;
let mut max_align: Option<Align> = None;
let mut min_pack: Option<Align> = None;
// Generate a deterministically-derived seed from the item's path hash
// to allow for cross-crate compilation to actually work
let mut field_shuffle_seed = tcx.def_path_hash(did).0.to_smaller_hash();
// If the user defined a custom seed for layout randomization, xor the item's
// path hash with the user defined seed, this will allowing determinism while
// still allowing users to further randomize layout generation for e.g. fuzzing
if let Some(user_seed) = tcx.sess.opts.unstable_opts.layout_seed {
field_shuffle_seed ^= user_seed;
}
for attr in tcx.get_attrs(did, sym::repr) {
for r in attr::parse_repr_attr(&tcx.sess, attr) {
flags.insert(match r {
attr::ReprC => ReprFlags::IS_C,
attr::ReprPacked(pack) => {
let pack = Align::from_bytes(pack as u64).unwrap();
min_pack =
Some(if let Some(min_pack) = min_pack { min_pack.min(pack) } else { pack });
ReprFlags::empty()
}
attr::ReprTransparent => ReprFlags::IS_TRANSPARENT,
attr::ReprSimd => ReprFlags::IS_SIMD,
attr::ReprInt(i) => {
size = Some(match i {
attr::IntType::SignedInt(x) => match x {
ast::IntTy::Isize => IntegerType::Pointer(true),
ast::IntTy::I8 => IntegerType::Fixed(Integer::I8, true),
ast::IntTy::I16 => IntegerType::Fixed(Integer::I16, true),
ast::IntTy::I32 => IntegerType::Fixed(Integer::I32, true),
ast::IntTy::I64 => IntegerType::Fixed(Integer::I64, true),
ast::IntTy::I128 => IntegerType::Fixed(Integer::I128, true),
},
attr::IntType::UnsignedInt(x) => match x {
ast::UintTy::Usize => IntegerType::Pointer(false),
ast::UintTy::U8 => IntegerType::Fixed(Integer::I8, false),
ast::UintTy::U16 => IntegerType::Fixed(Integer::I16, false),
ast::UintTy::U32 => IntegerType::Fixed(Integer::I32, false),
ast::UintTy::U64 => IntegerType::Fixed(Integer::I64, false),
ast::UintTy::U128 => IntegerType::Fixed(Integer::I128, false),
},
});
ReprFlags::empty()
}
attr::ReprAlign(align) => {
max_align = max_align.max(Some(Align::from_bytes(align as u64).unwrap()));
ReprFlags::empty()
}
});
}
}
// If `-Z randomize-layout` was enabled for the type definition then we can
// consider performing layout randomization
if tcx.sess.opts.unstable_opts.randomize_layout {
flags.insert(ReprFlags::RANDOMIZE_LAYOUT);
}
// This is here instead of layout because the choice must make it into metadata.
if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.def_path_str(did))) {
flags.insert(ReprFlags::IS_LINEAR);
}
ReprOptions { int: size, align: max_align, pack: min_pack, flags, field_shuffle_seed }
}
impl<'tcx> FieldDef { impl<'tcx> FieldDef {
/// Returns the type of this field. The resulting type is not normalized. The `subst` is /// Returns the type of this field. The resulting type is not normalized. The `subst` is
/// typically obtained via the second field of [`TyKind::Adt`]. /// typically obtained via the second field of [`TyKind::Adt`].
@ -2134,6 +2062,81 @@ impl<'tcx> TyCtxt<'tcx> {
.filter(move |item| item.kind == AssocKind::Fn && item.defaultness(self).has_value()) .filter(move |item| item.kind == AssocKind::Fn && item.defaultness(self).has_value())
} }
pub fn repr_options_of_def(self, did: DefId) -> ReprOptions {
let mut flags = ReprFlags::empty();
let mut size = None;
let mut max_align: Option<Align> = None;
let mut min_pack: Option<Align> = None;
// Generate a deterministically-derived seed from the item's path hash
// to allow for cross-crate compilation to actually work
let mut field_shuffle_seed = self.def_path_hash(did).0.to_smaller_hash();
// If the user defined a custom seed for layout randomization, xor the item's
// path hash with the user defined seed, this will allowing determinism while
// still allowing users to further randomize layout generation for e.g. fuzzing
if let Some(user_seed) = self.sess.opts.unstable_opts.layout_seed {
field_shuffle_seed ^= user_seed;
}
for attr in self.get_attrs(did, sym::repr) {
for r in attr::parse_repr_attr(&self.sess, attr) {
flags.insert(match r {
attr::ReprC => ReprFlags::IS_C,
attr::ReprPacked(pack) => {
let pack = Align::from_bytes(pack as u64).unwrap();
min_pack = Some(if let Some(min_pack) = min_pack {
min_pack.min(pack)
} else {
pack
});
ReprFlags::empty()
}
attr::ReprTransparent => ReprFlags::IS_TRANSPARENT,
attr::ReprSimd => ReprFlags::IS_SIMD,
attr::ReprInt(i) => {
size = Some(match i {
attr::IntType::SignedInt(x) => match x {
ast::IntTy::Isize => IntegerType::Pointer(true),
ast::IntTy::I8 => IntegerType::Fixed(Integer::I8, true),
ast::IntTy::I16 => IntegerType::Fixed(Integer::I16, true),
ast::IntTy::I32 => IntegerType::Fixed(Integer::I32, true),
ast::IntTy::I64 => IntegerType::Fixed(Integer::I64, true),
ast::IntTy::I128 => IntegerType::Fixed(Integer::I128, true),
},
attr::IntType::UnsignedInt(x) => match x {
ast::UintTy::Usize => IntegerType::Pointer(false),
ast::UintTy::U8 => IntegerType::Fixed(Integer::I8, false),
ast::UintTy::U16 => IntegerType::Fixed(Integer::I16, false),
ast::UintTy::U32 => IntegerType::Fixed(Integer::I32, false),
ast::UintTy::U64 => IntegerType::Fixed(Integer::I64, false),
ast::UintTy::U128 => IntegerType::Fixed(Integer::I128, false),
},
});
ReprFlags::empty()
}
attr::ReprAlign(align) => {
max_align = max_align.max(Some(Align::from_bytes(align as u64).unwrap()));
ReprFlags::empty()
}
});
}
}
// If `-Z randomize-layout` was enabled for the type definition then we can
// consider performing layout randomization
if self.sess.opts.unstable_opts.randomize_layout {
flags.insert(ReprFlags::RANDOMIZE_LAYOUT);
}
// This is here instead of layout because the choice must make it into metadata.
if !self.consider_optimizing(|| format!("Reorder fields of {:?}", self.def_path_str(did))) {
flags.insert(ReprFlags::IS_LINEAR);
}
ReprOptions { int: size, align: max_align, pack: min_pack, flags, field_shuffle_seed }
}
/// Look up the name of a definition across crates. This does not look at HIR. /// Look up the name of a definition across crates. This does not look at HIR.
pub fn opt_item_name(self, def_id: DefId) -> Option<Symbol> { pub fn opt_item_name(self, def_id: DefId) -> Option<Symbol> {
if let Some(cnum) = def_id.as_crate_root() { if let Some(cnum) = def_id.as_crate_root() {

View file

@ -65,7 +65,7 @@ fn variant_discriminants<'tcx>(
Variants::Multiple { variants, .. } => variants Variants::Multiple { variants, .. } => variants
.iter_enumerated() .iter_enumerated()
.filter_map(|(idx, layout)| { .filter_map(|(idx, layout)| {
(layout.abi() != Abi::Uninhabited) (layout.abi != Abi::Uninhabited)
.then(|| ty.discriminant_for_variant(tcx, idx).unwrap().val) .then(|| ty.discriminant_for_variant(tcx, idx).unwrap().val)
}) })
.collect(), .collect(),

View file

@ -11,7 +11,7 @@ use crate::{lint, HashStableContext};
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::stable_hasher::ToStableHashKey; use rustc_data_structures::stable_hasher::ToStableHashKey;
use rustc_target::abi::{Align, TargetDataLayout}; use rustc_target::abi::Align;
use rustc_target::spec::{PanicStrategy, SanitizerSet, SplitDebuginfo}; use rustc_target::spec::{PanicStrategy, SanitizerSet, SplitDebuginfo};
use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS}; use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS};
@ -900,7 +900,7 @@ fn default_configuration(sess: &Session) -> CrateConfig {
let min_atomic_width = sess.target.min_atomic_width(); let min_atomic_width = sess.target.min_atomic_width();
let max_atomic_width = sess.target.max_atomic_width(); let max_atomic_width = sess.target.max_atomic_width();
let atomic_cas = sess.target.atomic_cas; let atomic_cas = sess.target.atomic_cas;
let layout = TargetDataLayout::parse(&sess.target).unwrap_or_else(|err| { let layout = sess.target.parse_data_layout().unwrap_or_else(|err| {
sess.emit_fatal(err); sess.emit_fatal(err);
}); });

View file

@ -6,23 +6,11 @@ edition = "2021"
[dependencies] [dependencies]
bitflags = "1.2.1" bitflags = "1.2.1"
tracing = "0.1" tracing = "0.1"
rand = "0.8.4"
rand_xoshiro = "0.6.0"
serde_json = "1.0.59" serde_json = "1.0.59"
rustc_data_structures = { path = "../rustc_data_structures", optional = true } rustc_abi = { path = "../rustc_abi" }
rustc_feature = { path = "../rustc_feature", optional = true } rustc_data_structures = { path = "../rustc_data_structures" }
rustc_index = { path = "../rustc_index", default-features = false } rustc_feature = { path = "../rustc_feature" }
rustc_macros = { path = "../rustc_macros", optional = true } rustc_index = { path = "../rustc_index" }
rustc_serialize = { path = "../rustc_serialize", optional = true } rustc_macros = { path = "../rustc_macros" }
rustc_span = { path = "../rustc_span", optional = true } rustc_serialize = { path = "../rustc_serialize" }
rustc_span = { path = "../rustc_span" }
[features]
default = ["nightly"]
nightly = [
"rustc_data_structures",
"rustc_feature",
"rustc_index/nightly",
"rustc_macros",
"rustc_serialize",
"rustc_span",
]

View file

@ -262,7 +262,7 @@ impl CastTarget {
let mut size = self.rest.total; let mut size = self.rest.total;
for i in 0..self.prefix.iter().count() { for i in 0..self.prefix.iter().count() {
match self.prefix[i] { match self.prefix[i] {
Some(v) => size += Size { raw: v.size.bytes() }, Some(v) => size += v.size,
None => {} None => {}
} }
} }

View file

@ -87,8 +87,8 @@ where
_ => {} _ => {}
} }
if (offset.raw % 4) != 0 && scalar2.primitive().is_float() { if (offset.bytes() % 4) != 0 && scalar2.primitive().is_float() {
offset.raw += 4 - (offset.raw % 4); offset += Size::from_bytes(4 - (offset.bytes() % 4));
} }
data = arg_scalar(cx, &scalar2, offset, data); data = arg_scalar(cx, &scalar2, offset, data);
return data; return data;
@ -169,14 +169,14 @@ where
has_float: false, has_float: false,
arg_attribute: ArgAttribute::default(), arg_attribute: ArgAttribute::default(),
}, },
Size { raw: 0 }, Size::ZERO,
); );
if data.has_float { if data.has_float {
// Structure { float, int, int } doesn't like to be handled like // Structure { float, int, int } doesn't like to be handled like
// { float, long int }. Other way around it doesn't mind. // { float, long int }. Other way around it doesn't mind.
if data.last_offset < arg.layout.size if data.last_offset < arg.layout.size
&& (data.last_offset.raw % 8) != 0 && (data.last_offset.bytes() % 8) != 0
&& data.prefix_index < data.prefix.len() && data.prefix_index < data.prefix.len()
{ {
data.prefix[data.prefix_index] = Some(Reg::i32()); data.prefix[data.prefix_index] = Some(Reg::i32());
@ -185,7 +185,7 @@ where
} }
let mut rest_size = arg.layout.size - data.last_offset; let mut rest_size = arg.layout.size - data.last_offset;
if (rest_size.raw % 8) != 0 && data.prefix_index < data.prefix.len() { if (rest_size.bytes() % 8) != 0 && data.prefix_index < data.prefix.len() {
data.prefix[data.prefix_index] = Some(Reg::i32()); data.prefix[data.prefix_index] = Some(Reg::i32());
rest_size = rest_size - Reg::i32().size; rest_size = rest_size - Reg::i32().size;
} }
@ -214,13 +214,13 @@ where
C: HasDataLayout, C: HasDataLayout,
{ {
if !fn_abi.ret.is_ignore() { if !fn_abi.ret.is_ignore() {
classify_arg(cx, &mut fn_abi.ret, Size { raw: 32 }); classify_arg(cx, &mut fn_abi.ret, Size::from_bytes(32));
} }
for arg in fn_abi.args.iter_mut() { for arg in fn_abi.args.iter_mut() {
if arg.is_ignore() { if arg.is_ignore() {
continue; continue;
} }
classify_arg(cx, arg, Size { raw: 16 }); classify_arg(cx, arg, Size::from_bytes(16));
} }
} }

File diff suppressed because it is too large Load diff

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/")]
#![cfg_attr(feature = "nightly", feature(assert_matches))] #![feature(assert_matches)]
#![cfg_attr(feature = "nightly", feature(associated_type_bounds))] #![feature(associated_type_bounds)]
#![cfg_attr(feature = "nightly", feature(exhaustive_patterns))] #![feature(exhaustive_patterns)]
#![cfg_attr(feature = "nightly", feature(min_specialization))] #![feature(min_specialization)]
#![cfg_attr(feature = "nightly", feature(never_type))] #![feature(never_type)]
#![cfg_attr(feature = "nightly", feature(rustc_attrs))] #![feature(rustc_attrs)]
#![cfg_attr(feature = "nightly", feature(step_trait))] #![feature(step_trait)]
#![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)] #![deny(rustc::diagnostic_outside_of_impl)]
@ -22,27 +22,20 @@ 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)]
mod tests; mod tests;
/// Requirements for a `StableHashingContext` to be used in this crate. pub use rustc_abi::HashStableContext;
/// This is a hack to allow using the `HashStable_Generic` derive macro
/// instead of implementing everything in `rustc_middle`.
pub trait HashStableContext {}
/// The name of rustc's own place to organize libraries. /// The name of rustc's own place to organize libraries.
/// ///

View file

@ -35,7 +35,10 @@
//! to the list specified by the target, rather than replace. //! to the list specified by the target, rather than replace.
use crate::abi::call::Conv; use crate::abi::call::Conv;
use crate::abi::Endian; use crate::abi::{
AbiAndPrefAlign, AddressSpace, Align, Endian, Integer, Size, TargetDataLayout,
TargetDataLayoutErrors,
};
use crate::json::{Json, ToJson}; use crate::json::{Json, ToJson};
use crate::spec::abi::{lookup as lookup_abi, Abi}; use crate::spec::abi::{lookup as lookup_abi, Abi};
use crate::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault}; use crate::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault};
@ -1317,6 +1320,120 @@ pub struct Target {
pub options: TargetOptions, pub options: TargetOptions,
} }
impl Target {
pub fn parse_data_layout<'a>(&'a self) -> Result<TargetDataLayout, TargetDataLayoutErrors<'a>> {
// Parse an address space index from a string.
let parse_address_space = |s: &'a str, cause: &'a str| {
s.parse::<u32>().map(AddressSpace).map_err(|err| {
TargetDataLayoutErrors::InvalidAddressSpace { addr_space: s, cause, err }
})
};
// Parse a bit count from a string.
let parse_bits = |s: &'a str, kind: &'a str, cause: &'a str| {
s.parse::<u64>().map_err(|err| TargetDataLayoutErrors::InvalidBits {
kind,
bit: s,
cause,
err,
})
};
// Parse a size string.
let size = |s: &'a str, cause: &'a str| parse_bits(s, "size", cause).map(Size::from_bits);
// Parse an alignment string.
let align = |s: &[&'a str], cause: &'a str| {
if s.is_empty() {
return Err(TargetDataLayoutErrors::MissingAlignment { cause });
}
let align_from_bits = |bits| {
Align::from_bits(bits)
.map_err(|err| TargetDataLayoutErrors::InvalidAlignment { cause, err })
};
let abi = parse_bits(s[0], "alignment", cause)?;
let pref = s.get(1).map_or(Ok(abi), |pref| parse_bits(pref, "alignment", cause))?;
Ok(AbiAndPrefAlign { abi: align_from_bits(abi)?, pref: align_from_bits(pref)? })
};
let mut dl = TargetDataLayout::default();
let mut i128_align_src = 64;
for spec in self.data_layout.split('-') {
let spec_parts = spec.split(':').collect::<Vec<_>>();
match &*spec_parts {
["e"] => dl.endian = Endian::Little,
["E"] => dl.endian = Endian::Big,
[p] if p.starts_with('P') => {
dl.instruction_address_space = parse_address_space(&p[1..], "P")?
}
["a", ref a @ ..] => dl.aggregate_align = align(a, "a")?,
["f32", ref a @ ..] => dl.f32_align = align(a, "f32")?,
["f64", ref a @ ..] => dl.f64_align = align(a, "f64")?,
[p @ "p", s, ref a @ ..] | [p @ "p0", s, ref a @ ..] => {
dl.pointer_size = size(s, p)?;
dl.pointer_align = align(a, p)?;
}
[s, ref a @ ..] if s.starts_with('i') => {
let Ok(bits) = s[1..].parse::<u64>() else {
size(&s[1..], "i")?; // For the user error.
continue;
};
let a = align(a, s)?;
match bits {
1 => dl.i1_align = a,
8 => dl.i8_align = a,
16 => dl.i16_align = a,
32 => dl.i32_align = a,
64 => dl.i64_align = a,
_ => {}
}
if bits >= i128_align_src && bits <= 128 {
// Default alignment for i128 is decided by taking the alignment of
// largest-sized i{64..=128}.
i128_align_src = bits;
dl.i128_align = a;
}
}
[s, ref a @ ..] if s.starts_with('v') => {
let v_size = size(&s[1..], "v")?;
let a = align(a, s)?;
if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) {
v.1 = a;
continue;
}
// No existing entry, add a new one.
dl.vector_align.push((v_size, a));
}
_ => {} // Ignore everything else.
}
}
// Perform consistency checks against the Target information.
if dl.endian != self.endian {
return Err(TargetDataLayoutErrors::InconsistentTargetArchitecture {
dl: dl.endian.as_str(),
target: self.endian.as_str(),
});
}
let target_pointer_width: u64 = self.pointer_width.into();
if dl.pointer_size.bits() != target_pointer_width {
return Err(TargetDataLayoutErrors::InconsistentTargetPointerWidth {
pointer_size: dl.pointer_size.bits(),
target: self.pointer_width,
});
}
dl.c_enum_min_size = match Integer::from_size(Size::from_bits(self.c_enum_min_bits)) {
Ok(bits) => bits,
Err(err) => return Err(TargetDataLayoutErrors::InvalidBitsSize { err }),
};
Ok(dl)
}
}
pub trait HasTargetSpec { pub trait HasTargetSpec {
fn target_spec(&self) -> &Target; fn target_spec(&self) -> &Target;
} }

View file

@ -4,8 +4,6 @@ version = "0.0.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
rand = "0.8.4"
rand_xoshiro = "0.6.0"
tracing = "0.1" tracing = "0.1"
rustc_middle = { path = "../rustc_middle" } rustc_middle = { path = "../rustc_middle" }
rustc_data_structures = { path = "../rustc_data_structures" } rustc_data_structures = { path = "../rustc_data_structures" }

View file

@ -755,7 +755,7 @@ fn generator_layout<'tcx>(
size = size.align_to(align.abi); size = size.align_to(align.abi);
let abi = if prefix.abi.is_uninhabited() || variants.iter().all(|v| v.abi().is_uninhabited()) { let abi = if prefix.abi.is_uninhabited() || variants.iter().all(|v| v.abi.is_uninhabited()) {
Abi::Uninhabited Abi::Uninhabited
} else { } else {
Abi::Aggregate { sized: true } Abi::Aggregate { sized: true }

View file

@ -249,27 +249,27 @@ pub(super) fn sanity_check_layout<'tcx>(
if let Variants::Multiple { variants, .. } = &layout.variants { if let Variants::Multiple { variants, .. } = &layout.variants {
for variant in variants.iter() { for variant in variants.iter() {
// No nested "multiple". // No nested "multiple".
assert!(matches!(variant.variants(), Variants::Single { .. })); assert!(matches!(variant.variants, Variants::Single { .. }));
// Variants should have the same or a smaller size as the full thing, // Variants should have the same or a smaller size as the full thing,
// and same for alignment. // and same for alignment.
if variant.size() > layout.size { if variant.size > layout.size {
bug!( bug!(
"Type with size {} bytes has variant with size {} bytes: {layout:#?}", "Type with size {} bytes has variant with size {} bytes: {layout:#?}",
layout.size.bytes(), layout.size.bytes(),
variant.size().bytes(), variant.size.bytes(),
) )
} }
if variant.align().abi > layout.align.abi { if variant.align.abi > layout.align.abi {
bug!( bug!(
"Type with alignment {} bytes has variant with alignment {} bytes: {layout:#?}", "Type with alignment {} bytes has variant with alignment {} bytes: {layout:#?}",
layout.align.abi.bytes(), layout.align.abi.bytes(),
variant.align().abi.bytes(), variant.align.abi.bytes(),
) )
} }
// Skip empty variants. // Skip empty variants.
if variant.size() == Size::ZERO if variant.size == Size::ZERO
|| variant.fields().count() == 0 || variant.fields.count() == 0
|| variant.abi().is_uninhabited() || variant.abi.is_uninhabited()
{ {
// These are never actually accessed anyway, so we can skip the coherence check // These are never actually accessed anyway, so we can skip the coherence check
// for them. They also fail that check, since they have // for them. They also fail that check, since they have
@ -282,7 +282,7 @@ pub(super) fn sanity_check_layout<'tcx>(
let scalar_coherent = |s1: Scalar, s2: Scalar| { let scalar_coherent = |s1: Scalar, s2: Scalar| {
s1.size(cx) == s2.size(cx) && s1.align(cx) == s2.align(cx) s1.size(cx) == s2.size(cx) && s1.align(cx) == s2.align(cx)
}; };
let abi_coherent = match (layout.abi, variant.abi()) { let abi_coherent = match (layout.abi, variant.abi) {
(Abi::Scalar(s1), Abi::Scalar(s2)) => scalar_coherent(s1, s2), (Abi::Scalar(s1), Abi::Scalar(s2)) => scalar_coherent(s1, s2),
(Abi::ScalarPair(a1, b1), Abi::ScalarPair(a2, b2)) => { (Abi::ScalarPair(a1, b1), Abi::ScalarPair(a2, b2)) => {
scalar_coherent(a1, a2) && scalar_coherent(b1, b2) scalar_coherent(a1, a2) && scalar_coherent(b1, b2)

View file

@ -1893,10 +1893,10 @@ 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: &LayoutS<VariantIdx>, 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 {
let bytes = layout.size().bytes() - tag_size; let bytes = layout.size.bytes() - tag_size;
write!(w, "{size} byte{pl}", size = bytes, pl = if bytes == 1 { "" } else { "s" },); write!(w, "{size} byte{pl}", size = bytes, pl = if bytes == 1 { "" } else { "s" },);
} }
} }