diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -1108,6 +1108,7 @@ bool IsWin32StructABI; bool IsSoftFloatABI; bool IsMCUABI; + bool IsLinuxABI; unsigned DefaultNumRegisterParameters; static bool isRegisterSize(unsigned Size) { @@ -1173,6 +1174,7 @@ IsWin32StructABI(Win32StructABI), IsSoftFloatABI(SoftFloatABI), IsMCUABI(CGT.getTarget().getTriple().isOSIAMCU()), + IsLinuxABI(CGT.getTarget().getTriple().isOSLinux()), DefaultNumRegisterParameters(NumRegisterParameters) {} bool shouldPassIndirectlyForSwift(ArrayRef scalars, @@ -1597,6 +1599,9 @@ if (Align <= MinABIStackAlignInBytes) return 0; // Use default alignment. + if (IsLinuxABI && Ty->isFloatingType() && getContext().getTypeSize(Ty) == 128) + return 16; + // On non-Darwin, the stack type alignment is always 4. if (!IsDarwinVectorABI) { // Set explicit alignment, since we may need to realign the top. @@ -1890,6 +1895,9 @@ return getIndirectResult(Ty, /*ByVal=*/false, State); } + if (IsLinuxABI && Ty->isFloatingType() && getContext().getTypeSize(Ty) == 128) + return getIndirectResult(Ty, /*ByVal=*/true, State); + if (InReg) return ABIArgInfo::getDirectInReg(); return ABIArgInfo::getDirect(); diff --git a/clang/test/CodeGen/x86-long-double.cpp b/clang/test/CodeGen/x86-long-double.cpp --- a/clang/test/CodeGen/x86-long-double.cpp +++ b/clang/test/CodeGen/x86-long-double.cpp @@ -16,14 +16,14 @@ // RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin -mlong-double-64 | \ // RUN: FileCheck --check-prefixes=FP64,FP64-X64 %s -// RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686 -mlong-double-128 | \ -// RUN: FileCheck --check-prefix=FP128 %s +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=i386-pc-linux-gnu -mlong-double-128 | \ +// RUN: FileCheck --check-prefixes=FP128,FP128-X32-LINUX %s // RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686-apple-darwin -mlong-double-128 | \ -// RUN: FileCheck --check-prefix=FP128 %s +// RUN: FileCheck --check-prefixes=FP128,FP128-X32-DARWIN %s // RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64 -mlong-double-128 | \ -// RUN: FileCheck --check-prefix=FP128 %s +// RUN: FileCheck --check-prefixes=FP128,FP128-X64 %s // RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin -mlong-double-128 | \ -// RUN: FileCheck --check-prefix=FP128 %s +// RUN: FileCheck --check-prefixes=FP128,FP128-X64 %s // Check -malign-double increases the alignment from 4 to 8 on x86-32. // RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686 -mlong-double-64 \ @@ -53,4 +53,6 @@ // FP64: double @_Z3fooe(double %d) // FP80: x86_fp80 @_Z3fooe(x86_fp80 %d) -// FP128: fp128 @_Z3foog(fp128 %d) +// FP128-X32-LINUX: fp128 @_Z3foog(fp128* byval(fp128) align 16 %0) +// FP128-X32-DARWIN: fp128 @_Z3foog(fp128 %d) +// FP128-X64: fp128 @_Z3foog(fp128 %d) diff --git a/clang/test/CodeGen/x86_32-fp128-call-conv-linux.c b/clang/test/CodeGen/x86_32-fp128-call-conv-linux.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/x86_32-fp128-call-conv-linux.c @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -mlong-double-128 -w -fblocks -ffreestanding -triple i386-pc-linux-gnu -emit-llvm -o %t %s || FileCheck < %t %s + + +// CHECK-LABEL: define void @testfp128 +// CHECK-NEXT: %a.addr = alloca fp128, align 16 +// CHECK-NEXT: %a = load fp128, fp128* %0, align 16 +// CHECK-NEXT: store fp128 %a, fp128* %a.addr, align 16 +void testfp128(__float128 a) { + return; +} + +// CHECK-LABEL: define void @testlongdouble +// CHECK-NEXT: %a.addr = alloca fp128, align 16 +// CHECK-NEXT: %a = load fp128, fp128* %0, align 16 +// CHECK-NEXT: store fp128 %a, fp128* %a.addr, align 16 +void testlongdouble(long double a) { + return; +} + +// CHECK-LABEL: define void @testPassArguments +// CHECK: call void @testfp128(fp128* byval(fp128) align 16 %{{.*}}) +// CHECK: call void @testlongdouble(fp128* byval(fp128) align 16 %{{.*}}) +void testPassArguments() { + __float128 a=1.0; + testfp128(a); + testlongdouble(a); + return; +} diff --git a/clang/test/CodeGenCXX/float128-declarations.cpp b/clang/test/CodeGenCXX/float128-declarations.cpp --- a/clang/test/CodeGenCXX/float128-declarations.cpp +++ b/clang/test/CodeGenCXX/float128-declarations.cpp @@ -3,7 +3,7 @@ // RUN: %clang_cc1 -emit-llvm -triple powerpc64le-unknown-unknown \ // RUN: -target-feature +float128 -std=c++11 %s -o - | FileCheck %s // RUN: %clang_cc1 -emit-llvm -triple i386-unknown-linux-gnu -std=c++11 \ -// RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86 +// RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86-32-LINUX // RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown-linux-gnu -std=c++11 \ // RUN: %s -o - | FileCheck %s -check-prefix=CHECK-X86 // RUN: %clang_cc1 -emit-llvm -triple i686-pc-openbsd -std=c++11 \ @@ -123,3 +123,25 @@ // CHECK-X86-DAG: [[F4L:%[a-z0-9]+]] = load fp128, fp128* %f4l // CHECK-X86-DAG: [[INC:%[a-z0-9]+]] = fadd fp128 [[F4L]], 0xL00000000000000003FFF000000000000 // CHECK-X86-DAG: store fp128 [[INC]], fp128* %f4l + +// CHECK-X86-32-LINUX-DAG: @_ZN12_GLOBAL__N_13f1nE = internal global fp128 0xL00000000000000000000000000000000 +// CHECK-X86-32-LINUX-DAG: @_ZN12_GLOBAL__N_13f2nE = internal global fp128 0xL00000000000000004004080000000000 +// CHECK-X86-32-LINUX-DAG: @_ZN12_GLOBAL__N_15arr1nE = internal global [10 x fp128] +// CHECK-X86-32-LINUX-DAG: @_ZN12_GLOBAL__N_15arr2nE = internal global [3 x fp128] [fp128 0xL33333333333333333FFF333333333333, fp128 0xL00000000000000004000800000000000, fp128 0xL00000000000000004025176592E00000] +// CHECK-X86-32-LINUX-DAG: define internal fp128 @_ZN12_GLOBAL__N_16func1nERKg(fp128* +// CHECK-X86-32-LINUX-DAG: @f1f = global fp128 0xL00000000000000000000000000000000 +// CHECK-X86-32-LINUX-DAG: @f2f = global fp128 0xL33333333333333334004033333333333 +// CHECK-X86-32-LINUX-DAG: @arr1f = global [10 x fp128] +// CHECK-X86-32-LINUX-DAG: @arr2f = global [3 x fp128] [fp128 0xL3333333333333333BFFF333333333333, fp128 0xL0000000000000000C000800000000000, fp128 0xL0000000000000000C025176592E00000] +// CHECK-X86-32-LINUX-DAG: declare fp128 @_Z6func1fg(fp128* byval(fp128) align 16) #3 +// CHECK-X86-32-LINUX-DAG: define linkonce_odr void @_ZN2C1C2Eg(%class.C1* %this, fp128* byval(fp128) align 16 %0) +// CHECK-X86-32-LINUX-DAG: define linkonce_odr fp128 @_ZN2C16func2cEg(fp128* byval(fp128) align 16 %0) +// CHECK-X86-32-LINUX-DAG: define linkonce_odr fp128 @_Z6func1tIgET_S0_(fp128* byval(fp128) align 16 %0) +// CHECK-X86-32-LINUX-DAG: @__const.main.s1 = private unnamed_addr constant %struct.S1 { fp128 0xL00000000000000004006080000000000 } +// CHECK-X86-32-LINUX-DAG: store fp128 0xLF0AFD0EBFF292DCE42E0B38CDD83F26F, fp128* %f1l, align 16 +// CHECK-X86-32-LINUX-DAG: store fp128 0xL00000000000000008000000000000000, fp128* %f2l, align 16 +// CHECK-X86-32-LINUX-DAG: store fp128 0xLFFFFFFFFFFFFFFFF7FFEFFFFFFFFFFFF, fp128* %f3l, align 16 +// CHECK-X86-32-LINUX-DAG: store fp128 0xL0000000000000000BFFF000000000000, fp128* %f5l, align 16 +// CHECK-X86-32-LINUX-DAG: [[F4L:%[a-z0-9]+]] = load fp128, fp128* %f4l +// CHECK-X86-32-LINUX-DAG: [[INC:%[a-z0-9]+]] = fadd fp128 [[F4L]], 0xL00000000000000003FFF000000000000 +// CHECK-X86-32-LINUX-DAG: store fp128 [[INC]], fp128* %f4l