implement vector-containing aggregate alignment for x86 darwin
This commit is contained in:
parent
be1d4e3e0b
commit
a07eb0abbd
2 changed files with 109 additions and 31 deletions
|
@ -1,5 +1,5 @@
|
|||
use crate::abi::call::{ArgAttribute, FnAbi, PassMode, Reg, RegKind};
|
||||
use crate::abi::{Align, HasDataLayout, TyAbiInterface};
|
||||
use crate::abi::{Abi, Align, HasDataLayout, TyAbiInterface, TyAndLayout};
|
||||
use crate::spec::HasTargetSpec;
|
||||
|
||||
#[derive(PartialEq)]
|
||||
|
@ -53,38 +53,58 @@ where
|
|||
if arg.is_ignore() {
|
||||
continue;
|
||||
}
|
||||
if !arg.layout.is_aggregate() {
|
||||
arg.extend_integer_width_to(32);
|
||||
continue;
|
||||
}
|
||||
|
||||
// We need to compute the alignment of the `byval` argument. The rules can be found in
|
||||
// `X86_32ABIInfo::getTypeStackAlignInBytes` in Clang's `TargetInfo.cpp`. Summarized here,
|
||||
// they are:
|
||||
//
|
||||
// 1. If the natural alignment of the type is less than or equal to 4, the alignment is 4.
|
||||
//
|
||||
// 2. Otherwise, on Linux, the alignment of any vector type is the natural alignment.
|
||||
// (This doesn't matter here because we ensure we have an aggregate with the check above.)
|
||||
//
|
||||
// 3. Otherwise, on Apple platforms, the alignment of anything that contains a vector type
|
||||
// is 16.
|
||||
//
|
||||
// 4. If none of these conditions are true, the alignment is 4.
|
||||
let t = cx.target_spec();
|
||||
let align_4 = Align::from_bytes(4).unwrap();
|
||||
let align_16 = Align::from_bytes(16).unwrap();
|
||||
let byval_align = if arg.layout.align.abi < align_4 {
|
||||
align_4
|
||||
} else if t.is_like_osx && arg.layout.align.abi >= align_16 {
|
||||
// FIXME(pcwalton): This is dubious--we should actually be looking inside the type to
|
||||
// determine if it contains SIMD vector values--but I think it's fine?
|
||||
align_16
|
||||
if arg.layout.is_aggregate() {
|
||||
// We need to compute the alignment of the `byval` argument. The rules can be found in
|
||||
// `X86_32ABIInfo::getTypeStackAlignInBytes` in Clang's `TargetInfo.cpp`. Summarized
|
||||
// here, they are:
|
||||
//
|
||||
// 1. If the natural alignment of the type is <= 4, the alignment is 4.
|
||||
//
|
||||
// 2. Otherwise, on Linux, the alignment of any vector type is the natural alignment.
|
||||
// This doesn't matter here because we only pass aggregates via `byval`, not vectors.
|
||||
//
|
||||
// 3. Otherwise, on Apple platforms, the alignment of anything that contains a vector
|
||||
// type is 16.
|
||||
//
|
||||
// 4. If none of these conditions are true, the alignment is 4.
|
||||
|
||||
fn contains_vector<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool
|
||||
where
|
||||
Ty: TyAbiInterface<'a, C> + Copy,
|
||||
{
|
||||
match layout.abi {
|
||||
Abi::Uninhabited | Abi::Scalar(_) | Abi::ScalarPair(..) => false,
|
||||
Abi::Vector { .. } => true,
|
||||
Abi::Aggregate { .. } => {
|
||||
for i in 0..layout.fields.count() {
|
||||
if contains_vector(cx, layout.field(cx, i)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let t = cx.target_spec();
|
||||
let align_4 = Align::from_bytes(4).unwrap();
|
||||
let align_16 = Align::from_bytes(16).unwrap();
|
||||
let byval_align = if arg.layout.align.abi < align_4 {
|
||||
// (1.)
|
||||
align_4
|
||||
} else if t.is_like_osx && contains_vector(cx, arg.layout) {
|
||||
// (3.)
|
||||
align_16
|
||||
} else {
|
||||
// (4.)
|
||||
align_4
|
||||
};
|
||||
|
||||
arg.make_indirect_byval(Some(byval_align));
|
||||
} else {
|
||||
align_4
|
||||
};
|
||||
|
||||
arg.make_indirect_byval(Some(byval_align));
|
||||
arg.extend_integer_width_to(32);
|
||||
}
|
||||
}
|
||||
|
||||
if flavor == Flavor::FastcallOrVectorcall {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue