From: Fangrui Song Date: Mon, 15 Jul 2019 07:25:11 +0000 (+0000) Subject: [PowerPC] Support -mabi=ieeelongdouble and -mabi=ibmlongdouble X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a9bc6dd02c0309a30caf6d8c0ab4565e072d688a;p=clang [PowerPC] Support -mabi=ieeelongdouble and -mabi=ibmlongdouble gcc PowerPC supports 3 representations of long double: * -mlong-double-64 long double has the same representation of double but is mangled as `e`. In clang, this is the default on AIX, FreeBSD and Linux musl. * -mlong-double-128 2 possible 128-bit floating point representations: + -mabi=ibmlongdouble IBM extended double format. Mangled as `g` In clang, this is the default on Linux glibc. + -mabi=ieeelongdouble IEEE 754 quadruple-precision format. Mangled as `u9__ieee128` (`U10__float128` before gcc 8.2) This is currently unavailable. This patch adds -mabi=ibmlongdouble and -mabi=ieeelongdouble, and thus makes the IEEE 754 quadruple-precision long double available for languages supported by clang. Reviewed By: hfinkel Differential Revision: https://reviews.llvm.org/D64283 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@366044 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index 46012f73aa..bbe3f7b77d 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -172,6 +172,7 @@ VALUE_LANGOPT(MaxTypeAlign , 32, 0, "default maximum alignment for types") VALUE_LANGOPT(AlignDouble , 1, 0, "Controls if doubles should be aligned to 8 bytes (x86 only)") VALUE_LANGOPT(LongDoubleSize , 32, 0, "width of long double") +LANGOPT(PPCIEEELongDouble , 1, 0, "use IEEE 754 quadruple-precision for long double") COMPATIBLE_VALUE_LANGOPT(PICLevel , 2, 0, "__PIC__ level") COMPATIBLE_VALUE_LANGOPT(PIE , 1, 0, "is pie") LANGOPT(ROPI , 1, 0, "Read-only position independence") diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 8862a01582..1f6c000ecf 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -298,6 +298,8 @@ def menable_unsafe_fp_math : Flag<["-"], "menable-unsafe-fp-math">, "precision">; def mreassociate : Flag<["-"], "mreassociate">, HelpText<"Allow reassociation transformations for floating-point instructions">; +def mabi_EQ_ieeelongdouble : Flag<["-"], "mabi=ieeelongdouble">, + HelpText<"Use IEEE 754 quadruple-precision for long double">; def mfloat_abi : Separate<["-"], "mfloat-abi">, HelpText<"The float ABI to use">; def mtp : Separate<["-"], "mtp">, diff --git a/lib/Basic/Targets/PPC.cpp b/lib/Basic/Targets/PPC.cpp index bd0ae60038..2a773d9992 100644 --- a/lib/Basic/Targets/PPC.cpp +++ b/lib/Basic/Targets/PPC.cpp @@ -466,7 +466,9 @@ void PPCTargetInfo::adjust(LangOptions &Opts) { Opts.AltiVec = 1; TargetInfo::adjust(Opts); if (LongDoubleFormat != &llvm::APFloat::IEEEdouble()) - LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble(); + LongDoubleFormat = Opts.PPCIEEELongDouble + ? &llvm::APFloat::IEEEquad() + : &llvm::APFloat::PPCDoubleDouble(); } ArrayRef PPCTargetInfo::getTargetBuiltins() const { diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index c84cb480f1..6a83e1a480 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -1803,12 +1803,21 @@ void Clang::AddPPCTargetArgs(const ArgList &Args, break; } - if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) - // The ppc64 linux abis are all "altivec" abis by default. Accept and ignore - // the option if given as we don't have backend support for any targets - // that don't use the altivec abi. - if (StringRef(A->getValue()) != "altivec") + bool IEEELongDouble = false; + for (const Arg *A : Args.filtered(options::OPT_mabi_EQ)) { + StringRef V = A->getValue(); + if (V == "ieeelongdouble") + IEEELongDouble = true; + else if (V == "ibmlongdouble") + IEEELongDouble = false; + else if (V != "altivec") + // The ppc64 linux abis are all "altivec" abis by default. Accept and ignore + // the option if given as we don't have backend support for any targets + // that don't use the altivec abi. ABIName = A->getValue(); + } + if (IEEELongDouble) + CmdArgs.push_back("-mabi=ieeelongdouble"); ppc::FloatABI FloatABI = ppc::getPPCFloatABI(getToolChain().getDriver(), Args); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 7a07d9955f..8a9844096f 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -2745,6 +2745,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.LongDoubleSize = Args.hasArg(OPT_mlong_double_128) ? 128 : Args.hasArg(OPT_mlong_double_64) ? 64 : 0; + Opts.PPCIEEELongDouble = Args.hasArg(OPT_mabi_EQ_ieeelongdouble); Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags); Opts.ROPI = Args.hasArg(OPT_fropi); Opts.RWPI = Args.hasArg(OPT_frwpi); diff --git a/test/CodeGen/ppc64-long-double.cpp b/test/CodeGen/ppc64-long-double.cpp index d588d6b80e..a35965f2bf 100644 --- a/test/CodeGen/ppc64-long-double.cpp +++ b/test/CodeGen/ppc64-long-double.cpp @@ -3,6 +3,14 @@ // RUN: %clang_cc1 -triple powerpc64-linux-gnu -emit-llvm -o - %s -mlong-double-64 | \ // RUN: FileCheck --check-prefix=FP64 %s +// musl defaults to -mlong-double-64, so -mlong-double-128 is needed to make +// -mabi=ieeelongdouble effective. +// RUN: %clang_cc1 -triple powerpc64-linux-musl -emit-llvm -o - %s -mlong-double-128 \ +// RUN: -mabi=ieeelongdouble | FileCheck --check-prefix=FP128 %s +// RUN: %clang_cc1 -triple powerpc64-linux-gnu -emit-llvm -o - %s \ +// RUN: -mabi=ieeelongdouble | FileCheck --check-prefix=FP128 %s + +// IBM extended double is the default. // RUN: %clang_cc1 -triple powerpc64-linux-gnu -emit-llvm -o - %s | \ // RUN: FileCheck --check-prefix=IBM128 %s // RUN: %clang_cc1 -triple powerpc64-linux-musl -emit-llvm -o - -mlong-double-128 %s | \ @@ -13,10 +21,13 @@ int size = sizeof(x); // FP64: @x = global double {{.*}}, align 8 // FP64: @size = global i32 8 +// FP128: @x = global fp128 {{.*}}, align 16 +// FP128: @size = global i32 16 // IBM128: @x = global ppc_fp128 {{.*}}, align 16 // IBM128: @size = global i32 16 long double foo(long double d) { return d; } // FP64: double @_Z3fooe(double %d) +// FP128: fp128 @_Z3foou9__ieee128(fp128 %d) // IBM128: ppc_fp128 @_Z3foog(ppc_fp128 %d) diff --git a/test/Driver/ppc-abi.c b/test/Driver/ppc-abi.c index a82a01de27..fdcf45da29 100644 --- a/test/Driver/ppc-abi.c +++ b/test/Driver/ppc-abi.c @@ -66,4 +66,22 @@ // CHECK-ELFv2-PIC: "-mrelocation-model" "pic" "-pic-level" "2" // CHECK-ELFv2-PIC: "-target-abi" "elfv2" +// Check -mabi=ieeelongdouble is passed through but it does not change -target-abi. +// RUN: %clang -target powerpc64le-linux-gnu %s -mabi=ieeelongdouble -mabi=elfv1 -### 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-ELFv1-IEEE %s +// RUN: %clang -target powerpc64le-linux-gnu %s -mabi=elfv1 -mabi=ieeelongdouble -### 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-ELFv1-IEEE %s +// RUN: %clang -target powerpc64le-linux-gnu %s -mabi=elfv2 -mabi=elfv1 -mabi=ibmlongdouble -mabi=ieeelongdouble -### 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-ELFv1-IEEE %s +// CHECK-ELFv1-IEEE: "-mabi=ieeelongdouble" +// CHECK-ELFv1-IEEE: "-target-abi" "elfv1" + +// Check -mabi=ibmlongdouble is the default. +// RUN: %clang -target powerpc64le-linux-gnu %s -### 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-ELFv2-IBM128 %s +// RUN: %clang -target powerpc64le-linux-gnu %s -mabi=ibmlongdouble -### 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-ELFv2-IBM128 %s + +// CHECK-ELFv2-IBM128-NOT: "-mabi=ieeelongdouble" +// CHECK-ELFv2-IBM128: "-target-abi" "elfv2"