Skip to content

Commit fa5efe4

Browse files
committed
Auto merge of #45225 - eddyb:trans-abi, r=<try>
Refactor type memory layouts and ABIs, to be more general and easier to optimize. To combat combinatorial explosion, type layouts are now described through 3 orthogonal properties: * `Variants` describes the plurality of sum types (where applicable) * `Single` is for one inhabited/active variant, including all C `struct`s and `union`s * `Tagged` has its variants discriminated by an integer tag, including C `enum`s * `NicheFilling` uses otherwise-invalid values ("niches") for all but one of its inhabited variants * `FieldPlacement` describes the number and memory offsets of fields (if any) * `Union` has all its fields at offset `0` * `Array` has offsets that are a multiple of its `stride`; guarantees all fields have one type * `Arbitrary` records all the field offsets, which can be out-of-order * `Abi` describes how values of the type should be passed around, including for FFI * `Uninhabited` corresponds to no values, associated with unreachable control-flow * `Scalar` is ABI-identical to its only integer/floating-point/pointer "scalar component" * `ScalarPair` has two "scalar components", but only applies to the Rust ABI * `Vector` is for SIMD vectors, typically `#[repr(simd)]` `struct`s in Rust * `Aggregate` has arbitrary contents, including all non-transparent C `struct`s and `union`s Size optimizations implemented so far: * ignoring uninhabited variants (i.e. containing uninhabited fields), e.g.: * `Option<!>` is 0 bytes * `Result<T, !>` has the same size as `T` * using arbitrary niches, not just `0`, to represent a data-less variant, e.g.: * `Option<bool>`, `Option<Option<bool>>`, `Option<Ordering>` are all 1 byte * `Option<char>` is 4 bytes * using a range of niches to represent *multiple* data-less variants, e.g.: * `enum E { A(bool), B, C, D }` is 1 byte Code generation now takes advantage of `Scalar` and `ScalarPair` to, in more cases, pass around scalar components as immediates instead of indirectly, through pointers into temporary memory, while avoiding LLVM's "first-class aggregates", and there's more untapped potential here. Closes #44426, fixes #5977, fixes #14540, fixes #43278.
2 parents 7d475a2 + cac77ac commit fa5efe4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+4808
-5505
lines changed

src/liballoc/boxed.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ impl<T> Place<T> for IntermediateBox<T> {
151151
unsafe fn finalize<T>(b: IntermediateBox<T>) -> Box<T> {
152152
let p = b.ptr as *mut T;
153153
mem::forget(b);
154-
mem::transmute(p)
154+
Box::from_raw(p)
155155
}
156156

157157
fn make_place<T>() -> IntermediateBox<T> {
@@ -300,7 +300,10 @@ impl<T: ?Sized> Box<T> {
300300
issue = "27730")]
301301
#[inline]
302302
pub unsafe fn from_unique(u: Unique<T>) -> Self {
303-
mem::transmute(u)
303+
#[cfg(stage0)]
304+
return mem::transmute(u);
305+
#[cfg(not(stage0))]
306+
return Box(u);
304307
}
305308

306309
/// Consumes the `Box`, returning the wrapped raw pointer.
@@ -362,7 +365,14 @@ impl<T: ?Sized> Box<T> {
362365
issue = "27730")]
363366
#[inline]
364367
pub fn into_unique(b: Box<T>) -> Unique<T> {
365-
unsafe { mem::transmute(b) }
368+
#[cfg(stage0)]
369+
return unsafe { mem::transmute(b) };
370+
#[cfg(not(stage0))]
371+
return {
372+
let unique = b.0;
373+
mem::forget(b);
374+
unique
375+
};
366376
}
367377
}
368378

@@ -627,7 +637,7 @@ impl Box<Any + Send> {
627637
pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any + Send>> {
628638
<Box<Any>>::downcast(self).map_err(|s| unsafe {
629639
// reapply the Send marker
630-
mem::transmute::<Box<Any>, Box<Any + Send>>(s)
640+
Box::from_raw(Box::into_raw(s) as *mut (Any + Send))
631641
})
632642
}
633643
}

src/librustc/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,10 @@
4545
#![feature(conservative_impl_trait)]
4646
#![feature(const_fn)]
4747
#![feature(core_intrinsics)]
48+
#![feature(i128)]
4849
#![feature(i128_type)]
50+
#![feature(inclusive_range)]
51+
#![feature(inclusive_range_syntax)]
4952
#![cfg_attr(windows, feature(libc))]
5053
#![feature(never_type)]
5154
#![feature(nonzero)]

src/librustc/lint/context.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ use middle::privacy::AccessLevels;
3434
use rustc_serialize::{Decoder, Decodable, Encoder, Encodable};
3535
use session::{config, early_error, Session};
3636
use traits::Reveal;
37-
use ty::{self, TyCtxt};
37+
use ty::{self, TyCtxt, Ty};
38+
use ty::layout::{LayoutError, LayoutOf, TyLayout};
3839
use util::nodemap::FxHashMap;
3940

4041
use std::default::Default as StdDefault;
@@ -623,6 +624,14 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
623624
}
624625
}
625626

627+
impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for &'a LateContext<'a, 'tcx> {
628+
type TyLayout = Result<TyLayout<'tcx>, LayoutError<'tcx>>;
629+
630+
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
631+
(self.tcx, self.param_env.reveal_all()).layout_of(ty)
632+
}
633+
}
634+
626635
impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
627636
/// Because lints are scoped lexically, we want to walk nested
628637
/// items in the context of the outer item, so enable

src/librustc/ty/context.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predic
4242
use ty::RegionKind;
4343
use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
4444
use ty::TypeVariants::*;
45-
use ty::layout::{Layout, TargetDataLayout};
45+
use ty::layout::{LayoutDetails, TargetDataLayout};
4646
use ty::maps;
4747
use ty::steal::Steal;
4848
use ty::BindingMode;
@@ -79,7 +79,7 @@ use hir;
7979
/// Internal storage
8080
pub struct GlobalArenas<'tcx> {
8181
// internings
82-
layout: TypedArena<Layout>,
82+
layout: TypedArena<LayoutDetails>,
8383

8484
// references
8585
generics: TypedArena<ty::Generics>,
@@ -916,7 +916,7 @@ pub struct GlobalCtxt<'tcx> {
916916

917917
stability_interner: RefCell<FxHashSet<&'tcx attr::Stability>>,
918918

919-
layout_interner: RefCell<FxHashSet<&'tcx Layout>>,
919+
layout_interner: RefCell<FxHashSet<&'tcx LayoutDetails>>,
920920

921921
/// A vector of every trait accessible in the whole crate
922922
/// (i.e. including those from subcrates). This is used only for
@@ -1014,7 +1014,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
10141014
interned
10151015
}
10161016

1017-
pub fn intern_layout(self, layout: Layout) -> &'gcx Layout {
1017+
pub fn intern_layout(self, layout: LayoutDetails) -> &'gcx LayoutDetails {
10181018
if let Some(layout) = self.layout_interner.borrow().get(&layout) {
10191019
return layout;
10201020
}

0 commit comments

Comments
 (0)