Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions compiler/rustc_abi/src/canon_abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub enum CanonAbi {

/// Swift calling convention, exposed via LLVM's `swiftcc`. Cross-platform
/// and not tied to a specific target architecture.
Swift,
Swift { tail: bool },

/// ABIs relevant to 32-bit Arm targets
Arm(ArmCall),
Expand Down Expand Up @@ -66,7 +66,7 @@ impl CanonAbi {
| CanonAbi::RustTail => true,
CanonAbi::C
| CanonAbi::Custom
| CanonAbi::Swift
| CanonAbi::Swift { .. }
| CanonAbi::Arm(_)
| CanonAbi::GpuKernel
| CanonAbi::Interrupt(_)
Expand All @@ -87,7 +87,7 @@ impl fmt::Display for CanonAbi {
CanonAbi::RustPreserveNone => ExternAbi::RustPreserveNone,
CanonAbi::RustTail => ExternAbi::RustTail,
CanonAbi::Custom => ExternAbi::Custom,
CanonAbi::Swift => ExternAbi::Swift,
CanonAbi::Swift { .. } => ExternAbi::Swift,
CanonAbi::Arm(arm_call) => match arm_call {
ArmCall::Aapcs => ExternAbi::Aapcs { unwind: false },
ArmCall::CCmseNonSecureCall => ExternAbi::CmseNonSecureCall,
Expand Down
9 changes: 8 additions & 1 deletion compiler/rustc_abi/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
largest_niche: element.largest_niche.filter(|_| count != 0),
uninhabited: element.uninhabited && count != 0,
align: element.align,
size_without_padding: size,
size,
max_repr_align: None,
unadjusted_abi_align: element.align.abi,
Expand Down Expand Up @@ -512,6 +513,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
largest_niche: None,
uninhabited: false,
align: AbiAlign::new(align),
size_without_padding: size,
size: size.align_to(align),
max_repr_align,
unadjusted_abi_align,
Expand Down Expand Up @@ -742,6 +744,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
backend_repr: abi,
largest_niche,
uninhabited,
size_without_padding: size,
size,
align: AbiAlign::new(align),
max_repr_align,
Expand Down Expand Up @@ -1051,6 +1054,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
uninhabited,
backend_repr: abi,
align: AbiAlign::new(align),
size_without_padding: size,
size,
max_repr_align,
unadjusted_abi_align,
Expand Down Expand Up @@ -1294,8 +1298,9 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
}
}

let field_size = if repr.swift() { field.size_without_padding } else { field.size };
offset =
offset.checked_add(field.size, dl).ok_or(LayoutCalculatorError::SizeOverflow)?;
offset.checked_add(field_size, dl).ok_or(LayoutCalculatorError::SizeOverflow)?;
}

// The unadjusted ABI alignment does not include repr(align), but does include repr(pack).
Expand Down Expand Up @@ -1417,6 +1422,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
largest_niche,
uninhabited,
align: AbiAlign::new(align),
size_without_padding: min_size,
size,
max_repr_align,
unadjusted_abi_align,
Expand Down Expand Up @@ -1516,6 +1522,7 @@ where
backend_repr: repr,
largest_niche: elt.largest_niche,
uninhabited: false,
size_without_padding: size,
size,
align: AbiAlign::new(align),
max_repr_align: None,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_abi/src/layout/coroutine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ pub(super) fn layout<
// FIXME: Remove when <https://github.com/rust-lang/rust/issues/125735> is implemented and aliased coroutine fields are wrapped in `UnsafePinned`.
largest_niche: None,
uninhabited,
size_without_padding: size,
size,
align,
max_repr_align: None,
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_abi/src/layout/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
largest_niche: None,
uninhabited: false,
align: AbiAlign::new(dl.i8_align),
size_without_padding: Size::ZERO,
size: Size::ZERO,
max_repr_align: None,
unadjusted_abi_align: dl.i8_align,
Expand All @@ -39,6 +40,7 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
largest_niche: None,
uninhabited: true,
align: AbiAlign::new(dl.i8_align),
size_without_padding: Size::ZERO,
size: Size::ZERO,
max_repr_align: None,
unadjusted_abi_align: dl.i8_align,
Expand Down Expand Up @@ -80,6 +82,7 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
backend_repr: BackendRepr::Scalar(scalar),
largest_niche,
uninhabited: false,
size_without_padding: size,
size,
align,
max_repr_align: None,
Expand Down Expand Up @@ -114,6 +117,7 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
largest_niche,
uninhabited: false,
align: AbiAlign::new(align),
size_without_padding: size,
size,
max_repr_align: None,
unadjusted_abi_align: align,
Expand All @@ -140,6 +144,7 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
largest_niche: None,
uninhabited: true,
align: AbiAlign::new(dl.i8_align),
size_without_padding: Size::ZERO,
size: Size::ZERO,
max_repr_align: None,
unadjusted_abi_align: dl.i8_align,
Expand All @@ -166,6 +171,7 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutData<FieldIdx, VariantIdx> {
largest_niche: layout.largest_niche,
uninhabited: layout.uninhabited,
size: layout.size,
size_without_padding: layout.size_without_padding,
align: parent.align,
max_repr_align: parent.max_repr_align,
unadjusted_abi_align: parent.unadjusted_abi_align,
Expand Down
18 changes: 17 additions & 1 deletion compiler/rustc_abi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,13 @@ bitflags! {
/// See [`TyAndLayout::pass_indirectly_in_non_rustic_abis`] for details.
const PASS_INDIRECTLY_IN_NON_RUSTIC_ABIS = 1 << 5;
const IS_SCALABLE = 1 << 6;
const IS_SWIFT = 1 << 7;
// Any of these flags being set prevent field reordering optimisation.
const FIELD_ORDER_UNOPTIMIZABLE = ReprFlags::IS_C.bits()
| ReprFlags::IS_SIMD.bits()
| ReprFlags::IS_SCALABLE.bits()
| ReprFlags::IS_LINEAR.bits();
| ReprFlags::IS_LINEAR.bits()
| ReprFlags::IS_SWIFT.bits();
const ABI_UNOPTIMIZABLE = ReprFlags::IS_C.bits() | ReprFlags::IS_SIMD.bits();
}
}
Expand Down Expand Up @@ -184,6 +186,11 @@ impl ReprOptions {
self.flags.contains(ReprFlags::IS_C)
}

#[inline]
pub fn swift(&self) -> bool {
self.flags.contains(ReprFlags::IS_SWIFT)
}

#[inline]
pub fn packed(&self) -> bool {
self.pack.is_some()
Expand Down Expand Up @@ -2162,7 +2169,12 @@ pub struct LayoutData<FieldIdx: Idx, VariantIdx: Idx> {
/// especially in the case of by-pointer struct returns, which allocate stack even when unused.
pub uninhabited: bool,

/// The alignment of the type in memory.
pub align: AbiAlign,
/// The amount of memory occupied by this type, this excludes padding.
pub size_without_padding: Size,
/// The stride of the type is its size including padding. Or how much you need to move in
/// memory to get from one element to the next.
pub size: Size,

/// The largest alignment explicitly requested with `repr(align)` on this type or any field.
Expand Down Expand Up @@ -2226,6 +2238,7 @@ where
// `Interned<LayoutData>`. We print it like this to avoid having to update
// expected output in a lot of tests.
let LayoutData {
size_without_padding: min_size,
size,
align,
backend_repr,
Expand All @@ -2238,6 +2251,7 @@ where
randomization_seed,
} = self;
f.debug_struct("Layout")
.field("min_size", min_size)
.field("size", size)
.field("align", align)
.field("backend_repr", backend_repr)
Expand Down Expand Up @@ -2388,6 +2402,7 @@ pub enum AbiFromStrErr {
#[cfg_attr(feature = "nightly", derive(StableHash))]
pub struct VariantLayout<FieldIdx: Idx> {
pub size: Size,
pub size_without_padding: Size,
pub backend_repr: BackendRepr,
pub field_offsets: IndexVec<FieldIdx, Size>,
fields_in_memory_order: IndexVec<u32, FieldIdx>,
Expand All @@ -2403,6 +2418,7 @@ impl<FieldIdx: Idx> VariantLayout<FieldIdx> {

Self {
size: layout.size,
size_without_padding: layout.size_without_padding,
backend_repr: layout.backend_repr,
field_offsets: offsets,
fields_in_memory_order: in_memory_order,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,7 @@ impl<'a> AstValidator<'a> {
| CanonAbi::RustCold
| CanonAbi::RustPreserveNone
| CanonAbi::RustTail
| CanonAbi::Swift
| CanonAbi::Swift { .. }
| CanonAbi::Arm(_)
| CanonAbi::X86(_) => { /* nothing to check */ }

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/abi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ pub(crate) fn conv_to_call_conv(
_ => default_call_conv,
},

CanonAbi::Interrupt(_) | CanonAbi::Arm(_) | CanonAbi::Swift => {
CanonAbi::Interrupt(_) | CanonAbi::Arm(_) | CanonAbi::Swift { .. } => {
sess.dcx().fatal(format!("call conv {c:?} is not yet implemented"))
}
CanonAbi::GpuKernel => {
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_codegen_gcc/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,8 @@ pub fn conv_to_fn_attribute<'gcc>(sess: &Session, conv: CanonAbi) -> Option<FnAt
sess.dcx().fatal("gcc/gccjit backend does not support RustTail calling convention")
}
CanonAbi::RustCold => FnAttribute::Cold,
// gcc doesn't support Swift as far as I'm aware
CanonAbi::Swift { .. } => return None,
// Functions with this calling convention can only be called from assembly, but it is
// possible to declare an `extern "custom"` block, so the backend still needs a calling
// convention for declaring foreign functions.
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_codegen_llvm/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,11 @@ pub(crate) fn to_llvm_calling_convention(sess: &Session, abi: CanonAbi) -> llvm:
// possible to declare an `extern "custom"` block, so the backend still needs a calling
// convention for declaring foreign functions.
CanonAbi::Custom => llvm::CCallConv,
CanonAbi::Swift => llvm::SwiftCallConv,
CanonAbi::Swift { tail } => if tail {
llvm::SwiftCallConvTail
} else {
llvm::SwiftCallConv
}
CanonAbi::GpuKernel => match &sess.target.arch {
Arch::AmdGpu => llvm::AmdgpuKernel,
Arch::Nvptx64 => llvm::PtxKernel,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_codegen_llvm/src/llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ pub(crate) enum CallConv {
PreserveAll = 15,
SwiftCallConv = 16,
Tail = 18,
SwiftCallConvTail = 20,
PreserveNone = 21,
X86StdcallCallConv = 64,
X86FastcallCallConv = 65,
Expand Down
10 changes: 8 additions & 2 deletions compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,13 +164,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
sym::size_of_val => {
let tp_ty = fn_args.type_at(0);
let (_, meta) = args[0].val.pointer_parts();
let (llsize, _) = size_of_val::size_and_align_of_dst(bx, tp_ty, meta);
let (llsize, _, _) = size_of_val::size_and_align_of_dst(bx, tp_ty, meta);
OperandValue::Immediate(llsize)
}
sym::stride_of_val => {
let tp_ty = fn_args.type_at(0);
let (_, meta) = args[0].val.pointer_parts();
let (_, llstride, _) = size_of_val::size_and_align_of_dst(bx, tp_ty, meta);
OperandValue::Immediate(llstride)
}
sym::align_of_val => {
let tp_ty = fn_args.type_at(0);
let (_, meta) = args[0].val.pointer_parts();
let (_, llalign) = size_of_val::size_and_align_of_dst(bx, tp_ty, meta);
let (_, _, llalign) = size_of_val::size_and_align_of_dst(bx, tp_ty, meta);
OperandValue::Immediate(llalign)
}
sym::vtable_size | sym::vtable_align => {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/mir/place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
let unaligned_offset = bx.cx().const_usize(offset.bytes());

// Get the alignment of the field
let (_, mut unsized_align) = size_of_val::size_and_align_of_dst(bx, field.ty, meta);
let (_, _, mut unsized_align) = size_of_val::size_and_align_of_dst(bx, field.ty, meta);

// For packed types, we need to cap alignment.
if let ty::Adt(def, _) = self.layout.ty.kind()
Expand Down
33 changes: 18 additions & 15 deletions compiler/rustc_codegen_ssa/src/size_of_val.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
bx: &mut Bx,
t: Ty<'tcx>,
info: Option<Bx::Value>,
) -> (Bx::Value, Bx::Value) {
) -> (Bx::Value, Bx::Value, Bx::Value) {
let layout = bx.layout_of(t);
trace!("size_and_align_of_dst(ty={}, info={:?}): layout: {:?}", t, info, layout);
if layout.is_sized() {
let size = bx.const_usize(layout.size.bytes());
let size = bx.const_usize(layout.size_without_padding.bytes());
let stride = bx.const_usize(layout.size.bytes());
let align = bx.const_usize(layout.align.bytes());
return (size, align);
return (size, stride, align);
}
match t.kind() {
ty::Dynamic(..) => {
Expand All @@ -41,18 +42,19 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
let align_bound = Align::max_for_target(bx.data_layout()).bytes().into();
bx.range_metadata(align, WrappingRange { start: 1, end: align_bound });

(size, align)
(size, size, align)
}
ty::Slice(_) | ty::Str => {
let unit = layout.field(bx, 0);
// The info in this case is the length of the str, so the size is that
// times the unit size.
(
// All slice sizes must fit into `isize`, so this multiplication cannot
// wrap -- neither signed nor unsigned.
bx.unchecked_sumul(info.unwrap(), bx.const_usize(unit.size.bytes())),
bx.const_usize(unit.align.bytes()),
)
let info = info.unwrap();
// All slice sizes must fit into `isize`, so this multiplication cannot
// wrap -- neither signed nor unsigned.
let size = bx.unchecked_sumul(info, bx.const_usize(unit.size_without_padding.bytes()));
let stride = bx.unchecked_sumul(info, bx.const_usize(unit.size.bytes()));
let align = bx.const_usize(unit.align.bytes());
(size, stride, align)
}
ty::Foreign(_) => {
// `extern` type. We cannot compute the size, so panic.
Expand Down Expand Up @@ -83,9 +85,10 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
);

// This function does not return so we can now return whatever we want.
let size = bx.const_usize(layout.size.bytes());
let size = bx.const_usize(layout.size_without_padding.bytes());
let stride = bx.const_usize(layout.size.bytes());
let align = bx.const_usize(layout.align.bytes());
(size, align)
(size, stride, align)
}
ty::Adt(..) | ty::Tuple(..) => {
// First get the size of all statically known fields.
Expand All @@ -107,7 +110,7 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
// Recurse to get the size of the dynamically sized field (must be
// the last field).
let field_ty = layout.field(bx, i).ty;
let (unsized_size, mut unsized_align) = size_and_align_of_dst(bx, field_ty, info);
let (_, unsized_size, mut unsized_align) = size_and_align_of_dst(bx, field_ty, info);

// # First compute the dynamic alignment

Expand Down Expand Up @@ -175,9 +178,9 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
let addend = bx.sub(full_align, one);
let add = bx.add(full_size, addend);
let neg = bx.neg(full_align);
let full_size = bx.and(add, neg);
let full_stride = bx.and(add, neg);

(full_size, full_align)
(full_size, full_stride, full_align)
}
_ => bug!("size_and_align_of_dst: {t} not supported"),
}
Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_const_eval/src/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
layout: &TyAndLayout<'tcx>,
) -> InterpResult<'tcx, Option<(Size, Align)>> {
if layout.is_sized() {
return interp_ok(Some((layout.size, layout.align.abi)));
return interp_ok(Some((layout.size_without_padding, layout.align.abi)));
}
match layout.ty.kind() {
ty::Adt(..) | ty::Tuple(..) => {
Expand Down Expand Up @@ -473,7 +473,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// # Then compute the dynamic size

let unsized_offset_adjusted = unsized_offset_unadjusted.align_to(unsized_align);
let full_size = (unsized_offset_adjusted + unsized_size).align_to(full_align);
let full_size = unsized_offset_adjusted + unsized_size;

// Just for our sanitiy's sake, assert that this is equal to what codegen would compute.
assert_eq!(
Expand Down Expand Up @@ -511,6 +511,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
_ => span_bug!(self.cur_span(), "size_and_align_of::<{}> not supported", layout.ty),
}
}

#[inline]
pub fn size_and_align_of_val(
&self,
Expand Down
Loading
Loading