diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 53b87b73756894..4ba8c766269c2c 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -176,6 +176,7 @@ VALUE_LANGOPT(PackStruct , 32, 0, 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(DoubleSize , 32, 0, "width of double") 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") diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index bdcd771ff713b9..3a4830c8448311 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2179,6 +2179,8 @@ def mbranches_within_32B_boundaries : Flag<["-"], "mbranches-within-32B-boundari 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 mdouble_EQ : Joined<["-"], "mdouble=">, Group, Values<"32,64">, Flags<[CC1Option]>, + HelpText<"Force double to be 32 bits or 64 bits">; def LongDouble_Group : OptionGroup<"">, Group, DocName<"Long double flags">, DocBrief<[{Selects the long double implementation}]>; diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp index 58d018c5bd3e22..2330339bedfb2a 100644 --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -380,6 +380,20 @@ void TargetInfo::adjust(LangOptions &Opts) { LongDoubleFormat = &llvm::APFloat::IEEEquad(); } + if (Opts.DoubleSize) { + if (Opts.DoubleSize == 32) { + DoubleWidth = 32; + LongDoubleWidth = 32; + DoubleFormat = &llvm::APFloat::IEEEsingle(); + LongDoubleFormat = &llvm::APFloat::IEEEsingle(); + } else if (Opts.DoubleSize == 64) { + DoubleWidth = 64; + LongDoubleWidth = 64; + DoubleFormat = &llvm::APFloat::IEEEdouble(); + LongDoubleFormat = &llvm::APFloat::IEEEdouble(); + } + } + if (Opts.LongDoubleSize) { if (Opts.LongDoubleSize == DoubleWidth) { LongDoubleWidth = DoubleWidth; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index cb993e75b88cf3..1193dde5a67934 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4580,6 +4580,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, RenderFloatingPointOptions(TC, D, OFastEnabled, Args, CmdArgs, JA.getOffloadingDeviceKind()); + if (Arg *A = Args.getLastArg(options::OPT_mdouble_EQ)) { + if (TC.getArch() == llvm::Triple::avr) + A->render(Args, CmdArgs); + else + D.Diag(diag::err_drv_unsupported_opt_for_target) + << A->getAsString(Args) << TripleStr; + } + if (Arg *A = Args.getLastArg(options::OPT_LongDouble_Group)) { if (TC.getTriple().isX86()) A->render(Args, CmdArgs); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 08a0b9831e0c65..e2b24f0cfcea1d 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2937,6 +2937,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, 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.DoubleSize = getLastArgIntValue(Args, OPT_mdouble_EQ, 0, Diags); Opts.LongDoubleSize = Args.hasArg(OPT_mlong_double_128) ? 128 : Args.hasArg(OPT_mlong_double_64) ? 64 : 0; diff --git a/clang/test/CodeGen/mdouble.c b/clang/test/CodeGen/mdouble.c new file mode 100644 index 00000000000000..8399919f702574 --- /dev/null +++ b/clang/test/CodeGen/mdouble.c @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=avr-unknown-unknown -mdouble=64 | \ +// RUN: FileCheck --check-prefix=AVR-FP64 %s +// RUN: %clang_cc1 %s -emit-llvm -o - -triple=avr-unknown-unknown -mdouble=32 | \ +// RUN: FileCheck --check-prefix=AVR-FP32 %s + +double x = 0; +int size = sizeof(x); + +// FIXME: the double should have an alignment of 1 on AVR, not 4 or 8. +// AVR-FP64: @x = global double {{.*}}, align 8 +// AVR-FP64: @size = global i16 8 +// AVR-FP32: @x = global float {{.*}}, align 4 +// AVR-FP32: @size = global i16 4 diff --git a/clang/test/Driver/mdouble.c b/clang/test/Driver/mdouble.c new file mode 100644 index 00000000000000..408d907053163c --- /dev/null +++ b/clang/test/Driver/mdouble.c @@ -0,0 +1,7 @@ +// RUN: %clang -target avr -c -### %s -mdouble=64 2>&1 | FileCheck %s + +// CHECK: "-mdouble=64" + +// RUN: %clang -target aarch64 -c -### %s -mdouble=64 2>&1 | FileCheck --check-prefix=ERR %s + +// ERR: error: unsupported option '-mdouble=64' for target 'aarch64'