Index: cfe/trunk/include/clang/Basic/LangOptions.def =================================================================== --- cfe/trunk/include/clang/Basic/LangOptions.def +++ cfe/trunk/include/clang/Basic/LangOptions.def @@ -171,6 +171,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") COMPATIBLE_VALUE_LANGOPT(PICLevel , 2, 0, "__PIC__ level") COMPATIBLE_VALUE_LANGOPT(PIE , 1, 0, "is pie") LANGOPT(ROPI , 1, 0, "Read-only position independence") Index: cfe/trunk/include/clang/Driver/Options.td =================================================================== --- cfe/trunk/include/clang/Driver/Options.td +++ cfe/trunk/include/clang/Driver/Options.td @@ -2023,6 +2023,8 @@ def mfancy_math_387 : Flag<["-"], "mfancy-math-387">, Group; def mlong_calls : Flag<["-"], "mlong-calls">, Group, HelpText<"Generate branches with extended addressability, usually via indirect jumps.">; +def mlong_double_64 : Flag<["-"], "mlong-double-64">, Group, Flags<[CC1Option]>, + HelpText<"Force long double to be 64 bits">; def mno_long_calls : Flag<["-"], "mno-long-calls">, Group, HelpText<"Restore the default behaviour of not generating long calls">; def mexecute_only : Flag<["-"], "mexecute-only">, Group, Index: cfe/trunk/lib/Basic/TargetInfo.cpp =================================================================== --- cfe/trunk/lib/Basic/TargetInfo.cpp +++ cfe/trunk/lib/Basic/TargetInfo.cpp @@ -373,6 +373,12 @@ LongDoubleFormat = &llvm::APFloat::IEEEquad(); } + if (Opts.LongDoubleSize && Opts.LongDoubleSize == DoubleWidth) { + LongDoubleWidth = DoubleWidth; + LongDoubleAlign = DoubleAlign; + LongDoubleFormat = DoubleFormat; + } + if (Opts.NewAlignOverride) NewAlign = Opts.NewAlignOverride * getCharWidth(); Index: cfe/trunk/lib/Basic/Targets/PPC.h =================================================================== --- cfe/trunk/lib/Basic/Targets/PPC.h +++ cfe/trunk/lib/Basic/Targets/PPC.h @@ -345,17 +345,10 @@ break; } - switch (getTriple().getOS()) { - case llvm::Triple::FreeBSD: - case llvm::Triple::NetBSD: - case llvm::Triple::OpenBSD: - // FIXME: -mlong-double-128 is not yet supported on AIX. - case llvm::Triple::AIX: + if (Triple.isOSFreeBSD() || Triple.isOSNetBSD() || Triple.isOSOpenBSD() || + Triple.getOS() == llvm::Triple::AIX || Triple.isMusl()) { LongDoubleWidth = LongDoubleAlign = 64; LongDoubleFormat = &llvm::APFloat::IEEEdouble(); - break; - default: - break; } // PPC32 supports atomics up to 4 bytes. @@ -386,19 +379,13 @@ ABI = Triple.getEnvironment() == llvm::Triple::ELFv2 ? "elfv2" : "elfv1"; } - switch (Triple.getOS()) { - case llvm::Triple::FreeBSD: - LongDoubleWidth = LongDoubleAlign = 64; - LongDoubleFormat = &llvm::APFloat::IEEEdouble(); - break; - case llvm::Triple::AIX: - // FIXME: -mlong-double-128 is not yet supported on AIX. + if (Triple.getOS() == llvm::Triple::AIX) + SuitableAlign = 64; + + if (Triple.isOSFreeBSD() || Triple.getOS() == llvm::Triple::AIX || + Triple.isMusl()) { LongDoubleWidth = LongDoubleAlign = 64; LongDoubleFormat = &llvm::APFloat::IEEEdouble(); - SuitableAlign = 64; - break; - default: - break; } // PPC64 supports atomics up to 8 bytes. Index: cfe/trunk/lib/Driver/ToolChains/Clang.cpp =================================================================== --- cfe/trunk/lib/Driver/ToolChains/Clang.cpp +++ cfe/trunk/lib/Driver/ToolChains/Clang.cpp @@ -4001,6 +4001,17 @@ RenderFloatingPointOptions(TC, D, OFastEnabled, Args, CmdArgs); + if (Arg *A = Args.getLastArg(options::OPT_mlong_double_64)) { + if (TC.getArch() == llvm::Triple::x86 || + TC.getArch() == llvm::Triple::x86_64 || + TC.getArch() == llvm::Triple::ppc || TC.getTriple().isPPC64()) { + CmdArgs.push_back("-mlong-double-64"); + } else { + D.Diag(diag::err_drv_unsupported_opt_for_target) + << A->getAsString(Args) << TripleStr; + } + } + // Decide whether to use verbose asm. Verbose assembly is the default on // toolchains which have the integrated assembler on by default. bool IsIntegratedAssemblerDefault = TC.IsIntegratedAssemblerDefault(); Index: cfe/trunk/lib/Frontend/CompilerInvocation.cpp =================================================================== --- cfe/trunk/lib/Frontend/CompilerInvocation.cpp +++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp @@ -2742,6 +2742,7 @@ Opts.PackStruct = getLastArgIntValue(Args, OPT_fpack_struct_EQ, 0, Diags); Opts.MaxTypeAlign = getLastArgIntValue(Args, OPT_fmax_type_align_EQ, 0, Diags); Opts.AlignDouble = Args.hasArg(OPT_malign_double); + Opts.LongDoubleSize = Args.hasArg(OPT_mlong_double_64) ? 64 : 0; Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags); Opts.ROPI = Args.hasArg(OPT_fropi); Opts.RWPI = Args.hasArg(OPT_frwpi); Index: cfe/trunk/test/CodeGen/long-double-x86.c =================================================================== --- cfe/trunk/test/CodeGen/long-double-x86.c +++ cfe/trunk/test/CodeGen/long-double-x86.c @@ -1,4 +0,0 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686-apple-darwin9 | grep x86_fp80 - -long double x = 0; -int checksize[sizeof(x) == 16 ? 1 : -1]; Index: cfe/trunk/test/CodeGen/ppc64-align-long-double.c =================================================================== --- cfe/trunk/test/CodeGen/ppc64-align-long-double.c +++ cfe/trunk/test/CodeGen/ppc64-align-long-double.c @@ -1,16 +0,0 @@ -// REQUIRES: powerpc-registered-target -// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s - -struct S { - double a; - long double b; -}; - -// CHECK: %struct.{{[a-zA-Z0-9]+}} = type { double, ppc_fp128 } - -long double test (struct S x) -{ - return x.b; -} - -// CHECK: %{{[0-9]}} = load ppc_fp128, ppc_fp128* %{{[a-zA-Z0-9]+}}, align 16 Index: cfe/trunk/test/CodeGen/ppc64-long-double.cpp =================================================================== --- cfe/trunk/test/CodeGen/ppc64-long-double.cpp +++ cfe/trunk/test/CodeGen/ppc64-long-double.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple powerpc64-linux-musl -emit-llvm -o - %s | \ +// RUN: FileCheck --check-prefix=FP64 %s +// RUN: %clang_cc1 -triple powerpc64-linux-gnu -emit-llvm -o - %s -mlong-double-64 | \ +// RUN: FileCheck --check-prefix=FP64 %s +// RUN: %clang_cc1 -triple powerpc64-linux-gnu -emit-llvm -o - %s | \ +// RUN: FileCheck --check-prefix=IBM128 %s + +long double x = 0; +int size = sizeof(x); + +// FP64: @x = global double {{.*}}, align 8 +// FP64: @size = global i32 8 +// 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) +// IBM128: ppc_fp128 @_Z3foog(ppc_fp128 %d) Index: cfe/trunk/test/CodeGen/x86-long-double.cpp =================================================================== --- cfe/trunk/test/CodeGen/x86-long-double.cpp +++ cfe/trunk/test/CodeGen/x86-long-double.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686 | \ +// RUN: FileCheck --check-prefixes=FP80,FP80-ELF32 %s +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686-apple-darwin | \ +// RUN: FileCheck --check-prefixes=FP80,FP80-DARWIN %s +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64 | \ +// RUN: FileCheck --check-prefixes=FP80,FP80-ELF64 %s +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin | \ +// RUN: FileCheck --check-prefixes=FP80,FP80-DARWIN %s + +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686 -mlong-double-64 | \ +// RUN: FileCheck --check-prefixes=FP64,FP64-X32 %s +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686-apple-darwin -mlong-double-64 | \ +// RUN: FileCheck --check-prefixes=FP64,FP64-X32 %s +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64 -mlong-double-64 | \ +// RUN: FileCheck --check-prefixes=FP64,FP64-X64 %s +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64-apple-darwin -mlong-double-64 | \ +// RUN: FileCheck --check-prefixes=FP64,FP64-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 \ +// RUN: -malign-double | FileCheck --check-prefixes=FP64,FP64-X64 %s +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=x86_64 -mlong-double-64 \ +// RUN: -malign-double | FileCheck --check-prefixes=FP64,FP64-X64 %s + +long double x = 0; +int size = sizeof(x); + +// FP80-ELF32: @x = global x86_fp80 {{.*}}, align 4 +// FP80-ELF32: @size = global i32 12 +// FP80-ELF64: @x = global x86_fp80 {{.*}}, align 16 +// FP80-ELF64: @size = global i32 16 +// FP80-DARWIN: @x = global x86_fp80 {{.*}}, align 16 +// FP80-DARWIN: @size = global i32 16 + +// FP64-X32: @x = global double {{.*}}, align 4 +// FP64-X32: @size = global i32 8 +// FP64-X64: @x = global double {{.*}}, align 8 +// FP64-X64: @size = global i32 8 + +long double foo(long double d) { return d; } + +// FP64: double @_Z3fooe(double %d) +// FP80: x86_fp80 @_Z3fooe(x86_fp80 %d) Index: cfe/trunk/test/Driver/mlong-double-64.c =================================================================== --- cfe/trunk/test/Driver/mlong-double-64.c +++ cfe/trunk/test/Driver/mlong-double-64.c @@ -0,0 +1,11 @@ +// RUN: %clang -target powerpc-linux-musl -c -### %s -mlong-double-64 2>&1 | FileCheck %s +// RUN: %clang -target powerpc64-pc-freebsd12 -c -### %s -mlong-double-64 2>&1 | FileCheck %s +// RUN: %clang -target powerpc64le-linux-musl -c -### %s -mlong-double-64 2>&1 | FileCheck %s +// RUN: %clang -target i686-linux-gnu -c -### %s -mlong-double-64 2>&1 | FileCheck %s +// RUN: %clang -target x86_64-linux-musl -c -### %s -mlong-double-64 2>&1 | FileCheck %s + +// CHECK: "-mlong-double-64" + +// RUN: %clang -target aarch64 -c -### %s -mlong-double-64 2>&1 | FileCheck --check-prefix=ERR %s + +// ERR: error: unsupported option '-mlong-double-64' for target 'aarch64'