Skip to content

Commit

Permalink
Auto merge of #45225 - eddyb:trans-abi, r=<try>
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bors committed Oct 14, 2017
2 parents 7778906 + de42424 commit 3bd11e7
Show file tree
Hide file tree
Showing 73 changed files with 4,722 additions and 5,490 deletions.
18 changes: 14 additions & 4 deletions src/liballoc/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ impl<T> Place<T> for IntermediateBox<T> {
unsafe fn finalize<T>(b: IntermediateBox<T>) -> Box<T> {
let p = b.ptr as *mut T;
mem::forget(b);
mem::transmute(p)
Box::from_raw(p)
}

fn make_place<T>() -> IntermediateBox<T> {
Expand Down Expand Up @@ -300,7 +300,10 @@ impl<T: ?Sized> Box<T> {
issue = "27730")]
#[inline]
pub unsafe fn from_unique(u: Unique<T>) -> Self {
mem::transmute(u)
#[cfg(stage0)]
return mem::transmute(u);
#[cfg(not(stage0))]
return Box(u);
}

/// Consumes the `Box`, returning the wrapped raw pointer.
Expand Down Expand Up @@ -362,7 +365,14 @@ impl<T: ?Sized> Box<T> {
issue = "27730")]
#[inline]
pub fn into_unique(b: Box<T>) -> Unique<T> {
unsafe { mem::transmute(b) }
#[cfg(stage0)]
return unsafe { mem::transmute(b) };
#[cfg(not(stage0))]
return {
let unique = b.0;
mem::forget(b);
unique
};
}
}

Expand Down Expand Up @@ -627,7 +637,7 @@ impl Box<Any + Send> {
pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any + Send>> {
<Box<Any>>::downcast(self).map_err(|s| unsafe {
// reapply the Send marker
mem::transmute::<Box<Any>, Box<Any + Send>>(s)
Box::from_raw(Box::into_raw(s) as *mut (Any + Send))
})
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@
#![feature(conservative_impl_trait)]
#![feature(const_fn)]
#![feature(core_intrinsics)]
#![feature(i128)]
#![feature(i128_type)]
#![feature(inclusive_range)]
#![feature(inclusive_range_syntax)]
#![cfg_attr(windows, feature(libc))]
#![feature(never_type)]
#![feature(nonzero)]
Expand Down
8 changes: 4 additions & 4 deletions src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ use ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predic
use ty::RegionKind;
use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
use ty::TypeVariants::*;
use ty::layout::{Layout, TargetDataLayout};
use ty::layout::{CachedLayout, TargetDataLayout};
use ty::inhabitedness::DefIdForest;
use ty::maps;
use ty::steal::Steal;
Expand Down Expand Up @@ -80,7 +80,7 @@ use hir;
/// Internal storage
pub struct GlobalArenas<'tcx> {
// internings
layout: TypedArena<Layout>,
layout: TypedArena<CachedLayout>,

// references
generics: TypedArena<ty::Generics>,
Expand Down Expand Up @@ -931,7 +931,7 @@ pub struct GlobalCtxt<'tcx> {

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

layout_interner: RefCell<FxHashSet<&'tcx Layout>>,
layout_interner: RefCell<FxHashSet<&'tcx CachedLayout>>,

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

pub fn intern_layout(self, layout: Layout) -> &'gcx Layout {
pub fn intern_layout(self, layout: CachedLayout) -> &'gcx CachedLayout {
if let Some(layout) = self.layout_interner.borrow().get(&layout) {
return layout;
}
Expand Down
Loading

0 comments on commit 3bd11e7

Please sign in to comment.