implement vector-containing aggregate alignment for x86 darwin
This commit is contained in:
parent
be1d4e3e0b
commit
a07eb0abbd
@ -1,5 +1,5 @@
|
|||||||
use crate::abi::call::{ArgAttribute, FnAbi, PassMode, Reg, RegKind};
|
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;
|
use crate::spec::HasTargetSpec;
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
@ -53,38 +53,58 @@ pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, flavor: F
|
|||||||
if arg.is_ignore() {
|
if arg.is_ignore() {
|
||||||
continue;
|
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
|
if arg.layout.is_aggregate() {
|
||||||
// `X86_32ABIInfo::getTypeStackAlignInBytes` in Clang's `TargetInfo.cpp`. Summarized here,
|
// We need to compute the alignment of the `byval` argument. The rules can be found in
|
||||||
// they are:
|
// `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.
|
//
|
||||||
//
|
// 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 ensure we have an aggregate with the check above.)
|
// 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.
|
// 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();
|
// 4. If none of these conditions are true, the alignment is 4.
|
||||||
let align_4 = Align::from_bytes(4).unwrap();
|
|
||||||
let align_16 = Align::from_bytes(16).unwrap();
|
fn contains_vector<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool
|
||||||
let byval_align = if arg.layout.align.abi < align_4 {
|
where
|
||||||
align_4
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
} 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
|
match layout.abi {
|
||||||
// determine if it contains SIMD vector values--but I think it's fine?
|
Abi::Uninhabited | Abi::Scalar(_) | Abi::ScalarPair(..) => false,
|
||||||
align_16
|
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 {
|
} else {
|
||||||
align_4
|
arg.extend_integer_width_to(32);
|
||||||
};
|
}
|
||||||
|
|
||||||
arg.make_indirect_byval(Some(byval_align));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if flavor == Flavor::FastcallOrVectorcall {
|
if flavor == Flavor::FastcallOrVectorcall {
|
||||||
|
58
tests/codegen/align-byval-vector.rs
Normal file
58
tests/codegen/align-byval-vector.rs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
// revisions:x86-linux x86-darwin
|
||||||
|
|
||||||
|
//[x86-linux] compile-flags: --target i686-unknown-linux-gnu
|
||||||
|
//[x86-linux] needs-llvm-components: x86
|
||||||
|
//[x86-darwin] compile-flags: --target i686-apple-darwin
|
||||||
|
//[x86-darwin] needs-llvm-components: x86
|
||||||
|
|
||||||
|
// Tests that aggregates containing vector types get their alignment increased to 16 on Darwin.
|
||||||
|
|
||||||
|
#![feature(no_core, lang_items, repr_simd, simd_ffi)]
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
#![no_std]
|
||||||
|
#![no_core]
|
||||||
|
#![allow(non_camel_case_types)]
|
||||||
|
|
||||||
|
#[lang = "sized"]
|
||||||
|
trait Sized {}
|
||||||
|
#[lang = "freeze"]
|
||||||
|
trait Freeze {}
|
||||||
|
#[lang = "copy"]
|
||||||
|
trait Copy {}
|
||||||
|
|
||||||
|
#[repr(simd)]
|
||||||
|
pub struct i32x4(i32, i32, i32, i32);
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Foo {
|
||||||
|
a: i32x4,
|
||||||
|
b: i8,
|
||||||
|
}
|
||||||
|
|
||||||
|
// This tests that we recursively check for vector types, not just at the top level.
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct DoubleFoo {
|
||||||
|
one: Foo,
|
||||||
|
two: Foo,
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
// x86-linux: declare void @f({{.*}}byval(%Foo) align 4{{.*}})
|
||||||
|
// x86-darwin: declare void @f({{.*}}byval(%Foo) align 16{{.*}})
|
||||||
|
fn f(foo: Foo);
|
||||||
|
|
||||||
|
// x86-linux: declare void @g({{.*}}byval(%DoubleFoo) align 4{{.*}})
|
||||||
|
// x86-darwin: declare void @g({{.*}}byval(%DoubleFoo) align 16{{.*}})
|
||||||
|
fn g(foo: DoubleFoo);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
unsafe { f(Foo { a: i32x4(1, 2, 3, 4), b: 0 }) }
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
g(DoubleFoo {
|
||||||
|
one: Foo { a: i32x4(1, 2, 3, 4), b: 0 },
|
||||||
|
two: Foo { a: i32x4(1, 2, 3, 4), b: 0 },
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user