forked from OSchip/llvm-project
Add option to use older clang ABI behavior when passing certain union types as function arguments
Recently commit D78699 (commit 26cfb6e562
), fixed clang's behavior with respect
to passing a union type through a register to correctly follow the ABI. However,
this is an ABI breaking change with earlier versions of the clang compiler, so we
should add an -fclang-abi-compat option to address this. Additionally, the PS4 ABI
requires the older behavior, so that is added as well.
This change adds a Ver11 value to the ClangABI enum that when it is set (or the
target is the PS4 triple), we skip the ABI fix introduced in D78699.
Differential Revision: https://reviews.llvm.org/D89747
This commit is contained in:
parent
ae9d040028
commit
774ab60125
|
@ -153,6 +153,11 @@ public:
|
||||||
/// NetBSD.
|
/// NetBSD.
|
||||||
Ver9,
|
Ver9,
|
||||||
|
|
||||||
|
/// Attempt to be ABI-compatible with code generated by Clang 11.0.x
|
||||||
|
/// (git 2e10b7a39b93). This causes clang to pass unions with a 256-bit
|
||||||
|
/// vector member on the stack instead of using registers.
|
||||||
|
Ver11,
|
||||||
|
|
||||||
/// Conform to the underlying platform's C and C++ ABIs as closely
|
/// Conform to the underlying platform's C and C++ ABIs as closely
|
||||||
/// as we can.
|
/// as we can.
|
||||||
Latest
|
Latest
|
||||||
|
|
|
@ -3061,7 +3061,11 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase,
|
||||||
|
|
||||||
// Classify the fields one at a time, merging the results.
|
// Classify the fields one at a time, merging the results.
|
||||||
unsigned idx = 0;
|
unsigned idx = 0;
|
||||||
bool IsUnion = RT->isUnionType();
|
bool UseClang11Compat = getContext().getLangOpts().getClangABICompat() <=
|
||||||
|
LangOptions::ClangABI::Ver11 ||
|
||||||
|
getContext().getTargetInfo().getTriple().isPS4();
|
||||||
|
bool IsUnion = RT->isUnionType() && !UseClang11Compat;
|
||||||
|
|
||||||
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
|
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
|
||||||
i != e; ++i, ++idx) {
|
i != e; ++i, ++idx) {
|
||||||
uint64_t Offset = OffsetBase + Layout.getFieldOffset(idx);
|
uint64_t Offset = OffsetBase + Layout.getFieldOffset(idx);
|
||||||
|
|
|
@ -3460,6 +3460,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
|
||||||
Opts.setClangABICompat(LangOptions::ClangABI::Ver7);
|
Opts.setClangABICompat(LangOptions::ClangABI::Ver7);
|
||||||
else if (Major <= 9)
|
else if (Major <= 9)
|
||||||
Opts.setClangABICompat(LangOptions::ClangABI::Ver9);
|
Opts.setClangABICompat(LangOptions::ClangABI::Ver9);
|
||||||
|
else if (Major <= 11)
|
||||||
|
Opts.setClangABICompat(LangOptions::ClangABI::Ver11);
|
||||||
} else if (Ver != "latest") {
|
} else if (Ver != "latest") {
|
||||||
Diags.Report(diag::err_drv_invalid_value)
|
Diags.Report(diag::err_drv_invalid_value)
|
||||||
<< A->getAsString(Args) << A->getValue();
|
<< A->getAsString(Args) << A->getValue();
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
// RUN: %clang_cc1 -w -ffreestanding -triple x86_64-linux-gnu -target-feature +avx -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=AVX
|
// RUN: %clang_cc1 -w -ffreestanding -triple x86_64-linux-gnu -target-feature +avx -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=AVX
|
||||||
// RUN: %clang_cc1 -w -ffreestanding -triple x86_64-linux-gnu -target-feature +avx512f -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=AVX512
|
// RUN: %clang_cc1 -w -ffreestanding -triple x86_64-linux-gnu -target-feature +avx512f -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=AVX512
|
||||||
|
|
||||||
|
// Test Clang 11 and earlier behavior
|
||||||
|
// RUN: %clang_cc1 -w -ffreestanding -triple x86_64-linux-gnu -target-feature +avx -fclang-abi-compat=10.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=AVX --check-prefix=CHECK-LEGACY
|
||||||
|
// RUN: %clang_cc1 -w -ffreestanding -triple x86_64-linux-gnu -target-feature +avx512f -fclang-abi-compat=11.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-LEGACY --check-prefix=AVX512-LEGACY
|
||||||
|
// RUN: %clang_cc1 -w -ffreestanding -triple x86_64-scei-ps4 -target-feature +avx -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-LEGACY --check-prefix=AVX-LEGACY
|
||||||
|
|
||||||
// This tests verifies that a union parameter should pass by a vector regitster whose first eightbyte is SSE and the other eightbytes are SSEUP.
|
// This tests verifies that a union parameter should pass by a vector regitster whose first eightbyte is SSE and the other eightbytes are SSEUP.
|
||||||
|
|
||||||
typedef int __m256 __attribute__ ((__vector_size__ (32)));
|
typedef int __m256 __attribute__ ((__vector_size__ (32)));
|
||||||
|
@ -21,8 +27,10 @@ union M256 m1;
|
||||||
union M512 m2;
|
union M512 m2;
|
||||||
// CHECK-LABEL: define void @test()
|
// CHECK-LABEL: define void @test()
|
||||||
// CHECK: call void @foo1(<4 x double>
|
// CHECK: call void @foo1(<4 x double>
|
||||||
|
// CHECK-LEGACY: call void @foo1(%union.M256* byval(%union.M256) align 32
|
||||||
// AVX: call void @foo2(%union.M512* byval(%union.M512) align 64
|
// AVX: call void @foo2(%union.M512* byval(%union.M512) align 64
|
||||||
// AVX512: call void @foo2(<8 x double>
|
// AVX512: call void @foo2(<8 x double>
|
||||||
|
// AVX512-LEGACY: call void @foo2(%union.M512* byval(%union.M512) align 64
|
||||||
void test() {
|
void test() {
|
||||||
foo1(m1);
|
foo1(m1);
|
||||||
foo2(m2);
|
foo2(m2);
|
||||||
|
|
Loading…
Reference in New Issue