move things from rustc_target::abi to rustc_abi
This commit is contained in:
parent
27fb904d68
commit
390a637e29
21 changed files with 1700 additions and 1673 deletions
19
Cargo.lock
19
Cargo.lock
|
@ -3202,6 +3202,20 @@ dependencies = [
|
|||
"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]]
|
||||
name = "rustc_apfloat"
|
||||
version = "0.0.0"
|
||||
|
@ -4281,8 +4295,7 @@ name = "rustc_target"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"rand 0.8.5",
|
||||
"rand_xoshiro",
|
||||
"rustc_abi",
|
||||
"rustc_data_structures",
|
||||
"rustc_feature",
|
||||
"rustc_index",
|
||||
|
@ -4363,8 +4376,6 @@ dependencies = [
|
|||
name = "rustc_ty_utils"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rand 0.8.5",
|
||||
"rand_xoshiro",
|
||||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_hir",
|
||||
|
|
24
compiler/rustc_abi/Cargo.toml
Normal file
24
compiler/rustc_abi/Cargo.toml
Normal 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",
|
||||
]
|
|
@ -7,7 +7,9 @@ use std::{
|
|||
ops::{Bound, Deref},
|
||||
};
|
||||
|
||||
#[cfg(feature = "randomize")]
|
||||
use rand::{seq::SliceRandom, SeedableRng};
|
||||
#[cfg(feature = "randomize")]
|
||||
use rand_xoshiro::Xoshiro128StarStar;
|
||||
|
||||
use tracing::debug;
|
||||
|
@ -91,14 +93,16 @@ pub trait LayoutCalculator {
|
|||
// 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
|
||||
// we don't guarantee
|
||||
if repr.can_randomize_type_layout() {
|
||||
if repr.can_randomize_type_layout() && cfg!(feature = "randomize") {
|
||||
#[cfg(feature = "randomize")]
|
||||
{
|
||||
// `ReprOptions.layout_seed` is a deterministic seed that we can use to
|
||||
// randomize field ordering with
|
||||
let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed);
|
||||
|
||||
// Shuffle the ordering of the fields
|
||||
optimizing.shuffle(&mut rng);
|
||||
|
||||
}
|
||||
// Otherwise we just leave things alone and actually optimize the type's fields
|
||||
} else {
|
||||
match kind {
|
||||
|
@ -900,7 +904,7 @@ pub trait LayoutCalculator {
|
|||
let mut abi = Abi::Aggregate { sized: true };
|
||||
let index = V::new(0);
|
||||
for field in &variants[index] {
|
||||
assert!(!field.is_unsized());
|
||||
assert!(field.is_sized());
|
||||
align = align.max(field.align);
|
||||
|
||||
// If all non-ZST fields have the same ABI, forward this ABI
|
1399
compiler/rustc_abi/src/lib.rs
Normal file
1399
compiler/rustc_abi/src/lib.rs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -32,7 +32,6 @@ use rustc_middle::hir::nested_filter;
|
|||
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
||||
use rustc_middle::mir::mono::Linkage;
|
||||
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::{self, AdtKind, Const, DefIdTree, IsSuggestable, Ty, TyCtxt};
|
||||
use rustc_session::lint;
|
||||
|
@ -860,7 +859,7 @@ fn adt_def<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::AdtDef<'tcx> {
|
|||
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 {
|
||||
ItemKind::Enum(ref def, _) => {
|
||||
let mut distance_from_explicit = 0;
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
#![cfg_attr(feature = "nightly", feature(allow_internal_unstable))]
|
||||
#![cfg_attr(feature = "nightly", feature(extend_one))]
|
||||
#![cfg_attr(feature = "nightly", feature(min_specialization))]
|
||||
#![cfg_attr(feature = "nightly", feature(new_uninit))]
|
||||
#![cfg_attr(feature = "nightly", feature(step_trait))]
|
||||
#![cfg_attr(feature = "nightly", feature(stmt_expr_attributes))]
|
||||
#![cfg_attr(feature = "nightly", feature(test))]
|
||||
#![cfg_attr(
|
||||
feature = "nightly",
|
||||
feature(
|
||||
allow_internal_unstable,
|
||||
extend_one,
|
||||
min_specialization,
|
||||
new_uninit,
|
||||
step_trait,
|
||||
stmt_expr_attributes,
|
||||
test
|
||||
)
|
||||
)]
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
pub mod bit_set;
|
||||
|
|
|
@ -1378,7 +1378,7 @@ impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences {
|
|||
let (largest, slargest, largest_index) = iter::zip(enum_definition.variants, variants)
|
||||
.map(|(variant, variant_layout)| {
|
||||
// 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);
|
||||
bytes
|
||||
|
|
|
@ -1233,7 +1233,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
global_ctxt: untracked_resolutions,
|
||||
ast_lowering: untracked_resolver_for_lowering,
|
||||
} = 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);
|
||||
});
|
||||
let interners = CtxtInterners::new(arena);
|
||||
|
|
|
@ -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 {
|
||||
/// Returns the type of this field. The resulting type is not normalized. The `subst` is
|
||||
/// 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())
|
||||
}
|
||||
|
||||
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.
|
||||
pub fn opt_item_name(self, def_id: DefId) -> Option<Symbol> {
|
||||
if let Some(cnum) = def_id.as_crate_root() {
|
||||
|
|
|
@ -65,7 +65,7 @@ fn variant_discriminants<'tcx>(
|
|||
Variants::Multiple { variants, .. } => variants
|
||||
.iter_enumerated()
|
||||
.filter_map(|(idx, layout)| {
|
||||
(layout.abi() != Abi::Uninhabited)
|
||||
(layout.abi != Abi::Uninhabited)
|
||||
.then(|| ty.discriminant_for_variant(tcx, idx).unwrap().val)
|
||||
})
|
||||
.collect(),
|
||||
|
|
|
@ -11,7 +11,7 @@ use crate::{lint, HashStableContext};
|
|||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
|
||||
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::{Target, TargetTriple, TargetWarnings, TARGETS};
|
||||
|
||||
|
@ -900,7 +900,7 @@ fn default_configuration(sess: &Session) -> CrateConfig {
|
|||
let min_atomic_width = sess.target.min_atomic_width();
|
||||
let max_atomic_width = sess.target.max_atomic_width();
|
||||
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);
|
||||
});
|
||||
|
||||
|
|
|
@ -6,23 +6,11 @@ edition = "2021"
|
|||
[dependencies]
|
||||
bitflags = "1.2.1"
|
||||
tracing = "0.1"
|
||||
rand = "0.8.4"
|
||||
rand_xoshiro = "0.6.0"
|
||||
serde_json = "1.0.59"
|
||||
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
|
||||
rustc_feature = { path = "../rustc_feature", optional = true }
|
||||
rustc_index = { path = "../rustc_index", default-features = false }
|
||||
rustc_macros = { path = "../rustc_macros", optional = true }
|
||||
rustc_serialize = { path = "../rustc_serialize", optional = true }
|
||||
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",
|
||||
]
|
||||
rustc_abi = { path = "../rustc_abi" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_feature = { path = "../rustc_feature" }
|
||||
rustc_index = { path = "../rustc_index" }
|
||||
rustc_macros = { path = "../rustc_macros" }
|
||||
rustc_serialize = { path = "../rustc_serialize" }
|
||||
rustc_span = { path = "../rustc_span" }
|
||||
|
|
|
@ -262,7 +262,7 @@ impl CastTarget {
|
|||
let mut size = self.rest.total;
|
||||
for i in 0..self.prefix.iter().count() {
|
||||
match self.prefix[i] {
|
||||
Some(v) => size += Size { raw: v.size.bytes() },
|
||||
Some(v) => size += v.size,
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,8 +87,8 @@ where
|
|||
_ => {}
|
||||
}
|
||||
|
||||
if (offset.raw % 4) != 0 && scalar2.primitive().is_float() {
|
||||
offset.raw += 4 - (offset.raw % 4);
|
||||
if (offset.bytes() % 4) != 0 && scalar2.primitive().is_float() {
|
||||
offset += Size::from_bytes(4 - (offset.bytes() % 4));
|
||||
}
|
||||
data = arg_scalar(cx, &scalar2, offset, data);
|
||||
return data;
|
||||
|
@ -169,14 +169,14 @@ where
|
|||
has_float: false,
|
||||
arg_attribute: ArgAttribute::default(),
|
||||
},
|
||||
Size { raw: 0 },
|
||||
Size::ZERO,
|
||||
);
|
||||
|
||||
if data.has_float {
|
||||
// Structure { float, int, int } doesn't like to be handled like
|
||||
// { float, long int }. Other way around it doesn't mind.
|
||||
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[data.prefix_index] = Some(Reg::i32());
|
||||
|
@ -185,7 +185,7 @@ where
|
|||
}
|
||||
|
||||
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());
|
||||
rest_size = rest_size - Reg::i32().size;
|
||||
}
|
||||
|
@ -214,13 +214,13 @@ where
|
|||
C: HasDataLayout,
|
||||
{
|
||||
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() {
|
||||
if arg.is_ignore() {
|
||||
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
|
@ -8,13 +8,13 @@
|
|||
//! LLVM.
|
||||
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![cfg_attr(feature = "nightly", feature(assert_matches))]
|
||||
#![cfg_attr(feature = "nightly", feature(associated_type_bounds))]
|
||||
#![cfg_attr(feature = "nightly", feature(exhaustive_patterns))]
|
||||
#![cfg_attr(feature = "nightly", feature(min_specialization))]
|
||||
#![cfg_attr(feature = "nightly", feature(never_type))]
|
||||
#![cfg_attr(feature = "nightly", feature(rustc_attrs))]
|
||||
#![cfg_attr(feature = "nightly", feature(step_trait))]
|
||||
#![feature(assert_matches)]
|
||||
#![feature(associated_type_bounds)]
|
||||
#![feature(exhaustive_patterns)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(never_type)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(step_trait)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
|
@ -22,27 +22,20 @@ use std::iter::FromIterator;
|
|||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[macro_use]
|
||||
#[cfg(feature = "nightly")]
|
||||
extern crate rustc_macros;
|
||||
|
||||
#[macro_use]
|
||||
#[cfg(feature = "nightly")]
|
||||
extern crate tracing;
|
||||
|
||||
pub mod abi;
|
||||
#[cfg(feature = "nightly")]
|
||||
pub mod asm;
|
||||
pub mod json;
|
||||
#[cfg(feature = "nightly")]
|
||||
pub mod spec;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
/// Requirements for a `StableHashingContext` to be used in this crate.
|
||||
/// This is a hack to allow using the `HashStable_Generic` derive macro
|
||||
/// instead of implementing everything in `rustc_middle`.
|
||||
pub trait HashStableContext {}
|
||||
pub use rustc_abi::HashStableContext;
|
||||
|
||||
/// The name of rustc's own place to organize libraries.
|
||||
///
|
||||
|
|
|
@ -35,7 +35,10 @@
|
|||
//! to the list specified by the target, rather than replace.
|
||||
|
||||
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::spec::abi::{lookup as lookup_abi, Abi};
|
||||
use crate::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault};
|
||||
|
@ -1317,6 +1320,120 @@ pub struct Target {
|
|||
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 {
|
||||
fn target_spec(&self) -> &Target;
|
||||
}
|
||||
|
|
|
@ -4,8 +4,6 @@ version = "0.0.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
rand = "0.8.4"
|
||||
rand_xoshiro = "0.6.0"
|
||||
tracing = "0.1"
|
||||
rustc_middle = { path = "../rustc_middle" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
|
|
|
@ -755,7 +755,7 @@ fn generator_layout<'tcx>(
|
|||
|
||||
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
|
||||
} else {
|
||||
Abi::Aggregate { sized: true }
|
||||
|
|
|
@ -249,27 +249,27 @@ pub(super) fn sanity_check_layout<'tcx>(
|
|||
if let Variants::Multiple { variants, .. } = &layout.variants {
|
||||
for variant in variants.iter() {
|
||||
// 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,
|
||||
// and same for alignment.
|
||||
if variant.size() > layout.size {
|
||||
if variant.size > layout.size {
|
||||
bug!(
|
||||
"Type with size {} bytes has variant with size {} bytes: {layout:#?}",
|
||||
layout.size.bytes(),
|
||||
variant.size().bytes(),
|
||||
variant.size.bytes(),
|
||||
)
|
||||
}
|
||||
if variant.align().abi > layout.align.abi {
|
||||
if variant.align.abi > layout.align.abi {
|
||||
bug!(
|
||||
"Type with alignment {} bytes has variant with alignment {} bytes: {layout:#?}",
|
||||
layout.align.abi.bytes(),
|
||||
variant.align().abi.bytes(),
|
||||
variant.align.abi.bytes(),
|
||||
)
|
||||
}
|
||||
// Skip empty variants.
|
||||
if variant.size() == Size::ZERO
|
||||
|| variant.fields().count() == 0
|
||||
|| variant.abi().is_uninhabited()
|
||||
if variant.size == Size::ZERO
|
||||
|| variant.fields.count() == 0
|
||||
|| variant.abi.is_uninhabited()
|
||||
{
|
||||
// These are never actually accessed anyway, so we can skip the coherence check
|
||||
// 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| {
|
||||
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::ScalarPair(a1, b1), Abi::ScalarPair(a2, b2)) => {
|
||||
scalar_coherent(a1, a2) && scalar_coherent(b1, b2)
|
||||
|
|
|
@ -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 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)");
|
||||
} 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" },);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue