about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJubilee Young <workingjubilee@gmail.com>2024-10-09 12:20:28 -0700
committerJubilee Young <workingjubilee@gmail.com>2024-10-11 17:41:52 -0700
commit10721909f29024ba56a9ce667da8652a99a04784 (patch)
tree75236319d03880c1fbc2415227fb73e6b06ced10
parent255bdd2f24de119d85073e0c48acdebca25af551 (diff)
downloadrust-10721909f29024ba56a9ce667da8652a99a04784.tar.gz
rust-10721909f29024ba56a9ce667da8652a99a04784.zip
compiler: Wire `{TyAnd,}Layout` into `rustc_abi`
This finally unites TyAndLayout, Layout, and LayoutS into the same crate,
as one might imagine they would be placed. No functional changes.
-rw-r--r--compiler/rustc_abi/src/callconv.rs254
-rw-r--r--compiler/rustc_abi/src/layout.rs4
-rw-r--r--compiler/rustc_abi/src/layout/ty.rs4
-rw-r--r--compiler/rustc_abi/src/lib.rs8
-rw-r--r--compiler/rustc_middle/src/ty/context.rs2
-rw-r--r--compiler/rustc_target/src/callconv/mod.rs249
-rw-r--r--compiler/rustc_target/src/lib.rs11
7 files changed, 279 insertions, 253 deletions
diff --git a/compiler/rustc_abi/src/callconv.rs b/compiler/rustc_abi/src/callconv.rs
new file mode 100644
index 00000000000..2ecac8a9df1
--- /dev/null
+++ b/compiler/rustc_abi/src/callconv.rs
@@ -0,0 +1,254 @@
+mod abi {
+    pub(crate) use crate::Primitive::*;
+    pub(crate) use crate::Variants;
+}
+
+use rustc_macros::HashStable_Generic;
+
+use crate::{Abi, Align, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
+pub enum RegKind {
+    Integer,
+    Float,
+    Vector,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
+pub struct Reg {
+    pub kind: RegKind,
+    pub size: Size,
+}
+
+macro_rules! reg_ctor {
+    ($name:ident, $kind:ident, $bits:expr) => {
+        pub fn $name() -> Reg {
+            Reg { kind: RegKind::$kind, size: Size::from_bits($bits) }
+        }
+    };
+}
+
+impl Reg {
+    reg_ctor!(i8, Integer, 8);
+    reg_ctor!(i16, Integer, 16);
+    reg_ctor!(i32, Integer, 32);
+    reg_ctor!(i64, Integer, 64);
+    reg_ctor!(i128, Integer, 128);
+
+    reg_ctor!(f32, Float, 32);
+    reg_ctor!(f64, Float, 64);
+}
+
+impl Reg {
+    pub fn align<C: HasDataLayout>(&self, cx: &C) -> Align {
+        let dl = cx.data_layout();
+        match self.kind {
+            RegKind::Integer => match self.size.bits() {
+                1 => dl.i1_align.abi,
+                2..=8 => dl.i8_align.abi,
+                9..=16 => dl.i16_align.abi,
+                17..=32 => dl.i32_align.abi,
+                33..=64 => dl.i64_align.abi,
+                65..=128 => dl.i128_align.abi,
+                _ => panic!("unsupported integer: {self:?}"),
+            },
+            RegKind::Float => match self.size.bits() {
+                16 => dl.f16_align.abi,
+                32 => dl.f32_align.abi,
+                64 => dl.f64_align.abi,
+                128 => dl.f128_align.abi,
+                _ => panic!("unsupported float: {self:?}"),
+            },
+            RegKind::Vector => dl.vector_align(self.size).abi,
+        }
+    }
+}
+
+/// Return value from the `homogeneous_aggregate` test function.
+#[derive(Copy, Clone, Debug)]
+pub enum HomogeneousAggregate {
+    /// Yes, all the "leaf fields" of this struct are passed in the
+    /// same way (specified in the `Reg` value).
+    Homogeneous(Reg),
+
+    /// There are no leaf fields at all.
+    NoData,
+}
+
+/// Error from the `homogeneous_aggregate` test function, indicating
+/// there are distinct leaf fields passed in different ways,
+/// or this is uninhabited.
+#[derive(Copy, Clone, Debug)]
+pub struct Heterogeneous;
+
+impl HomogeneousAggregate {
+    /// If this is a homogeneous aggregate, returns the homogeneous
+    /// unit, else `None`.
+    pub fn unit(self) -> Option<Reg> {
+        match self {
+            HomogeneousAggregate::Homogeneous(reg) => Some(reg),
+            HomogeneousAggregate::NoData => None,
+        }
+    }
+
+    /// Try to combine two `HomogeneousAggregate`s, e.g. from two fields in
+    /// the same `struct`. Only succeeds if only one of them has any data,
+    /// or both units are identical.
+    fn merge(self, other: HomogeneousAggregate) -> Result<HomogeneousAggregate, Heterogeneous> {
+        match (self, other) {
+            (x, HomogeneousAggregate::NoData) | (HomogeneousAggregate::NoData, x) => Ok(x),
+
+            (HomogeneousAggregate::Homogeneous(a), HomogeneousAggregate::Homogeneous(b)) => {
+                if a != b {
+                    return Err(Heterogeneous);
+                }
+                Ok(self)
+            }
+        }
+    }
+}
+
+impl<'a, Ty> TyAndLayout<'a, Ty> {
+    /// Returns `true` if this is an aggregate type (including a ScalarPair!)
+    pub fn is_aggregate(&self) -> bool {
+        match self.abi {
+            Abi::Uninhabited | Abi::Scalar(_) | Abi::Vector { .. } => false,
+            Abi::ScalarPair(..) | Abi::Aggregate { .. } => true,
+        }
+    }
+
+    /// Returns `Homogeneous` if this layout is an aggregate containing fields of
+    /// only a single type (e.g., `(u32, u32)`). Such aggregates are often
+    /// special-cased in ABIs.
+    ///
+    /// Note: We generally ignore 1-ZST fields when computing this value (see #56877).
+    ///
+    /// This is public so that it can be used in unit tests, but
+    /// should generally only be relevant to the ABI details of
+    /// specific targets.
+    pub fn homogeneous_aggregate<C>(&self, cx: &C) -> Result<HomogeneousAggregate, Heterogeneous>
+    where
+        Ty: TyAbiInterface<'a, C> + Copy,
+    {
+        match self.abi {
+            Abi::Uninhabited => Err(Heterogeneous),
+
+            // The primitive for this algorithm.
+            Abi::Scalar(scalar) => {
+                let kind = match scalar.primitive() {
+                    abi::Int(..) | abi::Pointer(_) => RegKind::Integer,
+                    abi::Float(_) => RegKind::Float,
+                };
+                Ok(HomogeneousAggregate::Homogeneous(Reg { kind, size: self.size }))
+            }
+
+            Abi::Vector { .. } => {
+                assert!(!self.is_zst());
+                Ok(HomogeneousAggregate::Homogeneous(Reg {
+                    kind: RegKind::Vector,
+                    size: self.size,
+                }))
+            }
+
+            Abi::ScalarPair(..) | Abi::Aggregate { sized: true } => {
+                // Helper for computing `homogeneous_aggregate`, allowing a custom
+                // starting offset (used below for handling variants).
+                let from_fields_at =
+                    |layout: Self,
+                     start: Size|
+                     -> Result<(HomogeneousAggregate, Size), Heterogeneous> {
+                        let is_union = match layout.fields {
+                            FieldsShape::Primitive => {
+                                unreachable!("aggregates can't have `FieldsShape::Primitive`")
+                            }
+                            FieldsShape::Array { count, .. } => {
+                                assert_eq!(start, Size::ZERO);
+
+                                let result = if count > 0 {
+                                    layout.field(cx, 0).homogeneous_aggregate(cx)?
+                                } else {
+                                    HomogeneousAggregate::NoData
+                                };
+                                return Ok((result, layout.size));
+                            }
+                            FieldsShape::Union(_) => true,
+                            FieldsShape::Arbitrary { .. } => false,
+                        };
+
+                        let mut result = HomogeneousAggregate::NoData;
+                        let mut total = start;
+
+                        for i in 0..layout.fields.count() {
+                            let field = layout.field(cx, i);
+                            if field.is_1zst() {
+                                // No data here and no impact on layout, can be ignored.
+                                // (We might be able to also ignore all aligned ZST but that's less clear.)
+                                continue;
+                            }
+
+                            if !is_union && total != layout.fields.offset(i) {
+                                // This field isn't just after the previous one we considered, abort.
+                                return Err(Heterogeneous);
+                            }
+
+                            result = result.merge(field.homogeneous_aggregate(cx)?)?;
+
+                            // Keep track of the offset (without padding).
+                            let size = field.size;
+                            if is_union {
+                                total = total.max(size);
+                            } else {
+                                total += size;
+                            }
+                        }
+
+                        Ok((result, total))
+                    };
+
+                let (mut result, mut total) = from_fields_at(*self, Size::ZERO)?;
+
+                match &self.variants {
+                    abi::Variants::Single { .. } => {}
+                    abi::Variants::Multiple { variants, .. } => {
+                        // Treat enum variants like union members.
+                        // HACK(eddyb) pretend the `enum` field (discriminant)
+                        // is at the start of every variant (otherwise the gap
+                        // at the start of all variants would disqualify them).
+                        //
+                        // NB: for all tagged `enum`s (which include all non-C-like
+                        // `enum`s with defined FFI representation), this will
+                        // match the homogeneous computation on the equivalent
+                        // `struct { tag; union { variant1; ... } }` and/or
+                        // `union { struct { tag; variant1; } ... }`
+                        // (the offsets of variant fields should be identical
+                        // between the two for either to be a homogeneous aggregate).
+                        let variant_start = total;
+                        for variant_idx in variants.indices() {
+                            let (variant_result, variant_total) =
+                                from_fields_at(self.for_variant(cx, variant_idx), variant_start)?;
+
+                            result = result.merge(variant_result)?;
+                            total = total.max(variant_total);
+                        }
+                    }
+                }
+
+                // There needs to be no padding.
+                if total != self.size {
+                    Err(Heterogeneous)
+                } else {
+                    match result {
+                        HomogeneousAggregate::Homogeneous(_) => {
+                            assert_ne!(total, Size::ZERO);
+                        }
+                        HomogeneousAggregate::NoData => {
+                            assert_eq!(total, Size::ZERO);
+                        }
+                    }
+                    Ok(result)
+                }
+            }
+            Abi::Aggregate { sized: false } => Err(Heterogeneous),
+        }
+    }
+}
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index 620a051eeb7..6e1299944a0 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -11,6 +11,10 @@ use crate::{
     Variants, WrappingRange,
 };
 
+mod ty;
+
+pub use ty::{FIRST_VARIANT, FieldIdx, Layout, TyAbiInterface, TyAndLayout, VariantIdx};
+
 // A variant is absent if it's uninhabited and only has ZST fields.
 // Present uninhabited variants only require space for their fields,
 // but *not* an encoding of the discriminant (e.g., a tag value).
diff --git a/compiler/rustc_abi/src/layout/ty.rs b/compiler/rustc_abi/src/layout/ty.rs
index 9f26c98df86..c6812c4d4c0 100644
--- a/compiler/rustc_abi/src/layout/ty.rs
+++ b/compiler/rustc_abi/src/layout/ty.rs
@@ -6,10 +6,8 @@ use Primitive::*;
 use rustc_data_structures::intern::Interned;
 use rustc_macros::HashStable_Generic;
 
-pub mod call;
-
 // Explicitly import `Float` to avoid ambiguity with `Primitive::Float`.
-pub use rustc_abi::{Float, *};
+use crate::{Float, *};
 
 rustc_index::newtype_index! {
     /// The *source-order* index of a field in a variant.
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index fa7c98a7fa0..84d756b6d51 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -1,6 +1,7 @@
 // tidy-alphabetical-start
 #![cfg_attr(feature = "nightly", allow(internal_features))]
 #![cfg_attr(feature = "nightly", doc(rust_logo))]
+#![cfg_attr(feature = "nightly", feature(rustc_attrs))]
 #![cfg_attr(feature = "nightly", feature(rustdoc_internals))]
 #![cfg_attr(feature = "nightly", feature(step_trait))]
 #![warn(unreachable_pub)]
@@ -22,11 +23,16 @@ use rustc_macros::HashStable_Generic;
 #[cfg(feature = "nightly")]
 use rustc_macros::{Decodable_Generic, Encodable_Generic};
 
+mod callconv;
 mod layout;
 #[cfg(test)]
 mod tests;
 
-pub use layout::{LayoutCalculator, LayoutCalculatorError};
+pub use callconv::{Heterogeneous, HomogeneousAggregate, Reg, RegKind};
+pub use layout::{
+    FIRST_VARIANT, FieldIdx, Layout, LayoutCalculator, LayoutCalculatorError, TyAbiInterface,
+    TyAndLayout, VariantIdx,
+};
 
 /// Requirements for a `StableHashingContext` to be used in this crate.
 /// This is a hack to allow using the `HashStable_Generic` derive macro
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 50e7be82a79..1bdcae4dfb4 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -12,6 +12,7 @@ use std::marker::PhantomData;
 use std::ops::{Bound, Deref};
 use std::{fmt, iter, mem};
 
+use rustc_abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx};
 use rustc_ast::{self as ast, attr};
 use rustc_data_structures::defer;
 use rustc_data_structures::fingerprint::Fingerprint;
@@ -48,7 +49,6 @@ use rustc_session::{Limit, MetadataKind, Session};
 use rustc_span::def_id::{CRATE_DEF_ID, DefPathHash, StableCrateId};
 use rustc_span::symbol::{Ident, Symbol, kw, sym};
 use rustc_span::{DUMMY_SP, Span};
-use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx};
 use rustc_target::spec::abi;
 use rustc_type_ir::TyKind::*;
 use rustc_type_ir::fold::TypeFoldable;
diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs
index 352861c5ccb..832246495bc 100644
--- a/compiler/rustc_target/src/callconv/mod.rs
+++ b/compiler/rustc_target/src/callconv/mod.rs
@@ -1,10 +1,11 @@
 use std::fmt;
 use std::str::FromStr;
 
+pub use rustc_abi::{Reg, RegKind};
 use rustc_macros::HashStable_Generic;
 use rustc_span::Symbol;
 
-use crate::abi::{self, Abi, Align, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
+use crate::abi::{self, Abi, Align, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
 use crate::spec::{self, HasTargetSpec, HasWasmCAbiOpt, WasmCAbi};
 
 mod aarch64;
@@ -192,63 +193,6 @@ impl ArgAttributes {
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
-pub enum RegKind {
-    Integer,
-    Float,
-    Vector,
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
-pub struct Reg {
-    pub kind: RegKind,
-    pub size: Size,
-}
-
-macro_rules! reg_ctor {
-    ($name:ident, $kind:ident, $bits:expr) => {
-        pub fn $name() -> Reg {
-            Reg { kind: RegKind::$kind, size: Size::from_bits($bits) }
-        }
-    };
-}
-
-impl Reg {
-    reg_ctor!(i8, Integer, 8);
-    reg_ctor!(i16, Integer, 16);
-    reg_ctor!(i32, Integer, 32);
-    reg_ctor!(i64, Integer, 64);
-    reg_ctor!(i128, Integer, 128);
-
-    reg_ctor!(f32, Float, 32);
-    reg_ctor!(f64, Float, 64);
-}
-
-impl Reg {
-    pub fn align<C: HasDataLayout>(&self, cx: &C) -> Align {
-        let dl = cx.data_layout();
-        match self.kind {
-            RegKind::Integer => match self.size.bits() {
-                1 => dl.i1_align.abi,
-                2..=8 => dl.i8_align.abi,
-                9..=16 => dl.i16_align.abi,
-                17..=32 => dl.i32_align.abi,
-                33..=64 => dl.i64_align.abi,
-                65..=128 => dl.i128_align.abi,
-                _ => panic!("unsupported integer: {self:?}"),
-            },
-            RegKind::Float => match self.size.bits() {
-                16 => dl.f16_align.abi,
-                32 => dl.f32_align.abi,
-                64 => dl.f64_align.abi,
-                128 => dl.f128_align.abi,
-                _ => panic!("unsupported float: {self:?}"),
-            },
-            RegKind::Vector => dl.vector_align(self.size).abi,
-        }
-    }
-}
-
 /// An argument passed entirely registers with the
 /// same kind (e.g., HFA / HVA on PPC64 and AArch64).
 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable_Generic)]
@@ -380,195 +324,6 @@ impl CastTarget {
     }
 }
 
-/// Return value from the `homogeneous_aggregate` test function.
-#[derive(Copy, Clone, Debug)]
-pub enum HomogeneousAggregate {
-    /// Yes, all the "leaf fields" of this struct are passed in the
-    /// same way (specified in the `Reg` value).
-    Homogeneous(Reg),
-
-    /// There are no leaf fields at all.
-    NoData,
-}
-
-/// Error from the `homogeneous_aggregate` test function, indicating
-/// there are distinct leaf fields passed in different ways,
-/// or this is uninhabited.
-#[derive(Copy, Clone, Debug)]
-pub struct Heterogeneous;
-
-impl HomogeneousAggregate {
-    /// If this is a homogeneous aggregate, returns the homogeneous
-    /// unit, else `None`.
-    pub fn unit(self) -> Option<Reg> {
-        match self {
-            HomogeneousAggregate::Homogeneous(reg) => Some(reg),
-            HomogeneousAggregate::NoData => None,
-        }
-    }
-
-    /// Try to combine two `HomogeneousAggregate`s, e.g. from two fields in
-    /// the same `struct`. Only succeeds if only one of them has any data,
-    /// or both units are identical.
-    fn merge(self, other: HomogeneousAggregate) -> Result<HomogeneousAggregate, Heterogeneous> {
-        match (self, other) {
-            (x, HomogeneousAggregate::NoData) | (HomogeneousAggregate::NoData, x) => Ok(x),
-
-            (HomogeneousAggregate::Homogeneous(a), HomogeneousAggregate::Homogeneous(b)) => {
-                if a != b {
-                    return Err(Heterogeneous);
-                }
-                Ok(self)
-            }
-        }
-    }
-}
-
-impl<'a, Ty> TyAndLayout<'a, Ty> {
-    /// Returns `true` if this is an aggregate type (including a ScalarPair!)
-    fn is_aggregate(&self) -> bool {
-        match self.abi {
-            Abi::Uninhabited | Abi::Scalar(_) | Abi::Vector { .. } => false,
-            Abi::ScalarPair(..) | Abi::Aggregate { .. } => true,
-        }
-    }
-
-    /// Returns `Homogeneous` if this layout is an aggregate containing fields of
-    /// only a single type (e.g., `(u32, u32)`). Such aggregates are often
-    /// special-cased in ABIs.
-    ///
-    /// Note: We generally ignore 1-ZST fields when computing this value (see #56877).
-    ///
-    /// This is public so that it can be used in unit tests, but
-    /// should generally only be relevant to the ABI details of
-    /// specific targets.
-    pub fn homogeneous_aggregate<C>(&self, cx: &C) -> Result<HomogeneousAggregate, Heterogeneous>
-    where
-        Ty: TyAbiInterface<'a, C> + Copy,
-    {
-        match self.abi {
-            Abi::Uninhabited => Err(Heterogeneous),
-
-            // The primitive for this algorithm.
-            Abi::Scalar(scalar) => {
-                let kind = match scalar.primitive() {
-                    abi::Int(..) | abi::Pointer(_) => RegKind::Integer,
-                    abi::Float(_) => RegKind::Float,
-                };
-                Ok(HomogeneousAggregate::Homogeneous(Reg { kind, size: self.size }))
-            }
-
-            Abi::Vector { .. } => {
-                assert!(!self.is_zst());
-                Ok(HomogeneousAggregate::Homogeneous(Reg {
-                    kind: RegKind::Vector,
-                    size: self.size,
-                }))
-            }
-
-            Abi::ScalarPair(..) | Abi::Aggregate { sized: true } => {
-                // Helper for computing `homogeneous_aggregate`, allowing a custom
-                // starting offset (used below for handling variants).
-                let from_fields_at =
-                    |layout: Self,
-                     start: Size|
-                     -> Result<(HomogeneousAggregate, Size), Heterogeneous> {
-                        let is_union = match layout.fields {
-                            FieldsShape::Primitive => {
-                                unreachable!("aggregates can't have `FieldsShape::Primitive`")
-                            }
-                            FieldsShape::Array { count, .. } => {
-                                assert_eq!(start, Size::ZERO);
-
-                                let result = if count > 0 {
-                                    layout.field(cx, 0).homogeneous_aggregate(cx)?
-                                } else {
-                                    HomogeneousAggregate::NoData
-                                };
-                                return Ok((result, layout.size));
-                            }
-                            FieldsShape::Union(_) => true,
-                            FieldsShape::Arbitrary { .. } => false,
-                        };
-
-                        let mut result = HomogeneousAggregate::NoData;
-                        let mut total = start;
-
-                        for i in 0..layout.fields.count() {
-                            let field = layout.field(cx, i);
-                            if field.is_1zst() {
-                                // No data here and no impact on layout, can be ignored.
-                                // (We might be able to also ignore all aligned ZST but that's less clear.)
-                                continue;
-                            }
-
-                            if !is_union && total != layout.fields.offset(i) {
-                                // This field isn't just after the previous one we considered, abort.
-                                return Err(Heterogeneous);
-                            }
-
-                            result = result.merge(field.homogeneous_aggregate(cx)?)?;
-
-                            // Keep track of the offset (without padding).
-                            let size = field.size;
-                            if is_union {
-                                total = total.max(size);
-                            } else {
-                                total += size;
-                            }
-                        }
-
-                        Ok((result, total))
-                    };
-
-                let (mut result, mut total) = from_fields_at(*self, Size::ZERO)?;
-
-                match &self.variants {
-                    abi::Variants::Single { .. } => {}
-                    abi::Variants::Multiple { variants, .. } => {
-                        // Treat enum variants like union members.
-                        // HACK(eddyb) pretend the `enum` field (discriminant)
-                        // is at the start of every variant (otherwise the gap
-                        // at the start of all variants would disqualify them).
-                        //
-                        // NB: for all tagged `enum`s (which include all non-C-like
-                        // `enum`s with defined FFI representation), this will
-                        // match the homogeneous computation on the equivalent
-                        // `struct { tag; union { variant1; ... } }` and/or
-                        // `union { struct { tag; variant1; } ... }`
-                        // (the offsets of variant fields should be identical
-                        // between the two for either to be a homogeneous aggregate).
-                        let variant_start = total;
-                        for variant_idx in variants.indices() {
-                            let (variant_result, variant_total) =
-                                from_fields_at(self.for_variant(cx, variant_idx), variant_start)?;
-
-                            result = result.merge(variant_result)?;
-                            total = total.max(variant_total);
-                        }
-                    }
-                }
-
-                // There needs to be no padding.
-                if total != self.size {
-                    Err(Heterogeneous)
-                } else {
-                    match result {
-                        HomogeneousAggregate::Homogeneous(_) => {
-                            assert_ne!(total, Size::ZERO);
-                        }
-                        HomogeneousAggregate::NoData => {
-                            assert_eq!(total, Size::ZERO);
-                        }
-                    }
-                    Ok(result)
-                }
-            }
-            Abi::Aggregate { sized: false } => Err(Heterogeneous),
-        }
-    }
-}
-
 /// Information about how to pass an argument to,
 /// or return a value from, a function, under some ABI.
 #[derive(Clone, PartialEq, Eq, Hash, HashStable_Generic)]
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index 2121c4110dd..50679ab8cc8 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -21,8 +21,8 @@
 
 use std::path::{Path, PathBuf};
 
-pub mod abi;
 pub mod asm;
+pub mod callconv;
 pub mod json;
 pub mod spec;
 pub mod target_features;
@@ -30,6 +30,15 @@ pub mod target_features;
 #[cfg(test)]
 mod tests;
 
+pub mod abi {
+    pub(crate) use Float::*;
+    pub(crate) use Primitive::*;
+    // Explicitly import `Float` to avoid ambiguity with `Primitive::Float`.
+    pub use rustc_abi::{Float, *};
+
+    pub use crate::callconv as call;
+}
+
 pub use rustc_abi::HashStableContext;
 
 /// The name of rustc's own place to organize libraries.